ESP32实验03:0.96tft液晶显示屏驱动
基于ST7735s的0.96寸tft屏幕顯示
效果展示
- 實(shí)現(xiàn)了時(shí)鐘顯示,基于ds1307模塊,時(shí)鐘字體采用的模擬數(shù)碼管字體
- 實(shí)現(xiàn)了圖標(biāo)顯示,后續(xù)用于天氣以及狀態(tài)指示
- 暫未添加網(wǎng)絡(luò)校時(shí),以及網(wǎng)絡(luò)獲取天氣數(shù)據(jù)等功能
- 界面顯示沒(méi)有采用第三方庫(kù)(暫未找到合適的),采用原始的一個(gè)一個(gè)圖標(biāo)畫點(diǎn)顯示
整個(gè)實(shí)驗(yàn)斷斷續(xù)續(xù)耗時(shí)接近快2周時(shí)間,主要消耗的精力的有幾個(gè)方面
本文的重點(diǎn)講解的方面也就是上述3個(gè)采坑較多的地方,最后一部分就簡(jiǎn)單展示下關(guān)鍵的代碼,具體的代碼連接間本文末尾。話不多講,開(kāi)始正文部分。
1、模塊及開(kāi)發(fā)環(huán)境簡(jiǎn)介
tft屏幕參數(shù)
分辨率:160*80
驅(qū)動(dòng)芯片:ST7735S
通信接口:SPI
供電電壓:3.3V
tft屏幕與ESP32模塊連線
| GND | GND |
| VCC | 3.3v |
| SCL | 19(CLK) |
| SDA | 23(MOSI) |
| DC | 21 |
| RST | 18 |
其中
DC引腳用于控制spi總線傳輸?shù)氖敲钸€是數(shù)據(jù)。
DC:0傳送命令,DC:1傳送數(shù)數(shù)據(jù),可以這么理解,要向st7735某個(gè)寄存器寫入值,那么一般的邏輯是,先傳輸寄存器地址,再傳輸數(shù)據(jù)。當(dāng)傳輸?shù)刂非?#xff0c;DC引腳置為low,當(dāng)傳輸數(shù)據(jù)前,DC引腳置為high。也就是說(shuō)DC引腳實(shí)際控制的是接下來(lái)是要寫地址還是寫數(shù)據(jù)。
RST引腳是硬件復(fù)位tft屏幕,當(dāng)RST=0時(shí),硬件復(fù)位。需要將RST=1然后重新初始化屏幕,才能正常顯示。正常如果不用該引腳可以直接用上拉電阻拉高。在程序中,初始化前,需要將該引腳拉高。
開(kāi)發(fā)環(huán)境
開(kāi)發(fā)環(huán)境 vscode + platformIO
開(kāi)發(fā)框架 esp-idf
開(kāi)發(fā)語(yǔ)言 C
2、ST7735S說(shuō)明
備注:ST775S是內(nèi)置的tft屏幕面板內(nèi)部的,一般情況下是看不到該芯片的樣子。 所以不要拿到了屏幕模塊后就想拆開(kāi)看下ST7735芯片長(zhǎng)啥樣子,其實(shí),筆者也很好奇芯片的樣子。
2.1主要特性
支持3線或者4線SPI(區(qū)別在于3線沒(méi)有用DC pin)
支持8位/16位并行接口
數(shù)據(jù)顯示RAM 132H18RGB162V bits
顏色深度最高支持262K顏色,通常用的是64K
供電電壓3.15V to 5V
最大分辨率132*162
2.2 3&4線spi數(shù)據(jù)圖
3線spi實(shí)際每次傳輸?shù)臄?shù)據(jù)是9bit,最高為實(shí)現(xiàn)的就是DC引腳功能。
4線spi采用DC硬件引腳控制寫命令和寫數(shù)據(jù)。正常來(lái)說(shuō)選擇3線還是4線,屏幕在出廠的時(shí)候就確定了。3線還是4線是由ST7735內(nèi)部的SPI4W引腳來(lái)決定的。目前市面上默認(rèn)的液晶屏都是采用4線模式
選擇是串口還是spi實(shí)際也是出廠就設(shè)置好了的,其由內(nèi)部的IM2引腳來(lái)確定。
所以不要妄想將買到的并口屏幕改為spi串行通信,除非將整個(gè)屏幕拆開(kāi),重新連線,這基本是不現(xiàn)實(shí)的。
2.3初始化注意事項(xiàng)
在屏幕初始化過(guò)程中,會(huì)對(duì)st7735中的多個(gè)寄存器進(jìn)行賦值,其中有一些寄存器的值直接影響到屏幕的點(diǎn)亮和顯示,現(xiàn)將調(diào)試過(guò)程中出現(xiàn)的一些重要的寄存器初始化進(jìn)行說(shuō)明。
**10h Sleep In & 11h Sleep Out **
進(jìn)入睡眠模式,上電后,或者軟件或者硬件重置后,屏幕默認(rèn)進(jìn)入sleep 模式,此時(shí)屏幕是不會(huì)有任何顯示的。
退出睡眠模式只有一個(gè)方式,通過(guò)設(shè)置11h
初始化時(shí)只需要將11h中寫入0 即可。
**28h DisplayOff & 29h Display On **
上電默認(rèn)是顯示關(guān)閉模式,初始化時(shí)需要將液晶設(shè)置為顯示開(kāi)啟模式
初始化時(shí)只需要將 29h中寫入0即可打開(kāi)顯示開(kāi)啟模式。
** 3ah Interface Pixel Format **
屏幕色彩格式,設(shè)置屏幕的色彩位數(shù)。通常應(yīng)用情況下,采用的都是16bit色彩模式,也就是常說(shuō)的64K顏色。上電默認(rèn)是18bit顏色。
初始化時(shí),只需要在31h中寫入5,即可將其設(shè)置為64K色模式。
2.4液晶顯示原理分析
與屏幕顯示位置及顯示方向相關(guān)的寄存器主要有:
36h Memory Data Access Control 內(nèi)存數(shù)據(jù)控制,用于控制,屏幕(0,0)原點(diǎn)的位置,及x軸和y軸的方向
2ah 列地址設(shè)置寄存器
2bh 行地址設(shè)置寄存器
2c 內(nèi)存寫入寄存器,某個(gè)像素點(diǎn)顯示的顏色數(shù)據(jù)
其中最需要耗時(shí)也最需要深入了解的是36h寄存器,其涉及到屏幕的顯示方向及顯示位置。
36h 寄存器
在談寄存器具體內(nèi)容及含義前,先說(shuō)明下一般比較推薦的顯示方式。
一般是針對(duì)屏幕,將屏幕的左上腳默認(rèn)為屏幕原點(diǎn)(0,0),X軸往右,Y軸往下。掃描方向,從左到右,從上到下,這比較符合人正常的書寫順序。可能不太好理解掃描,舉個(gè)簡(jiǎn)單的例子
比如要在屏幕上顯示8bit英文 HELLO WORLD
那么 H 起始坐標(biāo) (0,0),終點(diǎn)坐標(biāo) (7,7)
E 起始坐標(biāo) (8,0),終點(diǎn)坐標(biāo)(15,7)
。。。。。
依次類推,那么D的起始和終點(diǎn)坐標(biāo)分別是(80,0)(87,7)
顯示的步驟如下
1、 設(shè)置行列地址,起始坐標(biāo)和終點(diǎn)坐標(biāo)
2、向屏幕內(nèi)存寫入每個(gè)像素點(diǎn)的顏色數(shù)據(jù)
3、屏幕將內(nèi)存中的數(shù)據(jù)按照掃描順序顯示在屏幕上
掃描順序從左到右,則先顯示(0,0)到(7,7)區(qū)域的 H,顯示順序 H -> E -> …-> D
如果是從右向左,則先顯示(80,0)(87,7)的D-> L … -> H
上下掃描也是如此,如果有多行,上下掃描,顯示上衣行再顯示下一行,如果是下上掃描,則先顯示下一行再顯示上一行。
一般情況下,不影響最終顯示結(jié)果,但是為了便于理解和習(xí)慣,推薦掃描順序從左到右,從上到小
再回到36h寄存器本身
MY 是鏡像Y軸
MX是鏡像X軸
MV是XY軸調(diào)換位置
以上圖為例,假設(shè)此時(shí) MY =0; MX =0 ,MV =0 則
當(dāng)MY=1 MX =0 ,MV =0,坐標(biāo)原點(diǎn)在左下角
當(dāng)MY=0 MX =1 ,MV =0,坐標(biāo)原點(diǎn)在右上角
當(dāng)MY=1 MX =1 ,MV =0,坐標(biāo)原點(diǎn)在右下角
ML 豎直方向掃描順序
MH水平方向掃描順序
通常都設(shè)置為0 從左到右,從上到下
屏幕原點(diǎn)的方向就依靠36H寄存器進(jìn)行調(diào)整,當(dāng)拿到一個(gè)新的屏幕的時(shí)候,就要選擇屏幕的坐標(biāo)原點(diǎn),通過(guò)調(diào)整36H,實(shí)現(xiàn)正對(duì)屏幕,原點(diǎn)位于左上角。
**2ah列地址設(shè)置 **
列地址對(duì)應(yīng)的是X軸,其由4個(gè)字節(jié)組成,第一個(gè)字節(jié)是起始地址高8位,第二個(gè)字節(jié)是起始地址低8為,第三個(gè)字節(jié)是終點(diǎn)坐標(biāo)高8位,第四個(gè)字節(jié)是終點(diǎn)坐標(biāo)低8位。
這一值得注意的是,采用的大端模式,低地址存儲(chǔ)的高位字節(jié),高地址存儲(chǔ)的低位字節(jié)。
比如如果地址是0xa0b1,則傳輸大端模式是應(yīng)該先傳輸0xa0,然后是0xb1;通常的用小端模式都是先傳輸0xb1然后是0xa0
**2bh行地址設(shè)置 **
行地址方式與列地址完全一致,就不過(guò)多說(shuō)明。
再說(shuō)下st7735屏幕分辯率的選擇。ST7735最大支持兩種分辨率 132162和128160
到底最大支持哪種分辨率是在屏幕模塊一出廠就確定了的,其取決月GM1和GM0兩個(gè)引腳
由于筆者用的屏幕是160*80所以不管是哪種方式,都不受影響。這主要是山寨屏幕,沒(méi)有出場(chǎng)說(shuō)明書,不知道出場(chǎng)的配置是怎么樣的。這里當(dāng)時(shí)也想了好久才想明白。
這張圖里面實(shí)際上就將36h的設(shè)置寫明白了。看圖吧就不多贅述了。
3、文字取模和圖片取模軟件
文字取模和圖片取模軟件都是將要在屏幕上顯示的轉(zhuǎn)化成為一個(gè)色彩集合數(shù)組。顯示是設(shè)置好地址后將該數(shù)組按照順序?qū)懭肫聊粌?nèi)存,最終在屏幕上顯示。這里面也有一些坑,如果沒(méi)注意,可能會(huì)顯示不正常。在此一次將這兩種取模軟件整理清楚。
3.1文字取模軟件
文字取模軟件通常使用的是PCtoLCD2002,界面如下圖
其中的關(guān)鍵點(diǎn)主要是在設(shè)置選項(xiàng)里面。
那么一個(gè)一個(gè)來(lái)測(cè)試,以生活的“生”字為例:
| 陰碼 | 逐行 | 逆向 | 0x80,0x00,0x88,0x00,0x88,0x00,0x88,0x00,0xFC,0x3F,0x84,0x00,0x82,0x00,0x81,0x00, 0x80,0x00,0xFC,0x1F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x7F,0x00,0x00 |
| 陰碼 | 逐行 | 順向 | 0x01,0x00,0x11,0x00,0x11,0x00,0x11,0x00,0x3F,0xFC,0x21,0x00,0x41,0x00,0x81,0x00, 0x01,0x00,0x3F,0xF8,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xFF,0xFE,0x00,0x00, |
| 陰碼 | 逐列 | 順向 | 0x01,0x02,0x02,0x02,0x0C,0x42,0x78,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0xFF,0xFE, 0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x42,0x08,0x02,0x00,0x02,0x00,0x00, |
| 陰碼 | 逐列 | 逆向 | 0x80,0x40,0x40,0x40,0x30,0x42,0x1E,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0xFF,0x7F, 0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x42,0x10,0x40,0x00,0x40,0x00,0x00, |
陰碼:需要點(diǎn)亮的點(diǎn)為1,如上圖,生活的“生”字最上面一個(gè)點(diǎn)占的bit7,如果是左往右寫點(diǎn)就是0x80。
逐行就是從左往右一個(gè)bit一個(gè)bit點(diǎn)亮數(shù)碼管,逆向是低位在前,順向是高位在前
分析表格最上面兩行,逆向第一個(gè)字節(jié)是0x80,順向第一個(gè)字節(jié)是0x01,將二者轉(zhuǎn)換為二進(jìn)制
| 逆向 | 0x80 | 1000 0000 |
| 順向 | 0x01 | 0000 0001 |
逆向順向的區(qū)別是轉(zhuǎn)成二進(jìn)制后,二者順序顛倒。
如圖數(shù)碼管,假設(shè)地址(0,0)在左上角。如果要顯示“生”字最上面的一個(gè)點(diǎn)
逆向:寫入順序(0,0)(1,0)(2,0)(3,0)(4,0)(5,0)… (7,0)
順向:寫入順序(7,0)(6,0)… (2,0)(1,0)(0,0)
都是在(7,0)坐標(biāo)寫入1,其他未寫入0,則點(diǎn)亮了“生”字最上面的一個(gè)點(diǎn)。對(duì)應(yīng)到tft屏幕寫入的就是顏色需要點(diǎn)亮就寫入前景色,需要滅的就寫入背景色。
這里要注意:在寫代碼向st7735的2c寄存器寫入的時(shí)候,逆向時(shí)要先判斷bit0的值,如果是1則寫入前景,0背景,然后是bit1,bit2…。順向的時(shí)候,則要先判斷bit7的值,然后bit6,bit5…
當(dāng)設(shè)置逐列時(shí),則寫入順序?yàn)?br /> 逆向:(0,0)(0,1)(0,2)… (0,7)
順向:(0,7)(0,6)…(0,1) (0,0)
再此就不在進(jìn)行二進(jìn)制轉(zhuǎn)換分析了。感興趣的可以自行研究下
從上述取模方式來(lái)看,由于st7735我們推薦的掃描方式是從左到右從上到小,這對(duì)應(yīng)的取模順序是逐行,逆向。所以只要任何屏幕我們都采用這種方式的時(shí)候,取模時(shí)就可以固定逐行+逆向。
3.2圖片取模軟件
圖片取模軟件通常使用的是Image2Lcd V2.9版本。其機(jī)密如下圖所示
掃描模式與文字取模一致,16位真彩色,取出來(lái)的數(shù)組一共是3200個(gè),40402。每個(gè)像素點(diǎn)顏色占2個(gè)字節(jié)。
這里的高位在前,是色彩的高8字節(jié)在前。正常顏色0xfbba,正常生成的數(shù)組是,0xba,0xfb。高位在前則為:0xfb,0xba。
這與文字取模里的順向和逆向是有區(qū)別的。
正常情況下建議,采用默認(rèn)的低位在前的方式。
3.3圖片取單色模
如果要將上述的qq圖片成為40*40單色顯示,直接用Image2Lcd設(shè)置為單色是不行的。經(jīng)過(guò)多次測(cè)試,這種方法取出模,數(shù)組是錯(cuò)誤的。
正確的方式是:
1、先用Image2Lcd將圖片保存為單色圖片
2、再將單色圖片導(dǎo)入到文字取模軟件PCtoLcd2002中,
3、生成數(shù)組。陰碼,逐行式,逆向
單色qq圖片文字取模軟件取模結(jié)果如下。共有200個(gè)字節(jié),40*40/8 每8個(gè)像素點(diǎn)占用一個(gè)字節(jié)
0x00,0x00,0x30,0x00,0x00,0x00,0x00,0xFE,0x03,0x00,0x00,0x80,0xFF,0x0F,0x00,0x00, 0x60,0xFE,0x1F,0x00,0x00,0xB0,0xFF,0x7F,0x00,0x00,0xF8,0xFF,0x7F,0x00,0x00,0xFC, 0xFF,0xFF,0x00,0x00,0xFC,0xF1,0xFC,0x01,0x00,0xFE,0xF3,0xF9,0x01,0x00,0xFE,0xF0, 0xF9,0x03,0x00,0xFF,0xB0,0xF8,0x03,0x08,0xFF,0x30,0xF8,0x03,0x1F,0xFF,0x70,0xF8, 0x03,0x3E,0xFF,0xFF,0xFC,0x03,0x7E,0xFF,0xFF,0xFF,0x07,0xFC,0x7F,0x00,0xFC,0x07, 0xF8,0x1F,0x00,0xF0,0x0F,0xF8,0x5F,0x00,0xEC,0x0F,0xF0,0xFF,0x01,0xFE,0x0F,0xE0, 0xFF,0xFF,0xFF,0x0F,0xC0,0xDF,0xFF,0xFF,0x1F,0x80,0x7F,0xFC,0xFF,0x3F,0x80,0xFF, 0xE7,0xFF,0x3F,0x80,0xF9,0xFF,0xFF,0x7E,0x80,0xE1,0xFF,0x7F,0x7C,0x80,0x01,0xFE, 0x7F,0xFC,0x80,0x01,0x00,0x7E,0xFC,0x80,0x01,0x00,0x7E,0xFC,0x80,0x01,0x00,0x7E, 0xFC,0x00,0x01,0x00,0x7E,0xEE,0x00,0x03,0x00,0x3C,0xC6,0x00,0x02,0x00,0x00,0x07, 0x00,0x06,0x00,0x00,0x03,0x00,0x0C,0x00,0x80,0x03,0x00,0x19,0x00,0xC0,0x04,0x80, 0x30,0x00,0x70,0x08,0x80,0xC0,0x01,0x3C,0x08,0x80,0x00,0xDF,0x0F,0x08,0x00,0x03, 0x8C,0x01,0x04,0x00,0xFC,0x03,0xFE,0x03,/*"C:\Users\yp\Downloads\0.96TFT測(cè)試程序\0.96TFT測(cè)試程序\圖片取模軟件(贈(zèng)送)\單色qq.bmp",0*/ /* (40 X 40 )*/經(jīng)測(cè)試能正常顯示。
而直接用圖片取模軟件,生成的數(shù)組如下:
0X00,0X00,0X0C,0X00,0X00,0X00,0X00,0X7F,0XC0,0X00,0X00,0X01,0XFF,0XF0,0X00,0X00, 0X06,0X7F,0XF8,0X00,0X00,0X0D,0XFF,0XFE,0X00,0X00,0X1F,0XFF,0XFE,0X00,0X00,0X3F, 0XFF,0XFF,0X00,0X00,0X3F,0X8F,0X3F,0X80,0X00,0X7F,0XCF,0X9F,0X80,0X00,0X7F,0X0F, 0X9F,0XC0,0X00,0XFF,0X0D,0X1F,0XC0,0X10,0XFF,0X0C,0X1F,0XC0,0XF8,0XFF,0X0E,0X1F, 0XC0,0X7C,0XFF,0XFF,0X3F,0XC0,0X7E,0XFF,0XFF,0XFF,0XE0,0X3F,0XFE,0X00,0X3F,0XE0, 0X3F,0XF8,0X00,0X0F,0XF0,0X1F,0XFA,0X00,0X37,0XF0,0X0F,0XFF,0X80,0X7F,0XF0,0X07, 0XFF,0XFF,0XFF,0XF0,0X03,0XFB,0XFF,0XFF,0XF8,0X01,0XFE,0X3F,0XFF,0XFC,0X01,0XFF, 0XC3,0XFF,0XFC,0X01,0X9F,0XFF,0XFF,0X7E,0X01,0X87,0XFF,0XFE,0X3E,0X01,0X80,0X7F, 0XFE,0X3F,0X01,0X80,0X00,0X7E,0X3F,0X01,0X80,0X00,0X7E,0X3F,0X01,0X80,0X00,0X7E, 0X3F,0X01,0X80,0X00,0X7E,0X77,0X00,0XC0,0X00,0X3C,0X63,0X00,0X40,0X00,0X00,0XE0, 0X00,0X60,0X00,0X00,0XC0,0X00,0X30,0X00,0X01,0X80,0X00,0X98,0X00,0X03,0X80,0X01, 0X0C,0X00,0X0E,0X20,0X01,0X03,0X00,0X3C,0X10,0X01,0X01,0XFF,0XF0,0X10,0X00,0XC0, 0X71,0XC0,0X60,0X00,0X3F,0XC0,0X7F,0X80該數(shù)組顯示不正常。
切記,單色圖片取模要先用Imag2Lcd轉(zhuǎn)成單色bmp圖片,然后用PCtoLcd轉(zhuǎn)成數(shù)組
4、重點(diǎn)部分代碼展示
設(shè)置顯示區(qū)域起始坐標(biāo)和終點(diǎn)坐標(biāo)。傳送方式為大端模式,要先傳送地址的高8位,然后再是低8位。
void lcd_set_region(uint8_t x_s,uint8_t y_s,uint8_t x_e,uint8_t y_e) {/*in st7735 col address set regeister 2Ah ,first byte send high 8bit second byte send lou 8bit,row address 2Bh is same*/uint8_t x_data[4]={0x00,x_s,0x00,x_e};uint8_t y_data[4]={0x00,y_s+24,0x00,y_e+24};lcd_cmd(my_spi,0x2A);lcd_data(my_spi,x_data,4);lcd_cmd(my_spi,0x2b);lcd_data(my_spi,y_data,4);lcd_cmd(my_spi,0x2c); }比較坑的是,這塊0.96寸tft屏幕,像素不是從0開(kāi)始的,所以y軸有一個(gè)24的偏移量,這一點(diǎn)太坑了,如果不知道,直接在(0,0)顯示一個(gè)顏色,實(shí)際是沒(méi)有的,因?yàn)檫@個(gè)點(diǎn)超出屏幕的顯示范圍。
畫點(diǎn)函數(shù),要先傳送顏色的高8位,然后是低8位,采用的也是大端傳輸方式。
void lcd_draw_point(uint8_t x ,uint8_t y,uint16_t color) {uint8_t temp[2];temp[0]=color>>8;temp[1]=color;lcd_set_region(x,y,x+1,y+1);lcd_data(my_spi,temp,2);}顯示單色圖片,注意大端模式。另外取模時(shí)是逆向,則先要判斷bit0的值 data>>0&0x01;如果是順向。則先要判斷bit7的值,data<<0&0x80
void lcd_draw_pic(uint8_t x,uint8_t y,uint8_t x_pixel,uint8_t y_pixel, uint16_t fc,uint16_t bc,char *s) {uint16_t i,j,k;uint8_t x_length = x_pixel/8;uint8_t x_yu = x_pixel%8;uint16_t fc_temp,bc_temp;/*st7735 */fc_temp =(fc <<8)|(fc>>8);bc_temp =(bc <<8)|(bc>>8);if(x_yu!=0){x_length = x_length +1;}lcd_set_region(x,y,x+x_pixel-1,y+y_pixel-1);// lcd_set_region(x,y,x+39,y+39);for(i=0;i<y_pixel;i++){for(j=0;j<x_length;j++){for (k=0;k<8;k++){if(((*(s+j+i*x_length))>>k)&0x01){lcd_write_data16bit(fc_temp);}else {lcd_write_data16bit(bc_temp);}/*check the last none 8bit byte of one row*/if (x_yu!=0 && j==(x_length-1) && k==(x_yu-1)){printf("break \r\n");break;}}}} }具體代碼鏈接如下
https://gitee.com/yvany/esp32projects.git
歡迎各位大佬指導(dǎo)和交流!!!
總結(jié)
以上是生活随笔為你收集整理的ESP32实验03:0.96tft液晶显示屏驱动的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 广西田园及20家子公司引入契约锁电子签章
- 下一篇: 网络蛋白质组学在计算机中应用,蛋白质组学