
前回「AVRからPORT制御のLCDを使う(ATtiny2313,TC1602E-13A)」で、8BITモードで使用したキャラクタLCDですが、今回は4BITモードで使います。
いつものごとく、横着な接続図。
ATtiny2313
+-----------+
-|1 20|- VCC
-|2 19|-
-|3 18|-
-|4 17|- PB5 ---> E
-|5 16|- PB4 ---> RS
-|6 15|- PB3 ---> DB3
-|7 14|- PB2 ---> DB2
-|8 13|- PB1 ---> DB1
-|9 12|- PB0 ---> DB0
GND -|10 11|-
+-----------+
TC1602E-13A
(Connector)
+-----------+
PB7 <--- DB7 -|14 13|- DB5 ---> PB5
PB5 <--- DB5 -|12 11|- DB4 ---> PB4
nc <--- DB3 -|10 9|- DB2 ---> nc
nc <--- DB1 -|8 7|- DB0 ---> nc
PD2 <--- E -|6 5|- R/W ---> GND
PD0 <--- RS -|4 3|- Vo
VSS -|2 1|- VDD
+-----------+
TC1602E-13Aの必要なピンとしては、
DB7〜4、E、RS、R/W
ですが、R/Wは、ライトしか使わないので、GNDに落としました。
前回使った時は、PORTDの2番ピンをEに割り当てており、Eのパルスを作るのに、このようにやっていました。
PORTD = 0b00000100; //E(PD2)=H
_delay_us(1);
PORTD = 0b00000000; //E(PD2)=L
本来はこうでしょうか。
PORTD |= 0b00000100; //E(PD2)=H
_delay_us(1);
PORTD &= ~0b00000100; //E(PD2)=L
今回、EをPORTDの2番からPORTBの5番へ移動させたのですが、上のようなプログラムでは、ピン配が変わる度に修正が大変です。
カスタマイズしやすいように、下の様に作り変えました。
マクロ
#define L 0 #define H 1 #define E(hl) ((struct bf*)&PORTB)->b5 = hl
本体
E(H);
_delay_us(1);
E(L);
マクロで使っている構造体は、ビットフィールドです。
struct bf{
int b0: 1;
int b1: 1;
int b2: 1;
int b3: 1;
int b4: 1;
int b5: 1;
int b6: 1;
int b7: 1;
};
ポート制御は、ビットフィールドを使わないとプログラミングが辛いですね。
エンディアン変換にも使えます。
~$ cat -n my_htonl.c
1 #include "stdio.h"
2 #include "stdint.h"
3
4 int main()
5 {
6 struct bf{
7 int b1: 8;
8 int b2: 8;
9 int b3: 8;
10 int b4: 8;
11 };
12
13 int32_t a;
14 int32_t b;
15
16 a = 0x12345678;
17
18 ((struct bf*)&b)->b1 = ((struct bf*)&a)->b4;
19 ((struct bf*)&b)->b2 = ((struct bf*)&a)->b3;
20 ((struct bf*)&b)->b3 = ((struct bf*)&a)->b2;
21 ((struct bf*)&b)->b4 = ((struct bf*)&a)->b1;
22
23 printf("a=%08x\n",a);
24 printf("b=%08x\n",b);
25 }
~$ gcc my_htonl.c ~$ ./a.out a=12345678 b=78563412 ~$
レポジトリはこちら
~$ git clone https://github.com/takkete/bread.git ~$ cd bread/mcu/avr/attiny2313/device/clcd


コメント
[…] キャラクタLCDに時計を表示します。 「ポート制御にビットフィールドを使う」で作ったプログラムを改造します。今回は時計とまではいかなくて、時を刻むだけのものです。 […]