ESP32实验03:0.96tft液晶显示屏驱动
基于ST7735s的0.96寸tft屏幕顯示
效果展示
- 實現了時鐘顯示,基于ds1307模塊,時鐘字體采用的模擬數碼管字體
- 實現了圖標顯示,后續用于天氣以及狀態指示
- 暫未添加網絡校時,以及網絡獲取天氣數據等功能
- 界面顯示沒有采用第三方庫(暫未找到合適的),采用原始的一個一個圖標畫點顯示
整個實驗斷斷續續耗時接近快2周時間,主要消耗的精力的有幾個方面
本文的重點講解的方面也就是上述3個采坑較多的地方,最后一部分就簡單展示下關鍵的代碼,具體的代碼連接間本文末尾。話不多講,開始正文部分。
1、模塊及開發環境簡介
tft屏幕參數
分辨率:160*80
驅動芯片:ST7735S
通信接口:SPI
供電電壓:3.3V
tft屏幕與ESP32模塊連線
| GND | GND |
| VCC | 3.3v |
| SCL | 19(CLK) |
| SDA | 23(MOSI) |
| DC | 21 |
| RST | 18 |
其中
DC引腳用于控制spi總線傳輸的是命令還是數據。
DC:0傳送命令,DC:1傳送數數據,可以這么理解,要向st7735某個寄存器寫入值,那么一般的邏輯是,先傳輸寄存器地址,再傳輸數據。當傳輸地址前,DC引腳置為low,當傳輸數據前,DC引腳置為high。也就是說DC引腳實際控制的是接下來是要寫地址還是寫數據。
RST引腳是硬件復位tft屏幕,當RST=0時,硬件復位。需要將RST=1然后重新初始化屏幕,才能正常顯示。正常如果不用該引腳可以直接用上拉電阻拉高。在程序中,初始化前,需要將該引腳拉高。
開發環境
開發環境 vscode + platformIO
開發框架 esp-idf
開發語言 C
2、ST7735S說明
備注:ST775S是內置的tft屏幕面板內部的,一般情況下是看不到該芯片的樣子。 所以不要拿到了屏幕模塊后就想拆開看下ST7735芯片長啥樣子,其實,筆者也很好奇芯片的樣子。
2.1主要特性
支持3線或者4線SPI(區別在于3線沒有用DC pin)
支持8位/16位并行接口
數據顯示RAM 132H18RGB162V bits
顏色深度最高支持262K顏色,通常用的是64K
供電電壓3.15V to 5V
最大分辨率132*162
2.2 3&4線spi數據圖
3線spi實際每次傳輸的數據是9bit,最高為實現的就是DC引腳功能。
4線spi采用DC硬件引腳控制寫命令和寫數據。正常來說選擇3線還是4線,屏幕在出廠的時候就確定了。3線還是4線是由ST7735內部的SPI4W引腳來決定的。目前市面上默認的液晶屏都是采用4線模式
選擇是串口還是spi實際也是出廠就設置好了的,其由內部的IM2引腳來確定。
所以不要妄想將買到的并口屏幕改為spi串行通信,除非將整個屏幕拆開,重新連線,這基本是不現實的。
2.3初始化注意事項
在屏幕初始化過程中,會對st7735中的多個寄存器進行賦值,其中有一些寄存器的值直接影響到屏幕的點亮和顯示,現將調試過程中出現的一些重要的寄存器初始化進行說明。
**10h Sleep In & 11h Sleep Out **
進入睡眠模式,上電后,或者軟件或者硬件重置后,屏幕默認進入sleep 模式,此時屏幕是不會有任何顯示的。
退出睡眠模式只有一個方式,通過設置11h
初始化時只需要將11h中寫入0 即可。
**28h DisplayOff & 29h Display On **
上電默認是顯示關閉模式,初始化時需要將液晶設置為顯示開啟模式
初始化時只需要將 29h中寫入0即可打開顯示開啟模式。
** 3ah Interface Pixel Format **
屏幕色彩格式,設置屏幕的色彩位數。通常應用情況下,采用的都是16bit色彩模式,也就是常說的64K顏色。上電默認是18bit顏色。
初始化時,只需要在31h中寫入5,即可將其設置為64K色模式。
2.4液晶顯示原理分析
與屏幕顯示位置及顯示方向相關的寄存器主要有:
36h Memory Data Access Control 內存數據控制,用于控制,屏幕(0,0)原點的位置,及x軸和y軸的方向
2ah 列地址設置寄存器
2bh 行地址設置寄存器
2c 內存寫入寄存器,某個像素點顯示的顏色數據
其中最需要耗時也最需要深入了解的是36h寄存器,其涉及到屏幕的顯示方向及顯示位置。
36h 寄存器
在談寄存器具體內容及含義前,先說明下一般比較推薦的顯示方式。
一般是針對屏幕,將屏幕的左上腳默認為屏幕原點(0,0),X軸往右,Y軸往下。掃描方向,從左到右,從上到下,這比較符合人正常的書寫順序。可能不太好理解掃描,舉個簡單的例子
比如要在屏幕上顯示8bit英文 HELLO WORLD
那么 H 起始坐標 (0,0),終點坐標 (7,7)
E 起始坐標 (8,0),終點坐標(15,7)
。。。。。
依次類推,那么D的起始和終點坐標分別是(80,0)(87,7)
顯示的步驟如下
1、 設置行列地址,起始坐標和終點坐標
2、向屏幕內存寫入每個像素點的顏色數據
3、屏幕將內存中的數據按照掃描順序顯示在屏幕上
掃描順序從左到右,則先顯示(0,0)到(7,7)區域的 H,顯示順序 H -> E -> …-> D
如果是從右向左,則先顯示(80,0)(87,7)的D-> L … -> H
上下掃描也是如此,如果有多行,上下掃描,顯示上衣行再顯示下一行,如果是下上掃描,則先顯示下一行再顯示上一行。
一般情況下,不影響最終顯示結果,但是為了便于理解和習慣,推薦掃描順序從左到右,從上到小
再回到36h寄存器本身
MY 是鏡像Y軸
MX是鏡像X軸
MV是XY軸調換位置
以上圖為例,假設此時 MY =0; MX =0 ,MV =0 則
當MY=1 MX =0 ,MV =0,坐標原點在左下角
當MY=0 MX =1 ,MV =0,坐標原點在右上角
當MY=1 MX =1 ,MV =0,坐標原點在右下角
ML 豎直方向掃描順序
MH水平方向掃描順序
通常都設置為0 從左到右,從上到下
屏幕原點的方向就依靠36H寄存器進行調整,當拿到一個新的屏幕的時候,就要選擇屏幕的坐標原點,通過調整36H,實現正對屏幕,原點位于左上角。
**2ah列地址設置 **
列地址對應的是X軸,其由4個字節組成,第一個字節是起始地址高8位,第二個字節是起始地址低8為,第三個字節是終點坐標高8位,第四個字節是終點坐標低8位。
這一值得注意的是,采用的大端模式,低地址存儲的高位字節,高地址存儲的低位字節。
比如如果地址是0xa0b1,則傳輸大端模式是應該先傳輸0xa0,然后是0xb1;通常的用小端模式都是先傳輸0xb1然后是0xa0
**2bh行地址設置 **
行地址方式與列地址完全一致,就不過多說明。
再說下st7735屏幕分辯率的選擇。ST7735最大支持兩種分辨率 132162和128160
到底最大支持哪種分辨率是在屏幕模塊一出廠就確定了的,其取決月GM1和GM0兩個引腳
由于筆者用的屏幕是160*80所以不管是哪種方式,都不受影響。這主要是山寨屏幕,沒有出場說明書,不知道出場的配置是怎么樣的。這里當時也想了好久才想明白。
這張圖里面實際上就將36h的設置寫明白了。看圖吧就不多贅述了。
3、文字取模和圖片取模軟件
文字取模和圖片取模軟件都是將要在屏幕上顯示的轉化成為一個色彩集合數組。顯示是設置好地址后將該數組按照順序寫入屏幕內存,最終在屏幕上顯示。這里面也有一些坑,如果沒注意,可能會顯示不正常。在此一次將這兩種取模軟件整理清楚。
3.1文字取模軟件
文字取模軟件通常使用的是PCtoLCD2002,界面如下圖
其中的關鍵點主要是在設置選項里面。
那么一個一個來測試,以生活的“生”字為例:
| 陰碼 | 逐行 | 逆向 | 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, |
陰碼:需要點亮的點為1,如上圖,生活的“生”字最上面一個點占的bit7,如果是左往右寫點就是0x80。
逐行就是從左往右一個bit一個bit點亮數碼管,逆向是低位在前,順向是高位在前
分析表格最上面兩行,逆向第一個字節是0x80,順向第一個字節是0x01,將二者轉換為二進制
| 逆向 | 0x80 | 1000 0000 |
| 順向 | 0x01 | 0000 0001 |
逆向順向的區別是轉成二進制后,二者順序顛倒。
如圖數碼管,假設地址(0,0)在左上角。如果要顯示“生”字最上面的一個點
逆向:寫入順序(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)坐標寫入1,其他未寫入0,則點亮了“生”字最上面的一個點。對應到tft屏幕寫入的就是顏色需要點亮就寫入前景色,需要滅的就寫入背景色。
這里要注意:在寫代碼向st7735的2c寄存器寫入的時候,逆向時要先判斷bit0的值,如果是1則寫入前景,0背景,然后是bit1,bit2…。順向的時候,則要先判斷bit7的值,然后bit6,bit5…
當設置逐列時,則寫入順序為
逆向:(0,0)(0,1)(0,2)… (0,7)
順向:(0,7)(0,6)…(0,1) (0,0)
再此就不在進行二進制轉換分析了。感興趣的可以自行研究下
從上述取模方式來看,由于st7735我們推薦的掃描方式是從左到右從上到小,這對應的取模順序是逐行,逆向。所以只要任何屏幕我們都采用這種方式的時候,取模時就可以固定逐行+逆向。
3.2圖片取模軟件
圖片取模軟件通常使用的是Image2Lcd V2.9版本。其機密如下圖所示
掃描模式與文字取模一致,16位真彩色,取出來的數組一共是3200個,40402。每個像素點顏色占2個字節。
這里的高位在前,是色彩的高8字節在前。正常顏色0xfbba,正常生成的數組是,0xba,0xfb。高位在前則為:0xfb,0xba。
這與文字取模里的順向和逆向是有區別的。
正常情況下建議,采用默認的低位在前的方式。
3.3圖片取單色模
如果要將上述的qq圖片成為40*40單色顯示,直接用Image2Lcd設置為單色是不行的。經過多次測試,這種方法取出模,數組是錯誤的。
正確的方式是:
1、先用Image2Lcd將圖片保存為單色圖片
2、再將單色圖片導入到文字取模軟件PCtoLcd2002中,
3、生成數組。陰碼,逐行式,逆向
單色qq圖片文字取模軟件取模結果如下。共有200個字節,40*40/8 每8個像素點占用一個字節
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測試程序\0.96TFT測試程序\圖片取模軟件(贈送)\單色qq.bmp",0*/ /* (40 X 40 )*/經測試能正常顯示。
而直接用圖片取模軟件,生成的數組如下:
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該數組顯示不正常。
切記,單色圖片取模要先用Imag2Lcd轉成單色bmp圖片,然后用PCtoLcd轉成數組
4、重點部分代碼展示
設置顯示區域起始坐標和終點坐標。傳送方式為大端模式,要先傳送地址的高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開始的,所以y軸有一個24的偏移量,這一點太坑了,如果不知道,直接在(0,0)顯示一個顏色,實際是沒有的,因為這個點超出屏幕的顯示范圍。
畫點函數,要先傳送顏色的高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);}顯示單色圖片,注意大端模式。另外取模時是逆向,則先要判斷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
歡迎各位大佬指導和交流!!!
總結
以上是生活随笔為你收集整理的ESP32实验03:0.96tft液晶显示屏驱动的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广西田园及20家子公司引入契约锁电子签章
- 下一篇: 网络蛋白质组学在计算机中应用,蛋白质组学