電音の工場ブログ

趣味の電子工作を中心としたブログです.音モノの工作が多いです.

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:当然ノイズだったら状態を戻してスキップです。