樹(shù)莓派基礎(chǔ)實(shí)驗(yàn)29:I2C LCD1602實(shí)驗(yàn)

一、介紹

?? 眾所周知,雖然液晶顯示器和其他顯示器大大的豐富了人機(jī)交互浴滴,但他們有一個(gè)共同的弱點(diǎn)。當(dāng)它們連接到控制器時(shí)岁钓,需要占用大量的IO口升略,但是一般的控制器沒(méi)有那么多的外部端口,也限制了控制器的其他功能屡限。因此品嚣,開(kāi)發(fā)具有I2C組件的LCD1602來(lái)解決該問(wèn)題,LCD1602是一種只用來(lái)顯示字母钧大、數(shù)字翰撑、符號(hào)等的點(diǎn)陣型液晶模塊。

?? 字符型液晶顯示模塊是由字符型液晶顯示屏LCD 啊央、控制驅(qū)動(dòng)主電路HD44780/KS0066及其擴(kuò)展驅(qū)動(dòng)電路HD44100或與其兼容的IC眶诈, 少量阻、容元件結(jié)構(gòu)件等裝配在PCB板上而成瓜饥。

??I2C總線是由PHLIPS發(fā)明的一種串行總線逝撬。它是一種高性能的串行總線,具有多主機(jī)系統(tǒng)所需的總線控制和高速或低速設(shè)備同步功能乓土。I2C LCD1602上的藍(lán)色電位器用于調(diào)整背光宪潮,以獲得更好的顯示效果溯警。I2C使用兩個(gè)雙向極漏開(kāi)路線,串行數(shù)據(jù)線(SDA)和串行時(shí)鐘線(SCL)狡相,通過(guò)電阻上拉梯轻。使用的典型電壓為5V或3.3V,但允許使用其他電壓的系統(tǒng)谣光。

??其它I2C總線實(shí)驗(yàn)可以查看前面的PCF8591相關(guān)實(shí)驗(yàn)檩淋,如:
??樹(shù)莓派基礎(chǔ)實(shí)驗(yàn)12:PCF8591模數(shù)轉(zhuǎn)換器實(shí)驗(yàn)

二、組件

★Raspberry Pi主板*1

★樹(shù)莓派電源*1

★40P軟排線*1

★I2C LCD1602模塊*1

★面包板*1

★跳線若干

三萄金、實(shí)驗(yàn)原理

LCD1602正面
LCD1602背面
LCD1602電路圖

?? 樹(shù)莓派的GPIO端口數(shù)量有限蟀悦,可通過(guò)IO擴(kuò)展芯片增加GPIO的數(shù)量,使得樹(shù)莓派可以適應(yīng)更多的應(yīng)用氧敢。本實(shí)驗(yàn)中的LCD1602模塊有16個(gè)管腳日戈,為節(jié)省GPIO端口,就使用了一款通過(guò)I2C總線擴(kuò)展IO的芯片孙乖,PCF8574浙炼。單個(gè)PCF8574可擴(kuò)展8個(gè)IO,一個(gè)I2C總線最多可掛載8個(gè)PCF8574唯袄,所以樹(shù)莓派最多可擴(kuò)展64個(gè)IO弯屈。

?? 本實(shí)驗(yàn)中的編程原理比較復(fù)雜,所以一定要程序和硬件原理結(jié)合起來(lái)看才易理解恋拷。如果不想深度學(xué)習(xí)底層原理及驅(qū)動(dòng)程序,掌握LCD1602的函數(shù)使用方法就可以了宴偿,但若想靈活運(yùn)用LCD1602窄刘,最好了解一下舷胜。

?? 本文是在網(wǎng)上查閱了很多中外資料娩践,匯集諸多大神的智慧,10幾天(當(dāng)然烹骨,每天還是要上班的)才整理匯編而成翻伺,但仍有很多不懂和錯(cuò)誤之處,特別是程序中有一長(zhǎng)串“穆趴?脸爱?遇汞??”注釋的地方空入,請(qǐng)大神們留言指出!

3.1 LCD1602的存儲(chǔ)器

??LCD1602里面存儲(chǔ)器有三種:CGROM化戳、CGRAM、DDRAM甩恼。
??DDRAM(Display Data RAM)就是顯示數(shù)據(jù)RAM切端,用來(lái)寄存待顯示的字符代碼。共80個(gè)字節(jié)烤咧,其地址和屏幕的對(duì)應(yīng)關(guān)系如下,如圖:

數(shù)據(jù)地址和屏幕對(duì)應(yīng)的關(guān)系

??DDRAM其實(shí)就是我們平時(shí)說(shuō)的PC機(jī)的顯存昌阿,如果說(shuō)我們想要在屏幕上顯示我們想要顯示的饥脑,直接把需要的字符代碼送入顯存就可以了恳邀,很簡(jiǎn)單就能夠在屏幕上顯示我們想要顯示的。相同的LCD1602總共存在80個(gè)字節(jié)的顯存灶轰,就是DDRAM谣沸。遺憾的是LCD1602顯示不出來(lái)這么多的字符,正是因?yàn)檫@樣笋颤,不是每一個(gè)寫(xiě)在DDRAM上的字符都能夠在顯示器上顯示出來(lái)乳附,一次只能顯示16個(gè)字符。正是因?yàn)檫@樣伴澄,我們?cè)诔绦蛑锌梢岳孟旅娴摹肮鈽?biāo)或顯示移動(dòng)指令”使字符慢慢移動(dòng)到可見(jiàn)的顯示范圍內(nèi)赋除,看到字符的移動(dòng)效果。

??那么如何在液晶上顯示字符呢非凌,就是把要寫(xiě)入的字符給DDRAM贤重。舉個(gè)例子,我現(xiàn)在想在屏幕上顯示“A”清焕,我就把我要的字符“A”的字符代碼41H寫(xiě)入DDRAM的00H地址處然后得到并蝗。那我們應(yīng)該怎么去寫(xiě)入呢,我們?cè)诤竺孢M(jìn)行進(jìn)一步的闡述秸妥。我們下面將要介紹的是A的字模滚停,如圖:

A的字模

??上面的圖左側(cè)顯示的就是“A”的字模數(shù)據(jù),上面的圖右側(cè)顯示“○”代表0粥惧,用“■”代表 1键畴。這樣我們就能夠顯示出“A”這個(gè)字形。

??在LCD1602模塊上固化了字模存儲(chǔ)器突雪,就是CGROM和CGRAM起惕,HD44780內(nèi)置了192個(gè)常用字符的字模,存于字符產(chǎn)生器CGROM(Character Generator ROM)中咏删,另外還有8個(gè)允許用戶自定義的字符產(chǎn)生RAM惹想,稱為CGRAM(Character Generator RAM),留給自定義的位置只有8個(gè)地址督函,也就是最多自定義8個(gè)符號(hào)或者圖形嘀粱。

??下圖(字模表)說(shuō)明了CGROM和CGRAM與字符的對(duì)應(yīng)關(guān)系。從ROM和RAM的名稱我們也可以知道辰狡,ROM是早已固化在LCD1602模塊中的锋叨,只能讀然鸨恰奥裸;但是RAM即可以讀又可以寫(xiě)。

字模表

??若是只要求在屏幕上顯示CGROM中已經(jīng)擁有的字符徽职,那就僅僅需要在DDRAM中寫(xiě)入它的字符代碼就可以了叫倍;若是想顯示的是CGROM中不存在的字符偷卧,例如美元的符號(hào)嘿般,那就只能先在CGRAM中規(guī)定,下一步再在DDRAM中寫(xiě)入我們之前自己定義的字符就可以涯冠。

字形和光標(biāo)

??上面這個(gè)圖說(shuō)明的是5×8點(diǎn)陣和5×10點(diǎn)陣字符的字形和光標(biāo)的位置。這里我們采用的是5×8點(diǎn)陣逼庞,那么定義這樣一個(gè)字符需要8個(gè)字節(jié)蛇更,每個(gè)字節(jié)的前3個(gè)位沒(méi)有被使用。

設(shè)置CGRAM地址指令

??上面這個(gè)圖說(shuō)明的是設(shè)置CGRAM地址指令赛糟。從這個(gè)指令的格式中我們可以看出派任,它共有aaaaaa這6位,一共可以表示64個(gè)地址璧南,即64個(gè)字節(jié)掌逛。一個(gè)5×8點(diǎn)陣字符共占用8個(gè)字節(jié),那么這64個(gè)字節(jié)一共可以自定義8個(gè)字符司倚。也就是說(shuō)豆混,上面這個(gè)圖的6位地址中的DB5DB4DB3用來(lái)表示8個(gè)自定義的字符,DB2DB1DB0用來(lái)表示每個(gè)字符的8個(gè)字節(jié)动知。這DB5DB4DB3所表示的8個(gè)自定義字符(0--7)就是要寫(xiě)入DDRAM中的字符代碼皿伺。

3.2 管腳

?? 加裝了I2C轉(zhuǎn)接版的LCD1602,能夠同時(shí)顯示16x02即32個(gè)字符盒粮。(16列2行)1602字符型LCD通常有16條引腳線的LCD:

?? 引腳 ?? 符號(hào)?? 功能說(shuō)明
1 VSS 一般接地
2 VDD 接電源(+5V)
3 V0 晶顯示器對(duì)比度調(diào)整端鸵鸥,接正電源時(shí)對(duì)比度最弱,接地電源時(shí)對(duì)比度最高(對(duì)比度過(guò)高時(shí)會(huì)產(chǎn)生“鬼影”丹皱,使用時(shí)可以通過(guò)一個(gè)10K的電位器調(diào)整對(duì)比度)妒穴。
4 RS RS為寄存器選擇,高電平(1)時(shí)選擇數(shù)據(jù)寄存器摊崭、低電平(0)時(shí)選擇指令寄存器讼油。
5 R/W R/W為讀寫(xiě)選擇,高電平(1)時(shí)進(jìn)行讀操作呢簸,低電平(0)時(shí)進(jìn)行寫(xiě)操作汁讼。
6 E E(或EN)端為使能(enable)端,寫(xiě)操作時(shí)阔墩,下降沿使能嘿架。讀操作時(shí),E高電平有效
7 DB0 低4位三態(tài)啸箫、 雙向數(shù)據(jù)總線 0位(最低位)
8 DB1 低4位三態(tài)耸彪、 雙向數(shù)據(jù)總線 1位
9 DB2 低4位三態(tài)、 雙向數(shù)據(jù)總線 2位
10 DB3 低4位三態(tài)忘苛、 雙向數(shù)據(jù)總線 3位
11 DB4 高4位三態(tài)蝉娜、 雙向數(shù)據(jù)總線 4位
12 DB5 高4位三態(tài)唱较、 雙向數(shù)據(jù)總線 5位
13 DB6 高4位三態(tài)、 雙向數(shù)據(jù)總線 6位
14 DB7 高4位三態(tài)召川、 雙向數(shù)據(jù)總線 7位(最高位)(也是busy flag)
15 BLA 背光電源正極
16 BLK 背光電源負(fù)極

3.3 LCD1602的基本操作及時(shí)序

?? 本系列模塊內(nèi)部具有兩個(gè) 8 位寄存器:指令寄存器(IR)和數(shù)據(jù)寄存器(DR)南缓。用戶可以通過(guò) RS 和 R/W 輸入信號(hào)的組合選擇指定的寄存器,進(jìn)行相應(yīng)的操作荧呐。下表中列出了組合選擇方式:

RS R/W 操作說(shuō)明
0 0 寫(xiě)入指令寄存器(清除屏等)
0 1 讀busy flag(DB7)汉形,以及讀取位址計(jì)數(shù)器(DB0~DB6)值
1 0 寫(xiě)入數(shù)據(jù)寄存器(顯示各字型等)
1 1 從數(shù)據(jù)寄存器讀取數(shù)據(jù)

LCD1602的基本操作:
 1. 讀狀態(tài):輸入RS=0,RW=1倍阐,E=高脈沖概疆。輸出:D0—D7為狀態(tài)字。
 2. 讀數(shù)據(jù):輸入RS=1峰搪,RW=1岔冀,E=高脈沖。輸出:D0—D7為數(shù)據(jù)概耻。
 3. 寫(xiě)命令:輸入RS=0使套,RW=0,E=高脈沖鞠柄。輸出:無(wú)童漩。(寫(xiě)完置E=高脈沖)
 4. 寫(xiě)數(shù)據(jù):輸入RS=1,RW=0春锋,E=高脈沖矫膨。輸出:無(wú)。
注意:E(或EN)端為使能(enable)端期奔,寫(xiě)操作時(shí)侧馅,下降沿使能。讀操作時(shí)呐萌,E高電平有效馁痴。

讀操作時(shí)序圖:


讀操作時(shí)序圖

寫(xiě)操作時(shí)序圖:


寫(xiě)操作時(shí)序圖

時(shí)序時(shí)間參數(shù):


時(shí)序時(shí)間參數(shù)

3.4 LCD1602的指令說(shuō)明

1602液晶模塊內(nèi)部的控制器共有11條控制指令:


LCD1602控制命令表

?? 1602液晶模塊的讀寫(xiě)操作、屏幕和光標(biāo)的操作都是通過(guò)指令編程來(lái)實(shí)現(xiàn)的肺孤。

指令1:清顯示罗晕,指令碼01H,光標(biāo)復(fù)位到地址00H位置赠堵。
說(shuō)明:清除屏幕顯示內(nèi)容小渊。光標(biāo)返回屏幕左上角。執(zhí)行這個(gè)指令時(shí)需要一定時(shí)間茫叭。
指令2:光標(biāo)復(fù)位酬屉,光標(biāo)返回到地址00H。
說(shuō)明:光標(biāo)返回屏幕左上角,它不改變屏幕顯示內(nèi)容呐萨。
指令3:光標(biāo)和顯示模式設(shè)置

進(jìn)入模式設(shè)置指令

I/D=1:寫(xiě)入新數(shù)據(jù)后光標(biāo)右移杀饵。
I/D=0:寫(xiě)入新數(shù)據(jù)后光標(biāo)左移。
S=1:顯示移動(dòng)谬擦。
S=0:顯示不移動(dòng)切距。
說(shuō)明:這里的設(shè)置是0x06。

指令4:顯示開(kāi)關(guān)控制惨远。

顯示開(kāi)關(guān)控制指令

D=1:顯示開(kāi)谜悟,D=0:顯示關(guān)。
C=1:光標(biāo)顯示锨络,C=0:光標(biāo)不顯示。
B=1:光標(biāo)閃爍狼牺,B=0:光標(biāo)不閃爍羡儿。
說(shuō)明:這里的設(shè)置是顯示開(kāi),不顯示光標(biāo)是钥,光標(biāo)不閃爍掠归,設(shè)置字為0x0c。

指令5:光標(biāo)或顯示移位

光標(biāo)或顯示移動(dòng)指令

光標(biāo)或顯示移動(dòng)指令說(shuō)明

說(shuō)明:在需要進(jìn)行整屏移動(dòng)時(shí)悄泥,這個(gè)指令非常有用虏冻,可以實(shí)現(xiàn)屏幕的滾動(dòng)顯示效果。初始化時(shí)不使用這個(gè)指令弹囚。

指令6:功能設(shè)置命令

工作方式設(shè)置指令

×:不關(guān)心厨相,也就是說(shuō)這個(gè)位是0或1都可以,一般取0鸥鹉。
DL:設(shè)置數(shù)據(jù)接口位數(shù)蛮穿。
DL=1:8位數(shù)據(jù)接口(D7—D0)。
DL=0:4位數(shù)據(jù)接口(D7—D4)毁渗。
N=0:一行顯示践磅。
N=1:兩行顯示。
F=0:5×8點(diǎn)陣字符灸异。
F=1:5×10點(diǎn)陣字符府适。
說(shuō)明:因?yàn)槭菍?xiě)指令字,所以RS和RW都是0肺樟。LCD1602只能用并行方式驅(qū)動(dòng)檐春,不能用串行方式驅(qū)動(dòng)。而并行方式又可以選擇8位數(shù)據(jù)接口或4位數(shù)據(jù)接口么伯。這里我們選擇4位數(shù)據(jù)接口(D3—D0)喇聊。我們的設(shè)置是4位數(shù)據(jù)接口,兩行顯示蹦狂,5×8點(diǎn)陣誓篱,即0b00101000也就是0x28朋贬。(注意:NF是10或11的效果是一樣的,都是兩行5×8點(diǎn)陣窜骄。因?yàn)樗荒芤詢尚?×10點(diǎn)陣方式進(jìn)行顯示锦募,換句話說(shuō),這里用0x28或0x2c是一樣的)邻遏。

指令7:字符發(fā)生器CGRAM地址設(shè)置糠亩。

設(shè)置CGRAM地址指令

指令8:DDRAM地址設(shè)置。

設(shè)置DDRAM地址指令

說(shuō)明:這個(gè)指令用于設(shè)置DDRAM地址准验。在對(duì)DDRAM進(jìn)行讀寫(xiě)之前赎线,首先要設(shè)置DDRAM地址,然后才能進(jìn)行讀寫(xiě)糊饱。前面我們說(shuō)過(guò)垂寥,DDRAM就是LCD1602的顯示存儲(chǔ)器。我們要在它上面進(jìn)行顯示另锋,就要把要顯示的字符寫(xiě)入DDRAM滞项。同樣,我們想知道DDRAM某個(gè)地址上有什么字符夭坪,也要先設(shè)置DDRAM地址文判,然后將它讀出到單片機(jī)。

指令9:讀忙信號(hào)和光標(biāo)地址

讀忙信號(hào)和地址計(jì)數(shù)器AC

BF:為忙標(biāo)志位室梅,高電平表示忙戏仓,此時(shí)模塊不能接收命令或者數(shù)據(jù)。如果為低電平表示不忙亡鼠。
說(shuō)明:這個(gè)指令用來(lái)讀取LCD1602狀態(tài)柜去。對(duì)于單片機(jī)來(lái)說(shuō),LCD1602屬于慢速設(shè)備拆宛。當(dāng)單片機(jī)向其發(fā)送一個(gè)指令后嗓奢,它將去執(zhí)行這個(gè)指令。這時(shí)如果單片機(jī)再次發(fā)送下一條指令浑厚,由于LCD1602速度較慢股耽,前一條指令還未執(zhí)行完畢,它將不接受這新的指令钳幅,導(dǎo)致新的指令丟失物蝙。因此這條讀忙指令可以用來(lái)判斷LCD1602是否忙,能否接收單片機(jī)發(fā)來(lái)的指令敢艰。當(dāng)BF=1诬乞,表示LCD1602正忙,不能接受單片機(jī)的指令;當(dāng)BF=0震嫉,表示LCD1602空閑森瘪,可以接收單片機(jī)的指令。RS=0票堵,表示是指令扼睬;RW=1,表示是讀取悴势。這條指令還有一個(gè)副產(chǎn)品:即可以得到地址記數(shù)器AC的值(address counter)窗宇。LCD1602維護(hù)了一個(gè)地址計(jì)數(shù)器AC,用來(lái)記錄下一次讀寫(xiě)CGRAM或DDRAM的位置特纤。需要強(qiáng)調(diào)的是:這條指令我一次也沒(méi)有執(zhí)行成功军俊。很多網(wǎng)友似乎也是這樣。好在我們有另外的辦法捧存,也就是延時(shí)粪躬。通過(guò)查看每條指令的執(zhí)行時(shí)間,再經(jīng)過(guò)一些試驗(yàn)矗蕊,可以確定指令的延時(shí)短蜕。這樣就可以在上一條指令執(zhí)行完畢后再執(zhí)行下一條指令了氢架。
指令10:寫(xiě)數(shù)據(jù)傻咖。

寫(xiě)數(shù)據(jù)到CGRAM或DDRAM指令

說(shuō)明:RS=1,數(shù)據(jù)岖研;RW=0卿操,寫(xiě)。指令執(zhí)行時(shí)孙援,要在DB7—DB0上先設(shè)置好要寫(xiě)入的數(shù)據(jù)害淤,然后執(zhí)行寫(xiě)命令。

指令11:讀數(shù)據(jù)拓售。

從CGRAM或DDRAM讀數(shù)據(jù)指令

說(shuō)明:RS=1窥摄,數(shù)據(jù);RW=1础淤,讀崭放。先設(shè)置好CGRAM或DDRAM的地址,然后執(zhí)行讀取命令鸽凶。數(shù)據(jù)就被讀入后DB7—DB0币砂。

3.5 初始化

??如果電路電源能滿足內(nèi)部RESET電路的如下要求, 初始化可自動(dòng)完成:


自動(dòng)初始化

??如果電路電源不能滿足內(nèi)部RESET電路的要求的話,需要用初始化程序來(lái)實(shí)現(xiàn)初始化玻侥,有8位總線和4位總線兩種模式决摧。

8位數(shù)據(jù)傳輸模式:


8位總線模式初始化

本次實(shí)驗(yàn)中使用4位數(shù)據(jù)傳輸模式:


4位總線初始化參數(shù)示例

3.6 DDRAM地址

1602字符液晶顯示可分為上下兩部分各16位進(jìn)行顯示,處于不同行時(shí)的字符顯示地址如下:

顯示字符 1 2 3 4 ...... 12 13 14 15 16
第一行地址 00H 01H 02H 03H ...... 0BH 0CH 0DH 0EH 0FH
第二行地址 40H 41H 42H 43H ...... 4BH 4CH 4DH 4EH 4FH

?? 按照上面指令8格式所示,由于地址為7位掌桩,在寫(xiě)入地址時(shí)边锁,第8位D7恒為1。當(dāng)我們想在指定位置寫(xiě)入內(nèi)容時(shí)拘鞋,要先指定地址砚蓬,如在第一行第一位寫(xiě)入,地址位是00H盆色,再加上DB7的1灰蛙,即80H(0010000000),第二行第一位是40H隔躲,再加上DB7的1摩梧,即C0H(0011000000),依次類推宣旱。

四仅父、實(shí)驗(yàn)步驟

??第1步:連接電路。連接電源打開(kāi)樹(shù)莓派浑吟,顯示屏就會(huì)亮笙纤,同時(shí)在第一行顯示一排黑方塊。如果看不到黑方塊或黑方塊不明顯组力,請(qǐng)調(diào)節(jié)可調(diào)電阻省容,直到黑方塊清晰顯示。如果調(diào)節(jié)可調(diào)電阻還看不到方塊燎字,則可能你的連接有問(wèn)題了腥椒,請(qǐng)檢查連接,包括檢查顯示屏的引腳有沒(méi)有虛焊候衍。

樹(shù)莓派 T型轉(zhuǎn)接板 LCD1602
SCL SCL SCL
SDA SDA SDA
5V 5V VCC
GND GND GND
LCD1602實(shí)驗(yàn)電路圖
LCD1602實(shí)驗(yàn)實(shí)物接線圖

??第2步:PCF8591模塊采用的是I2C(IIC)總線進(jìn)行通信的笼蛛,但是在樹(shù)莓派的鏡像中默認(rèn)是關(guān)閉的,在使用該傳感器的時(shí)候蛉鹿,我們必須首先允許IIC總線通信滨砍。

打開(kāi)I2C總線通信

??第3步:查詢LCD1602的地址。得出地址為0x27妖异。

pi@raspberrypi:~ $  ls /dev/i2c-*
/dev/i2c-1
pi@raspberrypi:~ $ sudo i2cdetect -y 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                        

??第4步:編寫(xiě)驅(qū)動(dòng)程序惋戏。這里先編寫(xiě)一個(gè)LCD1602.py文件,后面再編寫(xiě)一個(gè)python程序引入這個(gè)庫(kù)文件随闺,調(diào)用這個(gè)文件中的函數(shù)實(shí)現(xiàn)更復(fù)雜的功能日川。
??LCD1602.py文件就相當(dāng)于是LCD1602模塊的驅(qū)動(dòng)程序,單獨(dú)編寫(xiě)是為了便于重用矩乐。
??該程序也可以單獨(dú)運(yùn)行龄句,會(huì)在第一行顯示“Hello”回论,在第二行顯示“world!”。

#!/usr/bin/env python

import time
import smbus  #SMBus (System Management Bus,系統(tǒng)管理總線) 在程序中導(dǎo)入“smbus”模塊

BUS = smbus.SMBus(1)   #創(chuàng)建一個(gè)smbus實(shí)例
# 0 代表 /dev/i2c-0分歇, 1 代表 /dev/i2c-1 ,具體看使用的樹(shù)莓派那個(gè)I2C來(lái)決定
def write_word(addr, data):
    global BLEN   #該變量為1表示打開(kāi)LCD背光傀蓉,若是0則關(guān)閉背光
    temp = data
    if BLEN == 1:
        temp |= 0x08  #0x08=0000 1000,表開(kāi)背光
        #buf |= 0x08等價(jià)于buf = buf | 0x08(按位或)
    else:
        temp &= 0xF7  #0xF7=1111 0111职抡,表關(guān)閉背光
        #buf &= 0xF7等價(jià)于buf = buf & 0xF7(按位與)
    BUS.write_byte(addr ,temp)  #這里為什么又一次寫(xiě)入8位葬燎??缚甩?谱净??擅威?
    #write_byte(int addr, char val)發(fā)送一個(gè)字節(jié)到設(shè)備

def send_command(comm):
    # Send bit7-4 firstly
    buf = comm & 0xF0   #與運(yùn)算壕探,取高四位數(shù)值
    #由于4位總線的接線是接到P0口的高四位,傳送高四位不用改
    buf |= 0x04    #buf |= 0x04等價(jià)于buf = buf | 0x04(按位或)0x04=0000 0100
    # RS = 0, RW = 0, EN = 1 
    #為什么這樣寫(xiě)入代表RS = 0, RW = 0, EN = 1郊丛,低4位在這里有何意義李请??厉熟?导盅??揍瑟?白翻??
    write_word(LCD_ADDR ,buf)  #為什么這里又是8位寫(xiě)入月培?嘁字?恩急?杉畜??
    time.sleep(0.002)
    buf &= 0xFB    #buf &= 0xFB等價(jià)于buf = buf & 0xFB(按位與)0xFB=1111 1011
    # Make EN = 0衷恭,EN從1——>0此叠,下降沿,進(jìn)行寫(xiě)操作
    #為什么這樣寫(xiě)入代表Make EN = 0随珠?灭袁??窗看?茸歧??显沈?软瞎?
    write_word(LCD_ADDR ,buf)

    # Send bit3-0 secondly
    buf = (comm & 0x0F) << 4  #與運(yùn)算逢唤,取低四位數(shù)值,
    #由于4位總線的接線是接到P0口的高四位涤浇,所以要再左移4位
    buf |= 0x04               
    # RS = 0, RW = 0, EN = 1 寫(xiě)入命令
    write_word(LCD_ADDR ,buf)
    time.sleep(0.002)
    buf &= 0xFB               # Make EN = 0
    write_word(LCD_ADDR ,buf)

def send_data(data):
    # Send bit7-4 firstly
    buf = data & 0xF0
    buf |= 0x05               # RS = 1, RW = 0, EN = 1 寫(xiě)入數(shù)據(jù)
    write_word(LCD_ADDR ,buf)
    time.sleep(0.002)
    buf &= 0xFB               # Make EN = 0
    write_word(LCD_ADDR ,buf)

    # Send bit3-0 secondly
    buf = (data & 0x0F) << 4
    buf |= 0x05               # RS = 1, RW = 0, EN = 1 寫(xiě)入數(shù)據(jù)
    write_word(LCD_ADDR ,buf)
    time.sleep(0.002)
    buf &= 0xFB               # Make EN = 0
    write_word(LCD_ADDR ,buf)

def init(addr, bl):  #LCD1602初始化
    global LCD_ADDR  #該變量為設(shè)備地址
    global BLEN      #該變量為1表示打開(kāi)LCD背光鳖藕,若是0則關(guān)閉背光
    LCD_ADDR = addr
    BLEN = bl
    try:
        send_command(0x33) # 必須先初始化為8行模式   110011 Initialise
        time.sleep(0.005)
        send_command(0x32) # 然后初始化為4行模式   110010 Initialise
        time.sleep(0.005)
        send_command(0x28) # 4位總線,雙行顯示只锭,顯示5×8的點(diǎn)陣字符著恩。
        time.sleep(0.005)
        send_command(0x0C) # 打開(kāi)顯示屏,不顯示光標(biāo)蜻展,光標(biāo)所在位置的字符不閃爍
        time.sleep(0.005)
        send_command(0x01) # 清屏幕指令喉誊,將以前的顯示內(nèi)容清除
        time.sleep(0.005)
        send_command(0x06) # 設(shè)置光標(biāo)和顯示模式,寫(xiě)入新數(shù)據(jù)后光標(biāo)右移纵顾,顯示不移動(dòng)
        BUS.write_byte(LCD_ADDR, 0x08)  #這里這樣寫(xiě)入0x08是什么意思裹驰??片挂?幻林??音念?
    except:
        return False
    else:
        return True

def clear():
    send_command(0x01) # 清屏


def write(x, y, str):
    if x < 0:   #LCD1602只有16列沪饺,2行顯示,小于第0列的數(shù)據(jù)要做修正
        x = 0
    if x > 15:  #LCD1602只有16列闷愤,2行顯示整葡,大于第15列的數(shù)據(jù)要做修正
        x = 15
    if y <0:    #LCD1602只有16列,2行顯示,小于第0行的數(shù)據(jù)要做修正
        y = 0
    if y > 1:   #LCD1602只有16列像吻,2行顯示但狭,大于第1行的數(shù)據(jù)要做修正
        y = 1

    # 移動(dòng)光標(biāo)
    addr = 0x80 + 0x40 * y + x  
    #第一行第一位的地址為0x00,加上D7恒為1俱萍,所以第一行第一位的地址為0x80
    #第二行第一位是0x40,加上D7恒為1告丢,所以第二行第一位的地址為0x80加上0x40枪蘑,最后為0xC0
    send_command(addr)       #設(shè)置顯示位置

    for chr in str:
        send_data(ord(chr))  #發(fā)送顯示內(nèi)容
        #ord()函數(shù)以一個(gè)字符(長(zhǎng)度為1的字符串)作為參數(shù),
        #返回對(duì)應(yīng)的 ASCII 數(shù)值岖免,或者 Unicode 數(shù)值

if __name__ == '__main__':
    init(0x27, 1)  #在樹(shù)莓派終端上使用命令'sudo i2cdetect -y 1'查詢?cè)O(shè)備地址為0x27
    # 第二個(gè)參數(shù)1表示打開(kāi)LCD背光岳颇,若是0則關(guān)閉背光
    write(4, 0, 'Hello')  #4,0參數(shù)指顯示的起始位置為第4列颅湘,第0行
    write(7, 1, 'world!') #7话侧,1參數(shù)指顯示的起始位置為第7列,第1行
    #‘Hello’為要顯示的字符串
            

??第5步:編寫(xiě)控制程序闯参。先是靜態(tài)顯示內(nèi)容:第一行顯示“Greetings!!”瞻鹏,第二行顯示“Welcome here!”术羔,持續(xù)2秒。之后動(dòng)態(tài)滾動(dòng)顯示“Thank you for buying Raspberry! _”乙漓。
??

#!/usr/bin/env python
import LCD1602
import time

def setup():
    LCD1602.init(0x27, 1)   # init(slave address, background light)
    LCD1602.write(0, 0, 'Greetings!!')
    LCD1602.write(1, 1, 'Welcome here!')
    time.sleep(2)

def loop():
    space = '                '
    greetings = 'Thank you for buying Raspberry! ^_^'
    greetings = space + greetings
    while True:
        tmp = greetings
        for i in range(0, len(greetings)):
            LCD1602.write(0, 0, tmp)    #當(dāng)要顯示的字符串過(guò)長(zhǎng)時(shí)级历,會(huì)自動(dòng)在LCD的第二行顯示
            tmp = tmp[1:]   #每次循環(huán)去掉字符串首位字符,實(shí)現(xiàn)字幕向左移動(dòng)的效果
            time.sleep(0.8)
            LCD1602.clear()

def destroy():
    pass    

if __name__ == "__main__":
    try:
        setup()
        while True:
            loop()
    except KeyboardInterrupt:
        destroy()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末叭披,一起剝皮案震驚了整個(gè)濱河市寥殖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌涩蜘,老刑警劉巖嚼贡,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異同诫,居然都是意外死亡粤策,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)误窖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)叮盘,“玉大人,你說(shuō)我怎么就攤上這事霹俺∪岷穑” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵丙唧,是天一觀的道長(zhǎng)愈魏。 經(jīng)常有香客問(wèn)我,道長(zhǎng)想际,這世上最難降的妖魔是什么培漏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮胡本,結(jié)果婚禮上牌柄,老公的妹妹穿的比我還像新娘。我一直安慰自己打瘪,他們只是感情好友鼻,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布傻昙。 她就那樣靜靜地躺著闺骚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妆档。 梳的紋絲不亂的頭發(fā)上僻爽,一...
    開(kāi)封第一講書(shū)人閱讀 51,482評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音贾惦,去河邊找鬼胸梆。 笑死敦捧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的碰镜。 我是一名探鬼主播兢卵,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼绪颖!你這毒婦竟也來(lái)了秽荤?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤柠横,失蹤者是張志新(化名)和其女友劉穎窃款,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體牍氛,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晨继,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了搬俊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片紊扬。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖唉擂,靈堂內(nèi)的尸體忽然破棺而出珠月,到底是詐尸還是另有隱情,我是刑警寧澤楔敌,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布啤挎,位于F島的核電站,受9級(jí)特大地震影響卵凑,放射性物質(zhì)發(fā)生泄漏庆聘。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一勺卢、第九天 我趴在偏房一處隱蔽的房頂上張望伙判。 院中可真熱鬧,春花似錦黑忱、人聲如沸宴抚。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)菇曲。三九已至,卻和暖如春抚吠,著一層夾襖步出監(jiān)牢的瞬間常潮,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工楷力, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留喊式,地道東北人孵户。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像岔留,于是被迫代替她去往敵國(guó)和親夏哭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354