LCD(ACM1602K-NLW-BBW)をPICで動作確認したのでその時の記録になります。今回は、8ビットモードと4ビットモードのそれぞれで動作確認を行いました。参考になれば幸いです。
使用部品と回路構成
以下に使用部品および図1にLCDの回路を示します。
- PIC 16F13145
- LCD ACM1602K-NLW-BLW(秋月電子で購入)
- 金属皮膜抵抗2 kΩ,VoとGND間で接続 ※正しい方法ではない 図1、図2を参照
- ブレッドボード
- 配線

LCDのピンアサイン

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

LCDの初期化手順の説明



図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);
}
}
動作確認


図7と図8を見るとデータ線が4本少なくなるだけでも見た目が多少なりともすっきりしていることがわかるかと思います。プログラムに関しては8ビットモードのほうがそのままデータを出力すればよいので多少簡単になっていることがわかると思います。
まとめ
4ビットモード 8ビットモードでLCDの文字表示動作の確認ができました。余談ですがLCDの初期化に失敗していると表示が変になったり(LCDの上半分だけ全て真っ白表示)、delay関数による待ち時間が短く高速にデータが送られると、文字表示が欠落したり、意図した文字と違う文字が表示されたり意図しない箇所に表示されたり挙動がおかしくなっていました。
今回はここまでになります。最後まで読んでいただきありがとうございました。
