1.TFTLCD 簡(jiǎn)介
TFT-LCD 即薄膜晶體管液晶顯示器。TFT-LCD與無(wú)源 TN-LCD、 STN-LCD 的簡(jiǎn)單矩陣不同,它在液晶顯示屏的每一個(gè)象素上都設(shè)置有一個(gè)薄膜晶體管( TFT),可有效地克服非選通時(shí)的串?dāng)_,使顯示液晶屏的靜態(tài)特性與掃描線(xiàn)數(shù)無(wú)關(guān),因此大大提高了圖像質(zhì)量。 TFT-LCD 也被叫做真彩液晶顯示器。ALIENTEK TFTLCD 模塊采用 16 位的并方式與外部連接。
2.80 并口有如下一些信號(hào)線(xiàn):
信號(hào)線(xiàn) |
作用 |
CS |
TFTLCD 片選信號(hào) |
WR |
向 TFTLCD 寫(xiě)入數(shù)據(jù) |
RD |
從 TFTLCD 讀取數(shù)據(jù) |
D[15: 0] |
16 位雙向數(shù)據(jù)線(xiàn) |
RST |
硬復(fù)位 TFTLCD |
RS |
命令/數(shù)據(jù)標(biāo)志( 0,讀寫(xiě)命令; 1,讀寫(xiě)數(shù)據(jù)) |
注:TFTLCD 模塊的 RST 信號(hào)線(xiàn)是直接接到 STM32 的復(fù)位腳上,并不由軟件控制,這樣可以省下來(lái)一個(gè) IO口。另外我們還需要一個(gè)背光控制線(xiàn)來(lái)控制 TFTLCD 的背光。所以,我們總共需要的 IO 口數(shù)目為 21 個(gè)。
3.ILI9341 控制器介紹
ILI9341 液晶控制器自帶顯存,其顯存總大小為 172800( 240*320*18/8),即 18 位模式( 26萬(wàn)色)下的顯存量。在 16 位模式下, ILI9341 采用 RGB565 格式存儲(chǔ)顏色數(shù)據(jù),此時(shí) ILI9341的 18 位數(shù)據(jù)線(xiàn)與 MCU 的 16 位數(shù)據(jù)線(xiàn)以及 LCD GRAM 的對(duì)應(yīng)關(guān)系如圖:
ILI9341 在 16 位模式下面,數(shù)據(jù)線(xiàn)有用的是: D17~D13 和 D11~D1, D0和 D12 沒(méi)有用到,實(shí)際上在我們 LCD 模塊里面, ILI9341 的 D0 和 D12 壓根就沒(méi)有引出來(lái),這樣, ILI9341 的 D17~D13 和 D11~D1 對(duì)應(yīng) MCU 的 D15~D0。
MCU 的 16 位數(shù)據(jù), 最低 5 位代表藍(lán)色,中間 6 位為綠色,最高 5 位為紅色。數(shù)值越大,表示該顏色越深。 另外,特別注意 ILI9341 所有的指令都是 8 位的(高 8 位無(wú)效),且參數(shù)除了讀寫(xiě) GRAM 的時(shí)候是 16 位,其他操作參數(shù),都是 8 位的。
4.ILI9341 的重要命令
(1)0XD3
這個(gè)是讀 ID4 指令,用于讀取 LCD 控制器的 ID
可以看出, 0XD3 指令后面跟了 4 個(gè)參數(shù),最后 2 個(gè)參數(shù),讀出來(lái)是 0X93 和 0X41,剛好是控制器 ILI9341 的數(shù)字部分,從而,通過(guò)該指令,即可判別所用的 LCD 驅(qū)動(dòng)器是什么型號(hào),這樣,我們的代碼,就可以根據(jù)控制器的型號(hào)去執(zhí)行對(duì)應(yīng)驅(qū)動(dòng) IC 的初始化代碼,從而兼容不同驅(qū)動(dòng) IC 的屏,使得一個(gè)代碼支持多款 LCD。
(2)0X36
這是存儲(chǔ)訪(fǎng)問(wèn)控制指令,可以控制 ILI9341 存儲(chǔ)器的讀寫(xiě)方向,簡(jiǎn)單的說(shuō),就是在連續(xù)寫(xiě) GRAM 的時(shí)候,可以控制 GRAM 指針的增長(zhǎng)方向,從而控制顯示方式。(讀 GRAM 也是一樣)。該指令如表:
0X36 指令后面,緊跟一個(gè)參數(shù),主要關(guān)注: MY、 MX、 MV 這三個(gè)位,通過(guò)這三個(gè)位的設(shè)置,可以控制整個(gè) ILI9341 的全部掃描方向。
在利用 ILI9341 顯示內(nèi)容的時(shí)候,就有很大靈活性了,比如顯示 BMP 圖片,BMP 解碼數(shù)據(jù),就是從圖片的左下角開(kāi)始,慢慢顯示到右上角,如果設(shè)置 LCD 掃描方向?yàn)閺淖蟮接?,從下到上,那么我們只需要設(shè)置一次坐標(biāo),然后就不停的往 LCD 填充顏色數(shù)據(jù)即可,這樣可以大大提高顯示速度。
(3)0X2A
這是列地址設(shè)置指令, 在從左到右,從上到下的掃描方式(默認(rèn))下面,該指令用于設(shè)置橫坐標(biāo)( x 坐標(biāo)),該指令如表 :
在默認(rèn)掃描方式時(shí),該指令用于設(shè)置 x 坐標(biāo),該指令帶有 4 個(gè)參數(shù),實(shí)際上是 2 個(gè)坐標(biāo)值:SC 和 EC,即列地址的起始值和結(jié)束值, SC 必須小于等于 EC,且 0≤SC/EC≤239。一般在設(shè)置 x 坐標(biāo)的時(shí)候,我們只需要帶 2 個(gè)參數(shù)即可,也就是設(shè)置 SC 即可,因?yàn)槿绻?EC 沒(méi)有變化,我們只需要設(shè)置一次即可(在初始化 ILI9341 的時(shí)候設(shè)置),從而提高速度。
(4)0X2B
是頁(yè)地址設(shè)置指令, 在從左到右,從上到下的掃描方(默認(rèn))下面,該指令用于設(shè)置縱坐標(biāo)( y 坐標(biāo))。該指令如表:
在默認(rèn)掃描方式時(shí),該指令用于設(shè)置 y 坐標(biāo),該指令帶有 4 個(gè)參數(shù),實(shí)際上是 2 個(gè)坐標(biāo)值:SP 和 EP,即頁(yè)地址的起始值和結(jié)束值, SP 必須小于等于 EP,且 0≤SP/EP≤319。一般在設(shè)置y 坐標(biāo)的時(shí)候,我們只需要帶 2 個(gè)參數(shù)即可,也就是設(shè)置 SP 即可,因?yàn)槿绻?EP 沒(méi)有變化,我們只需要設(shè)置一次即可(在初始化 ILI9341 的時(shí)候設(shè)置),從而提高速度。
(5)0X2C
該指令是寫(xiě) GRAM 指令,在發(fā)送該指令之后,我們便可以往 LCD的 GRAM 里面寫(xiě)入顏色數(shù)據(jù)了,該指令支持連續(xù)寫(xiě),指令描述如表:
在收到指令 0X2C 之后,數(shù)據(jù)有效位寬變?yōu)?16 位,我們可以連續(xù)寫(xiě)入 LCD GRAM 值, 而 GRAM 的地址將根據(jù) MY/MX/MV 設(shè)置的掃描方向進(jìn)行自增。
(6)0X2E
該指令是讀 GRAM 指令,用于讀取 ILI9341 的顯存( GRAM),輸出情況如表:
該指令用于讀取 GRAM,如表 所示,ILI9341在收到該指令后,第一次輸出的是 dummy數(shù)據(jù),也就是無(wú)效的數(shù)據(jù),第二次開(kāi)始,讀取到的才是有效的 GRAM 數(shù)據(jù)(從坐標(biāo): SC, SP開(kāi)始),輸出規(guī)律為:每個(gè)顏色分量占 8 個(gè)位,一次輸出 2 個(gè)顏色分量。
比如:
第一次輸出是R1G1,隨后的規(guī)律為:B1R2?G2B2?R3G3?B3R4?G4B4?R5G5… 以此類(lèi)推。如果我們只需要讀取一個(gè)點(diǎn)的顏色值,那么只需要接收到參數(shù) 3 即可,如果要連續(xù)讀?。ɡ?GRAM 地址自增),那么就按照上述規(guī)律去接收顏色數(shù)據(jù)。
5.TFTLCD 模塊的使用流程
任何 LCD,使用流程都可以簡(jiǎn)單的用以上流程圖表示。其中硬復(fù)位和初始化序列,只需要執(zhí)行一次即可。而畫(huà)點(diǎn)流程就是:設(shè)置坐標(biāo) -> 寫(xiě) GRAM 指令 -> 寫(xiě)入顏色數(shù)據(jù),然后在 LCD 上面,我們就可以看到對(duì)應(yīng)的點(diǎn)顯示我們寫(xiě)入的顏色了。讀點(diǎn)流程為:設(shè)置坐標(biāo) -> 讀 GRAM 指令 -> 讀取顏色數(shù)據(jù),這樣就可以獲取到對(duì)應(yīng)點(diǎn)的顏色數(shù)據(jù)了。
1) 設(shè)置 STM32 與 TFTLCD 模塊相連接的 IO。
先將我們與 TFTLCD 模塊相連的 IO 口進(jìn)行初始化,以便驅(qū)動(dòng) LCD。 這里需要根據(jù)連接電路以及 TFTLCD 模塊的設(shè)置來(lái)確定。
2) 初始化 TFTLCD 模塊。
即上圖的初始化序列,這里我們沒(méi)有硬復(fù)位 LCD,因?yàn)?MiniSTM32 開(kāi)發(fā)板的 LCD 接口,將 TFTLCD 的 RST 同 STM32 的 RESET 連接在一起了,只要按下開(kāi)發(fā)板的 RESET 鍵,就會(huì)對(duì) LCD 進(jìn)行硬復(fù)位。
初始化序列,就是向 LCD 控制器寫(xiě)入一系列的設(shè)置值(比如伽馬校準(zhǔn)),這些初始化序列一般 LCD 供應(yīng)商會(huì)提供給客戶(hù),我們直接使用這些序列即可,不需要深入研究。在初始化之后, LCD 才可以正常使用。
3) 通過(guò)函數(shù)將字符和數(shù)字顯示到 TFTLCD 模塊上。
這一步則通過(guò)上圖 左側(cè)的流程,即:設(shè)置坐標(biāo)->寫(xiě) GRAM 指令->寫(xiě) GRAM 來(lái)實(shí)現(xiàn),但是這個(gè)步驟,只是一個(gè)點(diǎn)的處理,我們要顯示字符/數(shù)字,就必須要多次使用這個(gè)步驟,從而達(dá)到顯示字符/數(shù)字的目標(biāo),所以需要設(shè)計(jì)一個(gè)函數(shù)來(lái)實(shí)現(xiàn)數(shù)字/字符的顯示,之后調(diào)用該函數(shù),就可以實(shí)現(xiàn)數(shù)字/字符的顯示了。
6.實(shí)例學(xué)習(xí)
(1)在硬件上, TFTLCD 模塊與 MiniSTM32 開(kāi)發(fā)板的 IO口對(duì)應(yīng)關(guān)系如下:
功能 |
IO |
LCD_LED |
PC10 |
LCD_CS |
PC9 |
LCD _RS |
PC8 |
LCD _WR |
PC7 |
LCD _RD |
PC6 |
LCD _D[17:1] |
PB[15:0] |
(2)時(shí)序
模塊的8080并口讀/寫(xiě)的過(guò)程為:
先根據(jù)要寫(xiě)入/讀取的數(shù)據(jù)的類(lèi)型,設(shè)置RS為高(數(shù)據(jù))/低(命令),然后拉低片選,選中ILI9341,接著我們根據(jù)是讀數(shù)據(jù),還是要寫(xiě)數(shù)據(jù)置RD/WR為低。
1.讀數(shù)據(jù):在RD的上升沿, 讀取數(shù)據(jù)線(xiàn)上的數(shù)據(jù)(D[15:0]);
2.寫(xiě)數(shù)據(jù):在WR的上升沿,使數(shù)據(jù)寫(xiě)入到ILI9341里面
3.例程分析
//LCD重要參數(shù)集
typedef struct
{
u16 width; //LCD 寬度
u16 height; //LCD 高度
u16 id; //LCD ID
u8 dir; //橫屏還是豎屏控制:0,豎屏;1,橫屏。
u16 wramcmd; //開(kāi)始寫(xiě)gram指令
u16 setxcmd; //設(shè)置x坐標(biāo)指令
u16 setycmd; //設(shè)置y坐標(biāo)指令
}_lcd_dev;
/*寫(xiě)數(shù)據(jù)函數(shù):通過(guò) 80 并口向 LCD 模塊寫(xiě)入一個(gè) 16 位的數(shù)據(jù),宏定義的方式,以提高速度。*/
#define LCD_WR_DATA(data){ LCD_RS_SET; LCD_CS_CLR; DATAOUT(data); LCD_WR_CLR; LCD_WR_SET; LCD_CS_SET;}
void LCD_WR_DATAX(u16 data)
{
LCD_RS_SET;
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
/*通過(guò) 8080 并口向 LCD 模塊寫(xiě)入寄存器命令*/
//寫(xiě)寄存器函數(shù)
//data:寄存器值
void LCD_WR_REG(u16 data)
{
LCD_RS_CLR;//寫(xiě)地址
LCD_CS_CLR;
DATAOUT(data);
LCD_WR_CLR;
LCD_WR_SET;
LCD_CS_SET;
}
/*讀取 LCD 控制器的寄存器數(shù)據(jù)(非 GRAM 數(shù)據(jù))*/
//讀 LCD 寄存器數(shù)據(jù)
//返回值:讀到的值
u16 LCD_RD_DATA(void)
{
u16 t;
GPIOB->CRL=0X88888888; //PB0-7 上拉輸入
GPIOB->CRH=0X88888888; //PB8-15 上拉輸入
GPIOB->ODR=0X0000; //全部輸出 0
LCD_RS_SET;
LCD_CS_CLR;
LCD_RD_CLR; //讀取數(shù)據(jù)(讀寄存器時(shí),并不需要讀 2 次)
if(lcddev.id==0X8989)delay_us(2);//FOR 8989,延時(shí) 2us
t=DATAIN;
LCD_RD_SET;
LCD_CS_SET;
GPIOB->CRL=0X33333333; //PB0-7 上拉輸出
GPIOB->CRH=0X33333333; //PB8-15 上拉輸出
GPIOB->ODR=0XFFFF; //全部輸出高
return t;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
/*LCD 寄存器操作*/
//寫(xiě)寄存器:用于向 LCD 指定寄存器寫(xiě)入指定數(shù)據(jù)
//LCD_Reg:寄存器編號(hào)
//LCD_RegValue:要寫(xiě)入的值
void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue)
{
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
}
//讀寄存器:用于讀取指定寄存器的數(shù)據(jù)
//LCD_Reg:寄存器編號(hào)
//返回值:讀到的值
u16 LCD_ReadReg(u16 LCD_Reg)
{
LCD_WR_REG(LCD_Reg); //寫(xiě)入要讀的寄存器號(hào)
return LCD_RD_DATA();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
/*坐標(biāo)設(shè)置*/
//設(shè)置光標(biāo)位置:將 LCD 的當(dāng)前操作點(diǎn)設(shè)置到指定坐標(biāo)(x,y)
//Xpos:橫坐標(biāo)
//Ypos:縱坐標(biāo)
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
if(lcddev.id==0X9341||lcddev.id==0X5310)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
}else if(lcddev.id==0X6804)
{
if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//橫屏?xí)r處理
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_DATA(Ypos&0XFF);
}else if(lcddev.id==0X5510)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(Xpos>>8);
LCD_WR_REG(lcddev.setxcmd+1);
LCD_WR_DATA(Xpos&0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_REG(lcddev.setycmd+1);
LCD_WR_DATA(Ypos&0XFF);
}else
{
if(lcddev.dir==1)Xpos=lcddev.width-1-Xpos;//橫屏其實(shí)就是調(diào)轉(zhuǎn) x,y 坐標(biāo)
LCD_WriteReg(lcddev.setxcmd, Xpos);
LCD_WriteReg(lcddev.setycmd, Ypos);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
//畫(huà)點(diǎn)
//x,y:坐標(biāo)
//POINT_COLOR:此點(diǎn)的顏色
void LCD_DrawPoint(u16 x,u16 y)
{
LCD_SetCursor(x,y); //設(shè)置光標(biāo)位置
LCD_WriteRAM_Prepare(); //開(kāi)始寫(xiě)入 GRAM
LCD_WR_DATA(POINT_COLOR);
}
//讀取個(gè)某點(diǎn)的顏色值
//x,y:坐標(biāo)
//返回值:此點(diǎn)的顏色
u16 LCD_ReadPoint(u16 x,u16 y)
{
u16 r,g,b;
if(x>=lcddev.width||y>=lcddev.height)
return 0; //超過(guò)了范圍,直接返回
LCD_SetCursor(x,y);
if(lcddev.id==0X9341||lcddev.id==0X6804||lcddev.id==0X5310||lcddev.id==0X1963)
LCD_WR_REG(0X2E);//9341/6804/3510/1963 發(fā)送讀 GRAM 指令
else if(lcddev.id==0X5510)LCD_WR_REG(0X2E00);//5510 發(fā)送讀 GRAM 指令
else LCD_WR_REG(0X22); //其他 IC 發(fā)送讀 GRAM 指令
GPIOB->CRL=0X88888888; //PB0-7 上拉輸入
GPIOB->CRH=0X88888888; //PB8-15 上拉輸入
GPIOB->ODR=0XFFFF; //全部輸出高
LCD_RS_SET;
LCD_CS_CLR;
LCD_RD_CLR; //讀取數(shù)據(jù)(讀 GRAM 時(shí),第一次為假讀)
opt_delay(2); //延時(shí)
r=DATAIN; //實(shí)際坐標(biāo)顏色
LCD_RD_SET;
if(lcddev.id==0X1963)
{
LCD_CS_SET;
GPIOB->CRL=0X33333333; //PB0-7 上拉輸出
GPIOB->CRH=0X33333333; //PB8-15 上拉輸出
GPIOB->ODR=0XFFFF; //全部輸出高
return r; //1963 直接讀就可以
}
LCD_RD_CLR; //dummy READ
opt_delay(2); //延時(shí)
r=DATAIN; //實(shí)際坐標(biāo)顏色
LCD_RD_SET;
if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510)//這幾個(gè) IC 要分 2 次讀出
{
LCD_RD_CLR;
opt_delay(2);//延時(shí)
b=DATAIN;//讀取藍(lán)色值
LCD_RD_SET;
g=r&0XFF;//對(duì)于 9341,第一次讀取的是 RG 的值,R 在前,G 在后,各占 8 位
g<<=8;
}else if(lcddev.id==0X6804)
{
LCD_RD_CLR;
LCD_RD_SET;
r=DATAIN;//6804 第二次讀取的才是真實(shí)值
}
LCD_CS_SET;
GPIOB->CRL=0X33333333; //PB0-7 上拉輸出
GPIOB->CRH=0X33333333; //PB8-15 上拉輸出
GPIOB->ODR=0XFFFF; //全部輸出高
if(lcddev.id==0X9325||lcddev.id==0X4535||lcddev.id==0X4531||lcddev.id==0X8989||
lcddev.id==0XB505)return r; //這幾種 IC 直接返回顏色值
else if(lcddev.id==0X9341||lcddev.id==0X5310||lcddev.id==0X5510)
return (((r>>11)<<11)|((g>>10)<<5)|(b>>11));//這幾個(gè) IC 需要公式轉(zhuǎn)換一下
else return LCD_BGR2RGB(r); //其他 IC
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
//在指定位置顯示一個(gè)字符
//x,y:起始坐標(biāo)
//num:要顯示的字符:" "--->"~"
//size:字體大小 12/16/24
//mode:疊加方式(1)還是非疊加方式(0)
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
{
u8 temp,t1,t;
u16 y0=y;
u8 csize=(size/8+((size%8)?1:0))*(size/2);//得到字體一個(gè)字符對(duì)應(yīng)點(diǎn)陣集所占字節(jié)數(shù)
//設(shè)置窗口
num=num-' ';//得到偏移后的值
for(t=0;t<csize;t++)
{
if(size==12)temp=asc2_1206[num][t]; //調(diào)用 1206 字體
else if(size==16)temp=asc2_1608[num][t]; //調(diào)用 1608 字體
else if(size==24)temp=asc2_2412[num][t]; //調(diào)用 2412 字體
else return; //沒(méi)有的字庫(kù)
for(t1=0;t1<8;t1++)
{
if(temp&0x80)
LCD_Fast_DrawPoint(x,y,POINT_COLOR);
else if(mode==0)
LCD_Fast_DrawPoint(x,y,BACK_COLOR);
temp<<=1;
y++;
if(x>=lcddev.width)return; //超區(qū)域了
if((y-y0)==size)
{
y=y0; x++;
if(x>=lcddev.width)return; //超區(qū)域了
break;
}
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
//該初始化函數(shù)可以初始化各種 ALIENTEK 出品的 LCD 液晶屏
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO, ENABLE); //使能PORTB,C時(shí)鐘和AFIO時(shí)鐘
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);//開(kāi)啟SWD,失能JTAG
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6; ///PORTC6~10復(fù)用推挽輸出
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure); //GPIOC
GPIO_SetBits(GPIOC,GPIO_Pin_10|GPIO_Pin_9|GPIO_Pin_8|GPIO_Pin_7|GPIO_Pin_6);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; // PORTB推挽輸出
GPIO_Init(GPIOB, &GPIO_InitStructure); //GPIOB
GPIO_SetBits(GPIOB,GPIO_Pin_All);
delay_ms(50); // delay 50 ms
LCD_WriteReg(0x0000,0x0001);
delay_ms(50); // delay 50 ms
lcddev.id = LCD_ReadReg(0x0000);
if(lcddev.id<0XFF||lcddev.id==0XFFFF||lcddev.id==0X9300)//讀到ID不正確,新增lcddev.id==0X9300判斷,因?yàn)?341在未被復(fù)位的情況下會(huì)被讀成9300
{
//嘗試9341 ID的讀取
LCD_WR_REG(0XD3);
LCD_RD_DATA(); //dummy read
LCD_RD_DATA(); //讀到0X00
lcddev.id=LCD_RD_DATA(); //讀取93
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //讀取41
if(lcddev.id!=0X9341) //非9341,嘗試是不是6804
{
LCD_WR_REG(0XBF);
LCD_RD_DATA(); //dummy read
LCD_RD_DATA(); //讀回0X01
LCD_RD_DATA(); //讀回0XD0
lcddev.id=LCD_RD_DATA();//這里讀回0X68
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA();//這里讀回0X04
if(lcddev.id!=0X6804) //也不是6804,嘗試看看是不是NT35310
{
LCD_WR_REG(0XD4);
LCD_RD_DATA(); //dummy read
LCD_RD_DATA(); //讀回0X01
lcddev.id=LCD_RD_DATA(); //讀回0X53
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //這里讀回0X10
if(lcddev.id!=0X5310) //也不是NT35310,嘗試看看是不是NT35510
{
LCD_WR_REG(0XDA00);
LCD_RD_DATA(); //讀回0X00
LCD_WR_REG(0XDB00);
lcddev.id=LCD_RD_DATA();//讀回0X80
lcddev.id<<=8;
LCD_WR_REG(0XDC00);
lcddev.id|=LCD_RD_DATA();//讀回0X00
if(lcddev.id==0x8000)lcddev.id=0x5510;//NT35510讀回的ID是8000H,為方便區(qū)分,我們強(qiáng)制設(shè)置為5510
if(lcddev.id!=0X5510) //也不是NT5510,嘗試看看是不是SSD1963
{
LCD_WR_REG(0XA1);
lcddev.id=LCD_RD_DATA();
lcddev.id=LCD_RD_DATA(); //讀回0X57
lcddev.id<<=8;
lcddev.id|=LCD_RD_DATA(); //讀回0X61
if(lcddev.id==0X5761)lcddev.id=0X1963;//SSD1963讀回的ID是5761H,為方便區(qū)分,我們強(qiáng)制設(shè)置為1963
}
}
}
}
}
printf(" LCD ID:%x\r\n",lcddev.id); //打印LCD ID
if(lcddev.id==0X9341) //9341初始化
{
LCD_WR_REG(0xCF);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0xC1);
LCD_WR_DATAX(0X30);
LCD_WR_REG(0xED);
LCD_WR_DATAX(0x64);
LCD_WR_DATAX(0x03);
LCD_WR_DATAX(0X12);
LCD_WR_DATAX(0X81);
LCD_WR_REG(0xE8);
LCD_WR_DATAX(0x85);
LCD_WR_DATAX(0x10);
LCD_WR_DATAX(0x7A);
LCD_WR_REG(0xCB);
LCD_WR_DATAX(0x39);
LCD_WR_DATAX(0x2C);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x34);
LCD_WR_DATAX(0x02);
LCD_WR_REG(0xF7);
LCD_WR_DATAX(0x20);
LCD_WR_REG(0xEA);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_REG(0xC0); //Power control
LCD_WR_DATAX(0x1B); //VRH[5:0]
LCD_WR_REG(0xC1); //Power control
LCD_WR_DATAX(0x01); //SAP[2:0];BT[3:0]
LCD_WR_REG(0xC5); //VCM control
LCD_WR_DATAX(0x30); //3F
LCD_WR_DATAX(0x30); //3C
LCD_WR_REG(0xC7); //VCM control2
LCD_WR_DATAX(0XB7);
LCD_WR_REG(0x36); // Memory Access Control
LCD_WR_DATAX(0x48);
LCD_WR_REG(0x3A);
LCD_WR_DATAX(0x55);
LCD_WR_REG(0xB1);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x1A);
LCD_WR_REG(0xB6); // Display Function Control
LCD_WR_DATAX(0x0A);
LCD_WR_DATAX(0xA2);
LCD_WR_REG(0xF2); // 3Gamma Function Disable
LCD_WR_DATAX(0x00);
LCD_WR_REG(0x26); //Gamma curve selected
LCD_WR_DATAX(0x01);
LCD_WR_REG(0xE0); //Set Gamma
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x2A);
LCD_WR_DATAX(0x28);
LCD_WR_DATAX(0x08);
LCD_WR_DATAX(0x0E);
LCD_WR_DATAX(0x08);
LCD_WR_DATAX(0x54);
LCD_WR_DATAX(0XA9);
LCD_WR_DATAX(0x43);
LCD_WR_DATAX(0x0A);
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_REG(0XE1); //Set Gamma
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x15);
LCD_WR_DATAX(0x17);
LCD_WR_DATAX(0x07);
LCD_WR_DATAX(0x11);
LCD_WR_DATAX(0x06);
LCD_WR_DATAX(0x2B);
LCD_WR_DATAX(0x56);
LCD_WR_DATAX(0x3C);
LCD_WR_DATAX(0x05);
LCD_WR_DATAX(0x10);
LCD_WR_DATAX(0x0F);
LCD_WR_DATAX(0x3F);
LCD_WR_DATAX(0x3F);
LCD_WR_DATAX(0x0F);
LCD_WR_REG(0x2B);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x01);
LCD_WR_DATAX(0x3f);
LCD_WR_REG(0x2A);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0x00);
LCD_WR_DATAX(0xef);
LCD_WR_REG(0x11); //Exit Sleep
delay_ms(120);
LCD_WR_REG(0x29); //display on
}
LCD_Display_Dir(0); //默認(rèn)為豎屏
LCD_LED=1; //點(diǎn)亮背光
LCD_Clear(WHITE);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
注:此處僅為9341 的初始化
參考:
原子開(kāi)發(fā)手冊(cè)—–庫(kù)函數(shù)版
|