前回「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に時計を表示します。 「ポート制御にビットフィールドを使う」で作ったプログラムを改造します。今回は時計とまではいかなくて、時を刻むだけのものです。 […]