/****************************/ /* A/D読み出しテスト */ /****************************/ // AD0~3につないだ4つのVR値を読み出す // Arduino UNOで // ピン割り当て // PD0 RXD in RXD // PD1 TXD out TXD // PD2 IO2 out // PD3 IO3 out // PD4 IO4 out // PD5 IO5 out // PD6 IO6 out // PD7 IO7 out // PB0 IO8 out // PB1 IO9 out // PB2 IO10 out (!!!) test pulse // PB3 IO11 out (!!!) test pulse // PB4 IO12 out (!!!) test pulse // PB5 IO13 out LED // PC0 AD0 in VR1 // PC1 AD1 in VR2 // PC2 AD2 in VR3 // PC3 AD3 in VR4 // PC4 AD4 in pullup SW1 // PC5 AD5 in pullup SW2 // タイマー0 操作せず // タイマー1 OC1Aコンぺエマッチ割込 // タイマー2 1mSタイマー割込 /***** マクロ *****/ #define DIMSIZ(a) (sizeof(a)/sizeof(*a)) // 配列のデータ数を返す /***** I/Oポート制御 *****/ #define INP_SW1 ((~PINC) & (1 << PC4)) // SW1 (Lでon) #define INP_SW2 ((~PINC) & (1 << PC5)) // SW2 (Lでon) // テスト用 #define PB2_H (PORTB |= (1 << PB2)) // (!!!)PB2 H/L #define PB2_L (PORTB &= ~(1 << PB2)) #define PB3_H (PORTB |= (1 << PB3)) // (!!!)PB3 H/L #define PB3_L (PORTB &= ~(1 << PB3)) #define PB4_H (PORTB |= (1 << PB4)) // (!!!)PB4 H/L #define PB4_L (PORTB &= ~(1 << PB4)) #define LED_ON (PORTB |= (1 << PB5)) // (!!!)PB5 LED on/off #define LED_OFF (PORTB &= ~(1 << PB5)) #define LED_X (PINB |= (1 << PB5)) // LEDトグル /***** シリアル出力用文字バッファ *****/ char tx_bff[40]; // sprintf出力用 /********************************/ /* タイマー2割込み */ /********************************/ /***** タイマーデータ *****/ volatile byte f_1ms; // 1msありフラグ volatile byte tm_1ms; // 1msダウンカウントタイマー // max 255ms /***** タイマー2 1kHz割り込み *****/ // 1msサイクル ISR(TIMER2_COMPA_vect) { PB2_H; // (!!!) ADCSRA |= (1 << ADSC); // A/D変換開始 // タイマー f_1ms = 1; // 1msあり if(tm_1ms) tm_1ms--; // 1msダウンカウントタイマー PB2_L; // (!!!) } /*****************************/ /* A/D入力処理 */ /*****************************/ /***** A/Dデータ *****/ // A/D ch0~3:VR1~VR4 // 割り込みに関係なく読めるよう8bitで処理 volatile byte ad_avr[4]; // AD0~3 VR1~VR4がつながる // 平均値 0~255 // 平均計算 volatile word ad_add[4]; // 平均用加算値 // 64回加算 1023*64 = 65472 volatile byte ad_ch; // A/D変換チャンネル 0,1,2,3 volatile byte ad_cnt; // A/D変換平均回数 (64回) volatile byte f_adok; // 平均値確定フラグ // 256msごとに確定 // マルチプレックスデータ const byte PROGMEM ad_mpx[] = { // MPX指定 0b01000000, // 0 A/D ch0 0b01000001, // 1 ch1 0b01000010, // 2 ch2 0b01000011, // 3 ch3 // ||| ++++------- ADC MPX // ||+------------ ADLAR // ++------------- AVCC接続 }; /***** A/D割り込み処理 *****/ // タイマー割り込みでA/D変換開始 // 64回平均*4chで256msでデータが確定 // 1023*64=65472で16bitに入る ISR(ADC_vect) { word d; PB3_H; // (!!!) ad_add[ad_ch] += ADC; // 平均用に加算 // 平均処理 1chごとに処理 if(ad_cnt == 63){ // 63回目? d = ad_add[ad_ch] / 64; // 平均値 10bit ad_avr[ad_ch] = d / 4; // 8bitにして保存 ad_add[ad_ch] = 0; // 次加算データクリア } // 次ch ad_ch++; // 次ch if(ad_ch >= 4){ // 4ch終了 ad_ch = 0; // ch0に戻す ad_cnt++; // 平均加算回数 if(ad_cnt >= 64){ // 64回? ad_cnt = 0; f_adok = 1; // A/Dデータ確定 } } ADMUX = pgm_read_byte(&ad_mpx[ad_ch]); // MPX ch PB3_L; // (!!!) } /************************************/ /* タイマー1割込み */ /************************************/ /***** タイマー1コンペアマッチA割込み *****/ // プリスケーラ後のクロックは250kHz 4uS ISR(TIMER1_COMPA_vect) { PB4_H; // (!!!)PB4 H PB4_L; // (!!!)PB4 L } /******************************/ /* セットアップ */ /******************************/ /***** セットアップ *****/ // ATmega328Pのレジスタを直接制御 void setup() { cli(); // 割り込み禁止 // I/Oイニシャル PORTB = 0b00000000; // data/pull up DDRB = 0b00111111; // port指定 // |||||+---- PB0 IO8 out // ||||+----- PB1 IO9 out // |||+------ PB2 IO10 out test // ||+------- PB3 IO11 out test // |+-------- PB4 IO12 out test // +--------- PB5 IO13 out LED PORTC = 0b00110000; // data/pull up DDRC = 0b00000000; // |||||+---- PC0 AD0 in VR1 // ||||+----- PC1 AD1 in VR2 // |||+------ PC2 AD2 in VR3 // ||+------- PC3 AD3 in VR4 // |+-------- PC4 AD4 in SW1 pull up // +--------- PC5 AD5 in SW2 pull up PORTD = 0b00000011; // data/pull up DDRD = 0b11111110; // |||||||+---- PD0 RXD in // ||||||+----- PD1 TXD out // |||||+------ PD2 IO2 out // ||||+------- PD3 IO3 out // |||+-------- PD4 IO4 out // ||+--------- PD5 IO5 out // |+---------- PD6 IO6 out // +----------- PD7 IO7 out // タイマー1,OCR1Aコンペアマッチ TIMSK1 = 0b00000010; // | ||+--- TOIE1 // | |+---- OCIE1A 割込on // | +----- OCIE1B // +-------- ICIE1 TCCR1A = 0b00000000; // |||| ++--- WGM // ||++------- COM1B // ++--------- COM1A TCCR1B = 0b00001011; // || ||+++--- CS 1/64 4uS // || ++------ WGM CTC OCR1A // |+--------- ICES1 // |---------- ICNC1 OCR1A = 250 - 1; // 1mSで割込 // タイマー2 1mSタイマー割り込み TCCR2A = 0b00000010; // |||| ++--- CTC動作 // ||++------- OCR2B // ++--------- OCR2A TCCR2B = 0b00000100; // || |++++-- CS 1/64 250kHz // || +------ WGM22 // ++--------- FOC2 OCR2A = 250 - 1; // 1kHz TIMSK2 = 0b00000010; // ||+--- TOIE2 // |+---- OCIE2A 割込on // +----- OCIE2B // A/D割り込み DIDR0 = 0b00001111; // AD0~3 デジタル入力禁止 ADMUX = 0b01000000; // Vref=AVCC,MPX ch0 // ||| ++++---- ADC0 // ||+--------- ADLAR // ++---------- AVCC接続 ADCSRA = 0b10001111; // 125kHz,割込あり // |||||+++---- ADPS // ||||+------- ADIE A/D割り込み有効 // |||+-------- ADIF // ||+--------- ADATE // |+---------- ADSC // +----------- ADEN A/D許可 sei(); // 割り込み有効 // シリアル Serial.begin(9600); // シリアル通信 } /******************************/ /* ループ */ /******************************/ /***** LOOP *****/ void loop() { tm_1ms = 255; while(tm_1ms); Serial.println(F("A/D 8bit:VR1,2,3,4 SW1,2")); // LOOP while(1){ if(f_adok){ LED_X; // LED点滅 f_adok = 0; sprintf(tx_bff, "%3d %3d %3d %3d %d %d", ad_avr[0], ad_avr[1], ad_avr[2], ad_avr[3], INP_SW1 ? 1 : 0, INP_SW2 ? 1 : 0); Serial.println(tx_bff); } } } /*==== end of "ad_vr4.ino" ====*/