C言語で、キャラクタLCDを制御したいと思います。

前回で作成したpiob_init(uint8_t)、io_out(uint8_t,uint8_t)、sleep(uint16_t)を使用します。

LCDは以前から使用しているキャラクタLCDの「KKHMF DC 5V 1602 LCD ディスプレイモジュール 16×2キャラクタ LCDブルーブラックライト」を使用します。

回路図はこちらを参考にしてください aki-80 CN3-PBポートに接続しています。

LCDコントラストを調整する半固定抵抗器2KΩは手持ちのものを使用しています。

ソフトは以前作成した「RP2040(RaspberryPi Pico)に萌えたい。例題PIO I2C その2」のソフトを手直しして使用しました。

LCDへの書き込みは4ビットごとに書き込みします。
書き込みには、コマンドデータと表示用データの書き込みの2種類があります。
モードの切り替えは RS端子で行います。
コマンドデータ >> RS=0
表示用データ  >> RS=1

書き込みと読み出しのモード切替はRW端子で行います。
読み出し >> RW=1
書き込み >> RW=0
今回の場合は、読み出しは行わないので、RW端子は常に 0のままです。

実際の書き込みタイミングは、Eを正論理でパルスを送ります。
つまり、 E >> 0>1>0のタイミングの1発だけのパルスを生成します。

コマンドデータの4ビットの書き込みは下記のようになりました

void lcd4bitwrite(uint8_t command){
    command <<= 4;
    command |= (uint8_t)0b00001000;
    command &= (uint8_t)0b11111000;
    io_out(PortBD,command);
    command |= (uint8_t)0b00001100;
    command &= (uint8_t)0b11111100;
    io_out(PortBD,command);
    command |= (uint8_t)0b00001000;
    command &= (uint8_t)0b11111000;
    io_out(PortBD,command);    
}

同じような手順で、表示データの4ビットの書き込みは下記のようになります。
コマンドデータの書き込みと統合するとプログラムは短くなりますが、あえてわかりやすいように(ちょっと言い訳)分けてみました。

void data_lcd4bitwrite(uint8_t command){

    command <<= 4;
    command |= (uint8_t)0b00001001;
    command &= (uint8_t)0b11111001;
    io_out(PortBD,command);
    command |= (uint8_t)0b00001101;
    command &= (uint8_t)0b11111101;
    io_out(PortBD,command); 
    command |= (uint8_t)0b00001001;
    command &= (uint8_t)0b11111001;
    io_out(PortBD,command);;     

}

8ビット単位の書き込みは、上位4ビットを書き込みに続いて下位4ビットを書き込みしています。
コマンド書き込みと表示データ書き込みは次のようになります。

void lcd8bitwrite(uint8_t command){

    uint8_t command2;
    
    command2 = command;
    command >>= 4;
    lcd4bitwrite(command);
    lcd4bitwrite(command2);
}
void data_lcd8bitwrite(uint8_t command){

    uint8_t command2;
    
    command2 = command;
    command >>= 4;
    data_lcd4bitwrite(command);
    data_lcd4bitwrite(command2);

}

プログラム全体

実際のプログラムは下記のようになります。

#include <stdio.h>
#include <stdint.h>


extern	uint8_t	piob_init(uint8_t);
extern	uint8_t	io_out(uint8_t,uint8_t);
extern 	uint8_t sleep(uint16_t);

   
void lcd4bitwrite(uint8_t command);
void lcd8bitwrite(uint8_t command);
void data_lcd4bitwrite(uint8_t command);
void data_lcd8bitwrite(uint8_t command);

const	uint8_t PortBD = 0x1e;
const	uint8_t PortBC = 0x1f;



int main() {

    piob_init(0x00);				//B port output mode

    uint8_t message1[]=" **TMPZ84C015** ";
    uint8_t message2[]="Hello SDCC World";
    
    //Display initialization
	uint8_t data_set;

	data_set=0x03;

    lcd4bitwrite(data_set);
    sleep(5);
    lcd4bitwrite(data_set);
    lcd4bitwrite(data_set);
	data_set=0x02;
    lcd4bitwrite(data_set);    			//4bit mode
	data_set=0x28;
    lcd8bitwrite(data_set);     		//function set 4bit bus,2 line ,1 line=8
	data_set=0x0c;
    lcd8bitwrite(data_set);     		//disp on,under cursor off,block
	data_set=0x01;
    lcd8bitwrite(data_set);     		//disp clr
    sleep(2);
	data_set=0x06;
    lcd8bitwrite(data_set);     		//disp address incrmant on,disp shift off
	data_set=0x02;
    lcd8bitwrite(data_set);     		//cursor home set
    sleep(2);
    
	for (int i=0;message1[i] != '\0';i++){
        data_lcd8bitwrite(message1[i]);
//        printf("%c\n",message1[i]);
    }
	data_set = 0xc0;
    lcd8bitwrite(data_set);     		//x80 + 0x40(2 line top address)
	for (int i=0;message2[i] != '\0';i++){
        data_lcd8bitwrite(message2[i]);
//        printf("%c\n",message2[i]);       
    }
        return(0);
}


void lcd4bitwrite(uint8_t command){
    command <<= 4;
    command |= (uint8_t)0b00001000;
    command &= (uint8_t)0b11111000;
    io_out(PortBD,command);
    command |= (uint8_t)0b00001100;
    command &= (uint8_t)0b11111100;
    io_out(PortBD,command);
    command |= (uint8_t)0b00001000;
    command &= (uint8_t)0b11111000;
    io_out(PortBD,command);    
}
void lcd8bitwrite(uint8_t command){

    uint8_t command2;
    
    command2 = command;
    command >>= 4;
    lcd4bitwrite(command);
    lcd4bitwrite(command2);
}
void data_lcd4bitwrite(uint8_t command){

    command <<= 4;
    command |= (uint8_t)0b00001001;
    command &= (uint8_t)0b11111001;
    io_out(PortBD,command);
    command |= (uint8_t)0b00001101;
    command &= (uint8_t)0b11111101;
    io_out(PortBD,command); 
    command |= (uint8_t)0b00001001;
    command &= (uint8_t)0b11111001;
    io_out(PortBD,command);;     

}
void data_lcd8bitwrite(uint8_t command){

    uint8_t command2;
    
    command2 = command;
    command >>= 4;
    data_lcd4bitwrite(command);
    data_lcd4bitwrite(command2);

}

以上のCプログラムを 「lcd_main.c] として保存します。

コンパイルします。

$ sdcc -mz80 --out-fmt-ihx --code-loc 0xa000 --no-std-crt0 -o lcd_main.ihx mycrt0.rel lcd_main.c io_out.rel  piob_init.rel sleep.rel
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA
Conflicting flags in area    _CODE
Conflicting flags in area    _DATA

モニタ上のlコマンドで読みこみます。A000をコールします

>l                                                                              20A00000DDE5DD210000DD3921DCFF39F9AFF533CD26A333211100394D443E200269602354
20A02000362A69602323362A6960232323365421040009364D2105000936502106000936C9
20A040005A210700093638210800093634210900093643210A00093630210B000936312168
20A060000C00093635210D0009362A210E0009362A210F0009362021100009360021000011
20A0800039DD75FEDD74FF3648DD6EFEDD66FF233665DD6EFEDD66FF2323366CDD6EFEDD87
20A0A00066FF232323366CDD7EFEC6046FDD7EFFCE0067366FDD7EFEC6056FDD7EFFCE00AF

中略
00000001FF
OK
>

>c a000 y:

LCDに

 **TMPZ84C015**
  Hello SDCC World

と表示されたらOKです。

おすすめの記事