LCDの動作確認

LCD(ACM1602K-NLW-BBW)をPICで動作確認したのでその時の記録になります。今回は、8ビットモードと4ビットモードのそれぞれで動作確認を行いました。参考になれば幸いです。

使用部品と回路構成

以下に使用部品および図1にLCDの回路を示します。

  • PIC 16F13145
  • LCD ACM1602K-NLW-BLW(秋月電子で購入)
  • 金属皮膜抵抗2 kΩ,VoとGND間で接続 ※正しい方法ではない 図1、図2を参照
  • ブレッドボード
  • 配線
図1 4ビットモード時と8ビットモード時の回路図 右上の回路図はコントラスト調整用の半固定抵抗をVoに取り付けた場合のものを示しています。
LCDのピンアサイン
図2 LCDのピンアサイン(出典:https://akizukidenshi.com/goodsaffix/ACM1602K-NLW-BBW_VER1.pdf

8ビットモードではデータ線はDB0~DB7とPICの対応する出力端子を接続し、4ビットモードではDB4~DB7までのデータ線とPICの対応する出力端子を接続しています。またコントラスト調整を行わないと文字がきちんと表示されないため半固定抵抗が必要です。今回は購入し忘れたため適当な抵抗を接続したところきちんと表示できたので正しくない方法(データシートの指示と違うという意味で)でやっています。

LCDの制御方法の説明
図3 LCDの制御仕様 (出典:https://akizukidenshi.com/goodsaffix/ACM1602K-NLW-BBW_VER1.pdf)
LCDの初期化手順の説明
図4 LCDの初期化手順の説明 (8ビットモード)
図5 LCDの初期化手順の説明(4ビットモード)

図4、図5は図2と図3のデータシートとは別のサイトのものです。

図4、図5の出典:ST7066U

LCDは文字を表示させるだけなので(書き込みのみ使用)5番ピンをGNDに接続しています。

MCCでRSとEをそれぞれRB5ピンとRB6ピンに出力、また4ビットモードではRC0ピンからRC3ピン、8ビットモードではRC0ピンからRC7ピンまでを出力として設定しています。

ソースコード

あまり参考になるかわかりませんがLCDを動作できた時のそれぞれのソースコードを記載しておきます。データシートによると例えば初期化の処理などでビットの状態がどちらでもよいときがあり(データシートではXで記載)、この時そのビットは1にすればよいか0にすればよいかわからず、おそらくどちらかの状態に固定していればいいのかもしれませんが…

//4ビットモードで動作させた場合
void lcd4_send(uint8_t code, uint8_t mode)
{
    LATC = (code & 0xF0) >> 4;  // RC0-RC3に出力
	if (mode == 0) 
		RS_SetHigh();   // 表示データ時
	else
		RS_SetLow();    // コマンドデータ時
	E_SetHigh();           
	E_SetLow();            
}

void lcd4_char(uint8_t chr){
	lcd4_send(chr, 0);	// 上位4ビット出力
	lcd4_send(chr<<4, 0);	// 下位4ビット出力
	__delay_us(50);		
}

void lcd4_ctl(uint8_t ctl){
	lcd4_send(ctl, 1);	// 上位4ビット出力
	lcd4_send(ctl<<4, 1);	// 下位4ビット出力
	__delay_ms(2);		
}

void lcd4_clear(){
	lcd4_ctl(0x01);
	__delay_ms(15);		
}

void lcd4_init(){
    __delay_ms(150);          
	lcd4_send(0x30, 1);	// 8bit mode set
	__delay_ms(5);
	lcd4_send(0x30, 1);	// 8bit mode set
	__delay_ms(1);
	lcd4_send(0x30, 1);	// 8bit mode set
	__delay_ms(1);
	lcd4_send(0x20, 1);	// 4bit mode set
	__delay_ms(1);
	lcd4_ctl(0x2E);		// DL=0 4bit mode
	lcd4_ctl(0x08);		// display off C=D=B=0
	lcd4_ctl(0x0D);		// display on C=D=1 B=0
	lcd4_ctl(0x06);		// entry I/D=1 S=0
	lcd4_ctl(0x02);		// cursor home
}
void lcd4_str(uint8_t *str){
    while(*str != 0){        
        lcd4_char(*str++); 
    }
}
void main(void)
{
    SYSTEM_Initialize();       
    lcd4_init();                 
    lcd4_clear(); 
    while(1)                    
    {
        lcd4_ctl(0xC0);
        lcd4_str("Test LCD!!");
        __delay_ms(1000);
    }
}
//8ビットモードで動作させた場合
void lcd_send(uint8_t code, uint8_t mode)
{
    LATC = code;  // RC0-RC7に出力
	if (mode == 0)          
		RS_SetHigh();   //データ表示時
	else
		RS_SetLow();    // コマンド時
	E_SetHigh();            
	E_SetLow();            
    __delay_us(40);
}
void lcd_print(uint8_t *str){
    while(*str != 0){
        lcd_send(*str++, 0);
    }
}

void lcd_clear(){
  lcd_send(0x01, 1);      // 消去コマンド
  __delay_ms(15);
}

void lcd_init(){
    __delay_ms(150);           
    lcd_send(0x38, 1);	// FunctionSet 
    __delay_ms(5);
    lcd_send(0x38, 1);	// FunctionSet
    __delay_ms(1);
    lcd_send(0x38, 1);	// FunctionSet
    __delay_ms(1);
  lcd_send(0x08, 1);	// Display On/Off Control
    __delay_ms(1);
    lcd_send(0x0D, 1);
    __delay_ms(1);
    lcd_clear();
    lcd_send(0x06, 1);		// EntryMode Set I/D=1 S=0
    __delay_ms(1);
    lcd_send(0x02, 1);		// Return Home
}

void main(void)
{
    SYSTEM_Initialize();       
    lcd_init();                 
    lcd_clear();              
    while(1)                
    {
        lcd_send(0xC0, 1);
        lcd_print("Test LCD!!");
        __delay_ms(1000);
    }
}

動作確認

図6 4ビットモードでの動作状態
図7 8ビットモードでの動作状態

図7と図8を見るとデータ線が4本少なくなるだけでも見た目が多少なりともすっきりしていることがわかるかと思います。プログラムに関しては8ビットモードのほうがそのままデータを出力すればよいので多少簡単になっていることがわかると思います。

まとめ

4ビットモード 8ビットモードでLCDの文字表示動作の確認ができました。余談ですがLCDの初期化に失敗していると表示が変になったり(LCDの上半分だけ全て真っ白表示)、delay関数による待ち時間が短く高速にデータが送られると、文字表示が欠落したり、意図した文字と違う文字が表示されたり意図しない箇所に表示されたり挙動がおかしくなっていました。

今回はここまでになります。最後まで読んでいただきありがとうございました。