AVR入門(2)

Charlieplexingという方法を知ったので試してみた。
詳しい解説はWikipediaにあるので、それを参照してもらうことにして、
LEDを点灯するにはアノードをHIGH,カソードをLOWにすればよく、逆では点灯しないという単純なことが原理です。
マイコンの2本のピン1,2それぞれにLED1,2を並列に逆向きで接続したとします。(図はwikipediaから拝借)

PIN1,2をOUTPUTにしたとき、それぞれの状態によって

PIN2 PIN1 LED1 LED2
LOW LOW OFF OFF
LOW HIGH ON OFF
HIGH LOW OFF ON
HIGH HIGH OFF OFF

となることがわかります。
3本以上使う場合も一度に点灯するLEDは1つとして、使わない他のピンは接続しないというのがミソです。
これはAVRではDDRxを0(入力)にして、PORTxを1にするとHigh-Zで実現できます。
信号が3本の場合は3本のうち2本を選び、向きが正逆の2通りなので6個のLEDが点灯でき、
更にN本に一般化すれば、N個から2個取る組み合わせの2倍でN*(N-1)本のLEDを点灯できることがわかります。
ATtiny13では通常5本のピンが使えるので20個のLEDをドライブできることになりますが、
配線が面倒なのと原理さえわかればいいので、トリビアルでない最小のN=3の場合をやってみます。

LED1を点灯するにはPin1=H, Pin2=L, Pin3=High-Zとすればよく、
PIN1,2,3をそれぞれPB0,PB1,PB2に接続した場合は

DDRB=0b00000011;
PORTB=0b00000101;

とすればよいわけです。そこでナイトライダー的な点灯コードを書いてみました。

/*
  charlieplexing LED
  controling 6LEDs with 3 pins
  ATtiny13A
 */

#include <avr/io.h>
#include <util/delay.h>

int pat[10] = {0,1,2,3,4,5,4,3,2,1};

uint8_t ddrb[6] = {
  0b00000011,
  0b00000011,
  0b00000110,
  0b00000110,
  0b00000101,
  0b00000101,
};

uint8_t portb[6] = {
  0b00000101,
  0b00000110,
  0b00000011,
  0b00000101,
  0b00000110,
  0b00000011,
};
int main(void)
{
  int i;

  while(1){
    for (i=0; i<10; i++) {
      DDRB = ddrb[pat[i]];
      PORTB = portb[pat[i]];
      _delay_ms(50);
    }
  }
  return 0;
}

カテゴリー: AVR

コメントを残す

カテゴリー
2010年8月
 1
2345678
9101112131415
16171819202122
23242526272829
3031