ARMWSD
便利機能
「続きを読む」機能は便利です~
avr-gcc で工作(その9)
回路図はこちら → g:ecrafts:id:Chuck:20040919#p1
ロータリエンコーダの制御のソフトウェアを記述してみました。timer1 で 1msec ごとに割り込んで、ロータリエンコーダの信号線が接続されているポート(PD3, PD4) を監視します。PD3の信号の変化を見て、真の立下りエッジかノイズか判断した上で*1PD4の信号を見に行って、ロータリエンコーダの正回転(時計回り)、逆回転(反時計回り)を判別しています。正転なら7セグメントLEDに表示させる値をインクリメントして、逆転ならデクリメントです。
以下ソースコード
/* 7-seg. LED w/ Rotary Encoder */ #include#include #include #include enum { LOW, HIGH, EDGE } ; volatile uint8_t num = 128; uint8_t DIGIT[] = { 0x03, 0x9F, 0x25, 0x0D, 0x99, 0x49, 0x41, 0x1B, 0x01, 0x09 }; volatile uint8_t renc = HIGH; /* PB5 serial data PB6 latch clock PB7 shift clock */ void send7seg (uint8_t dat) { int i; for (i = 0; i < 8; i++, dat >>= 1) { if (dat & 0x01) sbi(PORTB, PB5); else cbi(PORTB, PB5); sbi(PORTB, PB7); cbi(PORTB, PB7); } } void load7seg (void) { sbi(PORTB, PB6); cbi(PORTB, PB6); } void send (uint8_t dat) { send7seg(DIGIT[dat % 10] & 0xFE); send7seg(DIGIT[(dat/10) % 10]); send7seg(DIGIT[dat / 100]); load7seg(); } SIGNAL (SIG_OVERFLOW1) { TCNT1 = 65536 - 1000 + 1; if (renc == EDGE) { if (bit_is_clear(PIND, PD3)) { // true falling edge renc = LOW; if (bit_is_clear(PIND, PD4)) num++; else num--; send(num); } else { renc = HIGH; // noise... } } else { if (bit_is_clear(PIND, PD3)) { if (renc == HIGH) renc = EDGE; else renc = LOW; } else { renc = HIGH; } } } void ioinit (void) { DDRA = _BV (PA0); DDRB = _BV (PB5) | _BV (PB6) | _BV (PB7); TCCR1B = _BV (CS11); TCNT1 = 65536 - 1000; timer_enable_int (_BV (TOIE1)); sei(); } int main(void) { ioinit(); cbi(PORTA, PA0); send(num); for (;;) ; return 0; } /* a b c d e f g p 1 1 1 1 1 1 1 1 -> 0xFF 0 0 0 0 0 0 0 1 1 -> 0x03 1 1 0 0 1 1 1 1 1 -> 0x9F 2 0 0 1 0 0 1 0 1 -> 0x25 3 0 0 0 0 1 1 0 1 -> 0x0D 4 1 0 0 1 1 0 0 1 -> 0x99 5 0 1 0 0 1 0 0 1 -> 0x49 6 0 1 0 0 0 0 0 1 -> 0x41 7 0 0 0 1 1 0 1 1 -> 0x1B 8 0 0 0 0 0 0 0 1 -> 0x01 9 0 0 0 0 1 0 0 1 -> 0x09 . 1 1 1 1 1 1 1 0 -> 0xFE */
*1:当然ノイズだったら状態を戻してスキップです。