Raspberry Pi Pico(d_17)LCD 1602 HD44780
LCD 1602 HD44780(I2C)
LCD 1602は2行16桁表示できる液晶ディスプレイ(Liquid Crystal Display)です。
LCD1602 モジュールのドライバーはHITACHI HD44780(Dot Matrix Liquid Crystal Display Controller/Driver)の互換4bitモードらしいです。実質、HD44780を設定している感じになります。そのためHD44780のデータシートが参考になります。
※micro:bitの記事e_21からRaspberry Pi Picoで使えるように追記、修正等をしました。
外観
LCD 1602モジュールの外観写真です。(以後はLCD 1602と記載します)
接続例
LCD 1602を5Vで動作させるので別途電源が必要です。
レベルコンバータ経由でI2C接続するだけです。そのため、接続図などは省きました。
I2C通信にはI2C1のSDA(GP10)SCL(GP11)を使いました。
接続が出来たらI2Cデバイスのスレーブアドレスを調べてみます。
ThonnyのShellで確認しました。
LCD 1602のスレーブアドレスは以下のように63(0x3f)でした。
>>> from machine import I2C,Pin
>>> i2c=I2C(1, scl=Pin(11), sda=Pin(10), freq=100_000)
>>> i2c.scan()
[63]
HD44780の説明
LCDドライバーのHD44780のデータシートから抜粋して説明します。
■4ビットモード
HD44780は4-bit or 8-bit MPU interfaceだそうです。
LCD 1602を駆動するためには4-bitモードに初期設定をする必要があります。
実際には、Instruction(コマンド)のFunction set 0x30(8-bit lengths)を3回送って初期化をした後、Function set 0x20(4-bit lengths)を送って4ビットバスモードにします。
Function set |0|0|1|DL|N|F|*|*|
※ HD44780のデータシートから抜粋
DL:(0)4-bit lengths (1)8-bit lengths /send or received
N :(0)1-line (1)2-line /number of display lines.
F :character font 2-line * 5x8dots
■コマンド・データ送信
8bitのデータ、コマンドを上下4bitで送信する4bitモードを使います。
上下の4bitデータの下位4bitに「BL|E|R/W|RS」のデータを付加して送信します。
Enableが1から0に変化した時点でLCDにデータが書き込まれるそうです。
そのため付加データのEのbitを’1’のデータ、続けてEのbitを’0’にしたデータを送信します。
4bitモードでコマンド(Instruction|RS=0)の1byteデータ(D7~D0)を送信(write|R/W=0)する場合、
|D7|D6|D5|D4|BL=1|EN=1|R/W=0|RS=0| (|D7|D6|D5|D4|1|1|0|0|)
|D7|D6|D5|D4|BL=1|EN=0|R/W=0|RS=0| (|D7|D6|D5|D4|1|0|0|0|)
|D3|D2|D1|D0|BL=1|EN=1|R/W=0|RS=0| (|D3|D2|D1|D0|1|1|0|0|)
|D3|D2|D1|D0|BL=1|EN=0|R/W=0|RS=0| (|D3|D2|D1|D0|1|0|0|0|)
の4回を送信します。
4bitモードでデータ(文字データ)を送信する場合はRS=1にします。
|D7|D6|D5|D4|BL=1|EN=1|R/W=0|RS=1| (|D7|D6|D5|D4|1|1|0|1|)
|D7|D6|D5|D4|BL=1|EN=0|R/W=0|RS=1| (|D7|D6|D5|D4|1|0|0|1|)
|D3|D2|D1|D0|BL=1|EN=1|R/W=0|RS=1| (|D3|D2|D1|D0|1|1|0|1|)
|D3|D2|D1|D0|BL=1|EN=0|R/W=0|RS=1| (|D3|D2|D1|D0|1|0|0|1|)
の4回を送信します。
■表示モードを設定
[0x28,0x0F,0x06,0x01]のコマンドを送信することにしました。
Function set (0x28) 4ビットバスモード(DL=’0′)、Display-Lines 2行(N=’1′)
Display on/off (0x0F) オン、カーソル、点滅(D=’1′,C=’1′,B=’1′)
Entry mode set (0x06) increment(I/D=’1′)
Clear display (0x01) クリア
■Display position
Entry mode set 0x06 にすると2-lineなのでDDRAMのaddress(カーソル、文字位置)は以下になります。
SetDDRAMのコマンドはDB7=’1’にしてDDRAMのaddressを指定します。
※ HD44780のデータシートから抜粋
列を’x’、行を’y’にするとDDRAMのaddressは y* 0x40 + x になります。
そのため、Display位置を指定するコマンドは (0x80 | (y* 0x40 + x))を送信することになります。
※ HD44780のデータシートから抜粋
■文字データの表示
文字データの送信例を示します。
※ HD44780のデータシートから抜粋 に加筆
’H’を表示する場合には、’H’に対応する文字コード’0x48’データを送信します。
送信データは先に示したような型で4回送信します。
|0|1|0|0|1|1|0|1| ‘0x4d’
|0|1|0|0|1|0|0|1| ‘0x49’
|1|0|0|0|1|1|0|1| ‘0x8d’
|1|0|0|0|1|0|0|1| ‘0x89’
※詳細は HD44780のデータシートを参照ください。
スクリプト
LCD 1602のスクリプトは以下のようにしました。
0行1列から’0123456789012345’を表示
1行1列から’abcdefghABCDEFGH’を表示
0行1列から’!#$%&()=|@+-*/<>’を上書き表示
1行1列からコード0xb0~0xbf(-アイ…ソ)を上書き表示
を試しています。
※開発環境はThonnyです。ThonnyでMicroPythonをRaspberry Pi Pico with RP2040にインストールして使っています。
※Raspberry Pi Pico単独で動作させるには’main.py’としてRaspberry Pi Picoにuploadして使います。
pico_lcd1602_02b.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from machine import I2C,Pin
import time
# LCD 1602
# HD44780U Dot Matrix Liquid Crystal Display Controller/Driver
adr_lcd=0x3f
i2c=I2C(1, scl=Pin(11), sda=Pin(10), freq=100_000)
# 1byte送信(write)
def lcd_wr(dat):
buf = bytearray(1) # 1byteごとに送る
buf[0] = dat
i2c.writeto(adr_lcd,buf)
time.sleep_ms(2)
# 上下4bitにEN,RSなど付加して4回送る
#|D7/3|D6/2|D5/1|D4/1|BL|EN|R/W|RS| 8bit
def lcd_dat(dat,RS=0): #デフォルトはコマンド送信(RS=0)、データ送信はRS=1
f= (dat & 0xf0)|0x0C|RS # |BL|EN|R/W|RS|=|1|1|0|RS|
s= (dat & 0xf0)|0x08|RS # |BL|EN|R/W|RS|=|1|0|0|RS|
return f,s
# コマンドを送る Instruction
def lcd_cmd(dat):
f,s=lcd_dat(dat)
lcd_wr(f)
lcd_wr(s)
f,s=lcd_dat(dat<<4) # LSB4bitをシフト
lcd_wr(f)
lcd_wr(s)
# 初期化 4bitモード、2行、カーソル点滅
def lcd_init():
# function_initilize 4bit 4-bit interface reset
fset=[0x30,0x30,0x30,0x20]
for c in fset:
f,s=lcd_dat(c)
lcd_wr(f)
lcd_wr(s)
# 4bit init set data
# 28:4bit col2,disp-cur,blink,entry-increase,disp-clear
bset=[0x28,0x0F,0x06,0x01]
for c in bset:
f,s=lcd_dat(c)
lcd_wr(f)
lcd_wr(s)
f,s=lcd_dat(c<<4)
lcd_wr(f)
lcd_wr(s)
# カーソル位置のセット (DDRAM address)
def lcd_pos(x, y):
pos=(0x80 | (y* 0x40 + x))
lcd_cmd(pos)
# 1文字を表示 (1文字データを送る RS=1)
def lcd_chr(dat):
#RS=1
f,s=lcd_dat(dat,RS=1)
lcd_wr(f)
lcd_wr(s)
f,s=lcd_dat(dat<<4,RS=1)
lcd_wr(f)
lcd_wr(s)
# 文字列の表示
def lcd_print(pr):
m_dat=pr.encode() # 英数字ならencodeが使えるようだ
for i in m_dat:
lcd_chr(i)
time.sleep(5)
# 実行 lcd に文字を表示
lcd_init()
lcd_cmd(0x01) #Clear
time.sleep(2)
# 0行1列から'0123456789012345'を表示
lcd_pos(0,0)
time.sleep(2)
moj='0123456789012345'
lcd_print(moj)
# 1行1列から'abcdefghABCDEFGH'を表示
lcd_pos(0,1)
time.sleep(2)
moj='abcdefghABCDEFGH'
lcd_print(moj)
# 0行1列から'!#$%&()=|@+-*/<>'を上書き表示
lcd_pos(0, 0)
time.sleep(2)
moj='!#$%&()=|@+-*/<>'
lcd_print(moj)
# 1行1列からコード0xb0~0xbf(-アイ...ソ)を上書き表示
# カタカナはROM CODEのデータを送る
lcd_pos(0, 1)
time.sleep(2)
for i in range(16):
code=0xb0+i
lcd_chr(code)
関数 部分説明
lcd_init()
LCD 1602(HD44780U)を初期化します。4bitモード、2行、カーソル点滅の設定にしています。
lcd_cmd(dat)
コマンドデータを送ります。
lcd_pos(x, y)
カーソル位置をセットします。
lcd_print(pr)
英数字の文字列(pr)を表示します。
lcd_chr(dat)
1文字のコードデータを送って表示します。
例えば’ア’を表示する場合、下表のROM Code表から upper ‘1011’ lower ‘0001’のコード’0xb1’を送ります。
>>> %Run -c $EDITOR_CONTENT
>>> lcd_chr(0xb1)
実行結果
結果は以下のようになりました。LCD 1602に文字を表示できました。
※初期化後の
カーソルが見えない場合はLCD 1602裏面のコントラストを調整して見てください。
動作確認の動画です。
まとめ
Raspberry Pi PicoでLCD 1602を使ってLCDディスプレイに文字表示ができました。