#define F_CPU 1000000L /* システムクロック=1 MHz(内蔵RC発振) */ #define COM_MAX 3 /* LEDのcommon端子の数 */ #define CALIB_REAL_MV 5080L /* リアル校正電圧[mV] */ #define CALIB_ADC_MV 2570L /* ADC校正電圧[mV](リアル校正電圧の約半分で入ってくる) */ #define LED_REFRESH_MS 15 /* LEDのリフレッシュレート[ms] */ #define LUMINOUS_PERSENT 30 /* LED輝度[%] */ #define ADC_REFRESH_MS 200 /* ADCの更新周期[ms] */ #define ADC_REFRESH (ADC_REFRESH_MS / LED_REFRESH_MS) /* ADCの更新周期[LEDリフレッシュ回数] */ #define COM_SWITCH_MS (LED_REFRESH_MS / COM_MAX) /* COM端子1本当たりの時間[ms] */ #define LED_ON_MS (COM_SWITCH_MS * LUMINOUS_PERSENT / 100) /* LEDがONしている時間[ms] */ #define LED_OFF_MS (COM_SWITCH_MS - LED_ON_MS) /* LEDがOFFしている時間[ms] */ #include #include #include #include #include #include // // Globals // uint16_t CurVolt; uint8_t SegRAM[3]; uint8_t CurCom = 0; /* Current COM Number 0, 1, 2, 0, 1, 2, ... */ uint8_t SegFont[10] PROGMEM = { //_abcdefg 0b10000001, /* 0 */ 0b11001111, /* 1 */ 0b10010010, /* 2 */ 0b10000110, /* 3 */ 0b11001100, /* 4 */ 0b10100100, /* 5 */ 0b10100000, /* 6 */ 0b10001101, /* 7 */ 0b10000000, /* 8 */ 0b10000100, /* 9 */ }; // // Prototypes // void wdt_off(void); void init_io(void); void adc_cont_start(void); void put_digit(void); void print_volt(void); // // MAIN LOOP // int main(void) { wdt_off(); /* ウォッチドッグタイマーをOFF */ init_io(); /* I/Oの初期化 */ adc_cont_start(); /* ADCを連続変換モードでスタート */ uint8_t adcref = 0; /* ADCのリフレッシュカウンタ */ while(1) { if (adcref == 0 && (ADCSR & _BV(ADIF))) { ADCSR |= _BV(ADIF); /* ADCの読み込み */ CurVolt = ADCW; /* 現在電圧の更新 */ } print_volt(); /* 電圧の表示 */ if (++CurCom >= COM_MAX) { /* 各カウンタの回転 */ CurCom = 0; if (++adcref >= ADC_REFRESH) adcref = 0; } _delay_ms(LED_ON_MS); /* 輝度調整:ONの時間 */ PORTB |= 0b00111000; /* 全消灯 */ _delay_ms(LED_OFF_MS); /* 輝度調整:OFFの時間 */ } return 0; } // // Functions // void wdt_off(void) { cli(); wdt_reset(); MCUSR &= ~(1 << WDRF); WDTCR |= (1 << WDCE) | (1 << WDE); WDTCR = 0x00; //sei(); } void init_io(void) { PORTA = 0xff; DDRA = 0xff; PORTB = 0b10111111; DDRB = 0b00111000; ADMUX = 0x29; /* REFS[1:0]/ADLAR/MUX[4:0] = 00101001 */ /* AVCCピン基準電圧、左揃え、シングルエンドCH9 */ ADCSR = 0x87; /* ADEN/ADSC/ADATE/ADIF/ADIE/ADPS[2:0] = 10000111 */ /* 完了割り込み禁止、クロック128分周 */ } void adc_cont_start(void) { ADCSR |= _BV(ADSC) + _BV(ADFR); } void put_digit(void) { uint8_t pb, pa; pb = PORTB | 0b00111000; pb &= ~(0b00001000 << CurCom); pa = SegRAM[CurCom]; PORTB = pb; /* COM端子のスイッチ */ PORTA = pa; /* フォントパターンの出力 */ } void print_volt(void) { uint32_t r; uint16_t p; if (CurCom == 0) { r = CurVolt; //r = r * VCC_MV / 1000; r = r * (CALIB_REAL_MV * CALIB_REAL_MV / CALIB_ADC_MV) / 1000L; p = r >> 16; if (p > 9) p = 9; SegRAM[0] = pgm_read_byte(&SegFont[p]) & 0b01111111; /* 最上位桁+小数点 */ r -= p * 65536L; r *= 10; p = r >> 16; SegRAM[1] = pgm_read_byte(&SegFont[p]); /* 中位桁 */ r -= p * 65536L; r *= 10; p = r >> 16; SegRAM[2] = pgm_read_byte(&SegFont[p]); /* 最下位桁 */ // r -= p * 65536L; // r *= 10; } put_digit(); /* SegRAM[]の内容(フォントパターン)で表示 */ }