AVRマイコンのポートで7セグLEDを表示する(ATtiny2313)

7seg-twenty-four-title
『24 -TWENTY FOUR-』
ジャックバウアーに夢中になりました。私的に一番面白かったのはシーズン1です。仕事をやっていると、一時間なんてあっという間に過ぎてしまいますが、ジャックバウアーの時間の使い方って上手いですよね。24時間でたいていのことは解決しますからね。
電子工作を始めたら、いつか7セグLEDで『24 -TWENTY FOUR-』のオープニングを作ってみようと思っていましたが、意外と簡単でした。まあそっくりそのままではなく、なんちゃって、です。音もないし。
A-3880EGの時と同じく、AVRのポートをふんだんに使っています。もったいないですねえ。
各ピン配はこのとおりです。

                 ATtiny2313
                +-----------+
               -|1        20|- VCC
 II-5 <--- PD0 -|2        19|- PB7 ---> II-6
 II-4 <--- PD1 -|3        18|- PB6 ---> II-7
 II-2 <--- PA1 -|4        17|- PB5 ---> II-9
 II-1 <--- PA0 -|5        16|- PB4 ---> II-10
  I-5 <--- PD2 -|6        15|- PB3 ---> I-6
  I-4 <--- PD3 -|7        14|- PB2 ---> I-7
  I-2 <--- PD4 -|8        13|- PB1 ---> I-9
  I-1 <--- PD5 -|9        12|- PB0 ---> I-10
           GND -|10       11|-
                +-----------+
 
7SEG(Cathode common)      7SEG(Cathode common)
        (I)                      (II)
   10 9  8  7  6             10 9  8  7  6
   |  |  |  |  |             |  |  |  |  |
  +-------------+           +-------------+
  |G  F cmn A  B|           |G  F cmn A  B|
  |             |           |             |
  |  +---A---+  |           |  +---A---+  |
  |  |       |  |           |  |       |  |
  |  F       B  |           |  F       B  |
  |  |       |  |           |  |       |  |
  |  +---G---+  |           |  +---G---+  |
  |  |       |  |           |  |       |  |
  |  E       C  |           |  E       C  |
  |  |       |  |           |  |       |  |
  |  +---D---+  |           |  +---D---+  |
  |          DP |           |          DP |
  |             |           |             |
  |E  D cmn C DP|           |E  D cmn C DP|
  +-------------+           +-------------+
   |  |  |  |  |             |  |  |  |  |
   1  2  3  4  5             1  2  3  4  5

ブレッドボードを使って配線したら以下のようになりました。
7seg-twenty-four-001

以下にソースを貼ってあります。
変わったところといえば、4行目からの文字列でしょうか。7セグLEDのピン配置と合わせるために、エスケープシーケンスを使っています。
数字の1の表示なら、ピン番号4と6なので、”\x4\x6″としています。
で、これを使うのが、61行目の

p = digit[num / 10];

なんですが、

while(pin=*p++)

で回して、文字列の最後、つまりNULLを見つけたら抜けるようになっています。
ただ、エスケープシーケンスは見難いので、

“46”

としておいて、

while(pin=*p++ – ‘0’)

としても良いかもしれません。

全文です。

~$ cat -n hello.c
     #include <avr/io.h>
     #include <util/delay.h>
     
     4  char *digit[] ={
     5      /* 0 */ "\x7\x6\x4\x2\x1\x9",
     6      /* 1 */ "\x4\x6",
     7      /* 2 */ "\x7\x6\xA\x1\x2",
     8      /* 3 */ "\x7\x6\xA\x4\x2",
     9      /* 4 */ "\x9\xA\x6\x4",
    10      /* 5 */ "\x9\xA\x7\x4\x2",
    11      /* 6 */ "\x7\x9\xA\x4\x2\x1",
    12      /* 7 */ "\x7\x9\x6\x4",
    13      /* 8 */ "\x7\x6\x4\x2\x1\x9\xA",
    14      /* 9 */ "\xA\x7\x9\x6\x4",
    15  };
    16 
    17  void anode(int sel, int pin)
    18  {
    19      switch(sel){
    20      case    1:  // 7SEG (I)
    21          switch(pin){
    22          case    1: PORTD |= 0b00100000;break;
    23          case    2: PORTD |= 0b00010000;break;
    24          case    4: PORTD |= 0b00001000;break;
    25          case    5: PORTD |= 0b00000100;break;
    26          case    6: PORTB |= 0b00001000;break;
    27          case    7: PORTB |= 0b00000100;break;
    28          case    9: PORTB |= 0b00000010;break;
    29          default:   PORTB |= 0b00000001;break;
    30          }
    31          break;
    32      case    2:  // 7SEG (II)
    33          switch(pin){
    34          case    1: PORTA |= 0b00000001;break;
    35          case    2: PORTA |= 0b00000010;break;
    36          case    4: PORTD |= 0b00000010;break;
    37          case    5: PORTD |= 0b00000001;break;
    38          case    6: PORTB |= 0b10000000;break;
    39          case    7: PORTB |= 0b01000000;break;
    40          case    9: PORTB |= 0b00100000;break;
    41          default:   PORTB |= 0b00010000;break;
    42          }
    43          break;
    44      }
    45  }
    46 
    47  void clear()
    48  {
    49      PORTB &= ~0b11111111;
    50      PORTD &= ~0b00111111;
    51      PORTA &= ~0b00000011;
    52  }
    53 
    54  void disp(int num)
    55  {
    56      int pin;
    57      char* p;
    58 
    59      clear();
    60 
    61      p = digit[num / 10];
    62      while(pin=*p++)
    63          anode(1,pin);
    64 
    65      p = digit[num % 10];
    66      while(pin=*p++)
    67          anode(2,pin);
    68  }
    69 
    70  int main()
    71  {
    72      DDRB = 0b11111111;      //ATtiny2313 pin.12-19 PB0-7 OUT
    73      DDRD = 0b00111111;      //ATtiny2313 pin.2,3,6-9 PD0-5 OUT
    74      DDRA = 0b00111111;      //ATtiny2313 pin.4,5 PA0-1 OUT
    75 
    76      //twenty-four logic
    77      {
    78          int i,j,wait,sel,pin;
    79 
    80          for(i=0;i<30;i+=5){
    81          for(j=0;j<5;j++){
    82              for(sel=1;sel<=2;sel++){
    83                  for(pin=1;pin<=9;pin++){
    84                      clear();
    85                      anode(sel,pin);
    86                      for(wait=1;wait<=(29-i);wait++){
    87                          _delay_ms(1);
    88                      }
    89                  }  
    90              }
    91          }
    92          }
    93      }
    94 
    95      disp(24);
    96 
    97      while(1)
    98          ;
    99 
   100      return 0;
   101  }

このように表示されます。
7seg-twenty-four-002
くるくる回って、だんだんと早くなり、(写真だと全部光っているように見えます)
最後にこうなります。
7seg-twenty-four-003

コメント

タイトルとURLをコピーしました