文章目錄
- LCD -- TFTLCD 原理與配置
- TFTLCD(薄膜晶體管液晶顯示幕)
- 簡介
- 特點
- 原理
- 驅動
- 驅動流程
- 硬復位
- 初始化序列
- 設定坐標
- 寫GRAM指令
- 寫入顏色資料(0X2C)
- LCD顯示
- 讀GRAM指令
- 讀出顏色資料(0X2E)
- 單片機處理
- RGB565格式
- ILI9341指令格式說明
- 幾條重要指令
- 0XD3
- 0X36
- 0X2A
- 0X2B
- 0X2C
- 0X2E
- FSMC簡介
- FSMC驅動LCD
- NOR PSRAM外設介面
- 存盤塊1
- 暫存器
- 暫存器組合
- LCD實驗原始碼
- 硬體連接(STM32F4開發板)
- LCD&lcddev結構體
- LCD結構體
- lcddev結構體
- 底層介面函式
- 初始化函式
- 坐標設定函式
- 畫點函式
- 讀點函式
- 字符顯示函式
LCD – TFTLCD 原理與配置
TFTLCD(薄膜晶體管液晶顯示幕)
簡介
Thin Film Transistor - Liquid Crystal Display
TFTLCD計技術是微電子技術與液晶顯示幕技術巧妙結合的一種技術,
TFT-LCD屏可視為兩片玻璃基板中間夾著一層液晶,上層的玻璃基板貼合彩色濾波片,下層玻璃有晶體管鑲嵌,當有電流通過晶體管產生電場變化,造成液晶分子偏轉,借以改變光線的偏極性,再利用偏光片決定像素的明暗狀態,此外,上層玻璃因與彩色濾光片貼合,形成每個像素各包含紅藍綠三顏色,像素便構成了皮膚上的影像畫面,
每一個像素上都設定有一個薄膜晶體管--->大大提高了影像質量
特點
亮度高
對比度高
層次感強
顏色鮮艷
原理

介面說明:
(DB1DB8,DB10DB17,總是按順序連接MCU的D0~D15)
① LCD_CS:LCD片選信號
② LCD_WR:LCD寫信號
③ LCD_RD: LCD讀信號
④ DB[17:1]:16位雙向資料線
⑤ LCD_RST:硬復位LCD信號
⑥ LCD_RS: 命令/資料標志(0:命令,1:資料)
⑦ BL_CTR:背光控制信號
⑧ T_MISO/T_MOST/T_PEN/T_CS/T_CLK,觸摸屏介面信號
驅動
8080并口讀/寫程序為:
先根據要寫入/讀取的資料的型別,設定RS為高(資料)/低(命令),然后拉低片選,選中ILI9341,接著根據是讀還是寫資料置RD/WD 為低
1.讀資料:在RD的上升沿,讀取資料線上的資料(D[15:0])
2.寫資料:在WR的上升沿,使資料寫入到ILI9341里面

驅動流程
硬復位
LCD_RST=0;
delay_ms(100);
LCD_RST=1;
初始化序列
不同廠家出廠的LCD的初始化序列是不同的,由廠家提供,
設定坐標
寫GRAM指令
寫入顏色資料(0X2C)
LCD顯示
讀GRAM指令
讀出顏色資料(0X2E)
單片機處理
RGB565格式

ILI9341指令格式說明
幾條重要指令
0XD3
用來讀取LCD控制器的ID
代碼相同,ID不同——>執行不同的LCD驅動初始化——>兼容不同的LCD螢屏

0X36
存盤訪問控制指令,可以控制ILI9341存盤器的讀寫方向
就是在連續寫GRAM的時候,可以控制GRAM指標的增長方向,從而控制顯示方式(讀GRAM也是一樣)


0X2A
列地址設定指令,默認從左向右,從上到下的掃描方式,用于設定橫坐標

0<=SC<=EC<=239
0X2B
頁(理解是行)地址設定指令,從左到右,從上到下的掃描方式下面,該指令用于設定縱坐標,

0<=SP<=EP<=319
0X2C
寫GRAM指令,在發送該指令后,可往LCD的GRAM里面寫入顏色資料,支持連續寫(地址自動遞增)

0X2E
讀GRAM指令,用于讀取ILI9341的顯存,同0X2C指令,該指令支持連續讀(地址自動遞增)

ILI9341收到指令后,第一次輸出dummy資料(無效),第二次開始,讀取到的才是有效的GRAM資料,輸出規律為每個顏色分量占8個位,一次輸出2個顏色分量,比如:第一次輸出是R1G1,隨后的規律為B1R1->G2B2->R3G3->~
FSMC簡介
FSMC,靈活的靜態存盤控制器,能夠與同步或異步存盤器和16位IPC存盤器卡連接,

FSMC驅動LCD
FSMC驅動外部SRAM時,外部SRAM的控制一般有:地址線(如A0A25)、資料線(如D0D15)、寫信號(WE,即WR)、讀信號(OE,即RD)、片選信號(CS),如果SRAM支持位元組控制,那么還有UBLB信號,
而TFTL CD的信號我們在前面介紹過,包括: RS、D0D15、WR、RD、CS.RST和BL等,其中真正在操作LCD的時候需要用到的就只有:RS、DOD15、WR.RD和CS.其操作時序和SRAM的控制完全類似,唯一不同就是TFTLCD有RS信號,但是沒有地址信號,
TFTLCD通過RS信號來決定傳送的資料是資料還是命令,本質上可以理解為一個地址信號,比如我們把RS接在AO上面,那么當FSMC控制器寫地址0的時候,會使得AO變為0,對TFTLCD來說,就是寫命令,而FSMC寫地址1的時候, A0將會變為1,對TFTLCD來說,就是寫資料,這樣把資料和命令區分開,對應SRAM操作的兩個連續地址,當然RS也可以接在其他地址線上,戰艦V3和精英板開發板都是把RS連接在A10上面,而探索者STM32F4把RS接在A6上面,
因此,可以把TFTLCD當成一個SRAM來用,只不過這個SRAM有2個地址,這就是FSMC可以驅動LCD的原理,
NOR PSRAM外設介面
STM32的FSMC將外部存盤器劃分為固定大小為256M位元組的四個存盤塊

存盤塊1
Bank1(存盤塊1)用于驅動NOR FLASH/SRAM/PSRAM,被分為四個區,每區管理54M位元組空間,每個區都有獨立的暫存器對所連接的存盤器進行配置,Bank1 的256M位元組空間由28根地址線[HADDR【27:0】]尋址,
HADDR是內部AHB地址總線,其中HADDR【25:0】來自外部存盤器地址FSMC_A[25:0],HADDR[26:27]對四個區進行尋址,

當Bank1接的是16位寬度存盤器的時候: HADDR[25:1——>FSMC_A[24:0]
當Bank1接的是8位寬度存盤器的時候: HADDR[25:0]——>FSMC_A[25:0]
不論外部接8位/16位寬設備,FSMC_A[0]永遠接在外部設備地址A[0]
這里使用模式A來驅動LCD


暫存器

對于NORELASH/PSRAM控制器(存盤塊1),通過ESMC BCRx、FSMC_BTRx和FSMC_ BWTRx暫存器設定(其中x=1~4,對應4個區),通過這3個暫存器,可E設定FSMC訪問外部存盤器的時序引數,拓寬了可選用的外部存盤器的速度范圍,
EXTMOD:擴展模式使能位,控制是否允許讀寫不同的時序,需設定為1
WREN:寫使能位,向TFTLCD寫資料,故該位必須設定為1
MWID[1:0]:存盤器資料總線寬度,00,表示8位資料模式;01表示16位資料模式;10和11保留,TFTLCD是16位資料線,所以設定WMID[1:0]=01."MTYP[1:0]:存盤器型別,00表示SRAM、ROM; 01表示PSRAM:10表示NORFLASH;11保留,LCD當成SRAM,需要設定MTYP[1:0]=00.
MBKEN:存盤塊使能位,設定為1

ACCMOD[1:0]:訪問模式,00:模式A;01:模式B:10:模式C;11:模式D.
DATAST[7:0]:資料保持時間,等于: DATAST(+1)個HCLK時鐘周期,DATAST最大為255,對ILI9341來說,其實就是RD低電平持續時間,最大為355ns,對STM32F1,一個HCLK=13.8ns (1/72M),設定為15;對STM32F4,一個HCLK=6ns(1/168M),設定為60,
ADDSET[3:0]:地址建立時間,表示:ADDSET (+1)個HCLK周期, ADDSET最大為15,對ILI9341來說,這里相當于RD高電平持續時間,為90ns,STM32F1的FSMC性能存在問題,即便設定為0,RD也有190ns的高電平,我們這里設定為1,而對STM32F4,則設定為15,

ACCMOD[1:0]:訪問模式,00:模式A;01:模式B:10:模式C;11:模式D,
DATAST[7:0]:資料保持時間,等于:DATAST(+1)個HCLK時鐘周期, DATAST最大為255,對I LI9341來說,其實就是WR低電平持續時間,為15ns,不過ILI9320等則需要50ns,考慮兼容性,對STM32F1,一個HCLK=13.8ns (1/72M),設定為3;對STM32F4,一個HCLK=6ns(1/168M),設定為9,
ADDSET[3:0]:地址建立時間,表示: ADDSET+1個HCLK周期, ADDSET最大為15,對ILI9341相當于WR高電平持續時間,為15ns,兼容ILI9320,對STM32F1設定為1,STM32F4,設定為8,
暫存器組合
ST官方庫提供的暫存器定義,沒有定義單獨的暫存器,而是將他們進行組合,
FSMC BCR×和FSMC_BTRx,組合成BTCR[8]暫存器組
BTCR[0]對應FSMC BCR1,BTCR[1]對應FSMC BTR1
BTCR[2]對應FSMC BCR2,BTCR[3]對應FSMC BTR2
BTCR[4]對應FSMC_BCR3,BTCR[5]對應FSMC BTR3
BTCR[6]對應FSMC BCR4,BTCR[7]對應FSMC BTR4
F.SMC BWTRX則組合成BWTR[7]:
BWTR[O]對應FSMC_BWTR1,BWTR[2]對應FSMC_BWTR2
BWTRI4]對應FSMC BWTR3, BWTR[6]對應FSMC BWTR4
LCD實驗原始碼
硬體連接(STM32F4開發板)
LCD_BL(背光控刷)對應 PBO;
LCD_CS對應PGl2即 FSMC_NE4;
LCD_RS對應 PG0FSMC_Al0;
LCD_wR對應PDS 即 FSMC_NWE;
LCD_RD對應PD4即 FSMC_NOE;
LCD_D[15:0]則直接連接在FSMC_Dl5~FSMC_D0;
LCD&lcddev結構體
LCD結構體
typedef struct
{
vu16 LCD_ REG;
vu16 LCD RAM;
}LCD_TypeDef;
//使用NOR/SRAM的 Bank1.sector4,地址位HADDR[27,26]=11A10作為資料命令區分線
//注意設定時STM32內部會右移一位對齊!
#define LCD_BASE ((u32)(0x6co0o000|Ox0000007FE))
#define LCD ((LCD_ TypeDef*)LCD_ BASE)
LCD_BASE,根據外部電路的連接來確定,如Bank1.sector4就是從地址OX6C000000開始,而OX000007FE,則是A10的偏移量,以A10為例,7FE換成二進制為:111 11111110,而16位資料時,地址右移一位對齊,對應到地址引腳,就是: A10:A0=011 11111111,此時A10是0,但是如果16位地址再加1(對應到8位地址是加2,即7FE+0X02),那么:A10:A0=100 0000 0000,此時A10就是1了,即實作了對RS的0和1的控制,
將((LCD_ TypeDef)LCD_ BASE)這個地址強制轉換為LCD_TypeDef結構體地址,得到LCD->LCD_REG的地址OX6CO0,07FE,對應A10的狀態為O(即RS=0),而LCD->LCD_RAM的地址就是0X6C00,0800(結構體地址自增),對應A10的狀態為1(即RS=1),從而實作對RS的控制,*
lcddev結構體
typedef struct{
u16 width; //LCD寬度
u16 height; //LCD高度
u16 id; //LCD ID
u8 dir; //橫屏還是豎屏控制:0,豎屏:1,橫屏,
u16 wramcmd; //開始寫gram指令
u16 setxcmd; //設定x坐標指令
u16 setycmd; //設定y坐標指令
}_Icd_dev;
//LCD引數
extern _lcd_dev lcddev;//管理LCD重要引數
該結構體引數的賦值,基本都是在LCD_Display_Dir函式完成
底層介面函式
總括:
void LCD WR REG(u16 regval) //寫暫存器值函式
void LCD WR DATA(u16 data) //寫資料函式
u16 LCD RD DATA(void) //讀資料函式
void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue) //寫暫存器內容函式
u16 LCD_ReadReg(u16 LCD_Reg) //讀暫存器內容函式
void LCD WriteRAM Prepare(void) //開始寫GRAM函式
void LCD_WriteRAM(u16 RGB_Code) //寫GRAM函式
void LCD_WR_REG(vu16 regval)
{
regval=regval; //使用-O2優化時,必須插入延時
LCD->LCD_REG=regval;//寫入暫存器序號
}//寫暫存器值
void LcD_WR_DATA(vul6 data)
data=data;
//使用-o2優化的時候,必須插入的延時
LCD->LCD_RAM=data ;
)
//讀LcD資料
ul6 LCD_RD_DATA (void)
vul6 ram;
//防止被優化
ram=LCD->LCD_RAM;
return ram;
//LCD_Reg:暫存器地址
//LCD Regvalue:要寫入的資料
void LcD_WriteReg (ul6 LCD_Reg,ul6 LCD_Regvalue)
LCD->LCD_REG= LCD_Reg;//寫入要寫的暫存器序號LCD->LCD_RAM=LCD_Regvalue; //寫入資料
//讀暫存器
//LCD Reg:暫存器地址//回傳值:讀到的資料
ul6 LCD_ReadReg (ul6 LCD_Reg)
L.CD_WR_REG(LCD_Reg) ;//寫入要讀的暫存器序號delay_us(5) ;
return LCD_RD_DATA ( );//回傳讀到的值
}
void LCD_writeRAM_Prepare (void)
{
LCD->LCD_REG=lcddev.wramcmd;
}
//RGB_code:顏色值
void LcD_writeRAM (ul6 RGB_code){
LCD->LCD_RAM=RGB_code; //寫十六位GRAM
初始化函式
//LCD初始化
void LCD_Init(void)
{
初始化GPIO;
初始化FSMC;
讀取LCD D;
printf( "LCD ID:%Kx\rn", lcddev.id);//列印LCD ID,用到了串口1
//初始化串口1,否則黑屏
根據不同的ID執行LCD初始化代碼;
LCD Display Dir(0); //默認為豎屏
LCD LED=1; //點亮背光
LCD Clear (WHITE); //清屏
坐標設定函式
//設定游標位置
//Xpos:橫坐標
//Ypos:縱坐標
void LCD SetCursor (ul6 Xpos,u16 Ypos)
{
if(lcddev.idoX9341 I|lcddev.id 0X5310)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR DATA (Xpos>>8);
LCD_WR DATA (Xpos&OXFF);
LCD_WR_REG(1eddev.setycmd);
LCD_WR_DATA(Ypos>>8);
LCD_WR_ DATA(Ypos&OXFF);
}else if(lcddev. idXXX){}
//根據不同的LCD型號,執行不同的代碼
}
畫點函式
//畫點
//x, y:坐標
//POINT _COLOR:此點的顏色
void LCD_DrawPoint (u16 x, ul6 y)
{
LCD SetCursor (x,y); //設定游標位置
LCD_WriteRAM_Prepare(); //開始寫入GRAM
LCD->LCD_ RAM=POINT_COLOR;//非Mini板的操作方式
讀點函式
ul6 LCD_ReadPoint (ul6 x,ul6 y){
ul6 r=0, g=o,b=0 ;
if(x>=lcddev.width ||y>=lcddev.height)return 0;//超過了范圍,直接回傳LcD_setcursor(x,y);
if(lcddev.id==0X9341||lcddev.id==OX6804 ||lcddev.id==OX5310||leddev.id==OX1963)LED_WR_REG(0X2E);//341/684/3510/1963發送讀cour指令
else if (lcddev.id==0X5510)LCD_wR_REG (OX2Eo0); //5510發送讀GRAw指令
else LCD_WR_REG(0X22);//其他Ic發送讀GRAv指令
if(lcddev.id==0X9320)opt_delay (2);//FOR 9320,延時2usr=LCD_RD_DATA();-l / dummy Read
if ( lcddev.id==0X1963) return r;//1963直接讀就可以
opt_delay (2);
r=LCD_RD_DATA( ) ;//實際坐標顏色
if (lcddev.id==0X9341||lcddev.id==OX5310||lcddev.id==OX5510)//9341/NT35310/NT35510要分2次讀出
{
opt_delay (2);
b=LCD_RD_DATA();
g=r&0XFF;//對于9341/5310/5510,第一次讀取的是Rc的值,R在前,c在后,各占8位
g<<=8 ;
if(lcddev.id==O0X9325||lcddev. id=O0X4535||lcddev .id==0X4531 ||lcddev .id==O0XB505]||lcddev.id==0XC505)return r;//這幾種rc直接回傳顏色值
else if(lcddev.id=0X9341||lcddev.id==0X5310||lcddev.id==0X5510)return ((r>>l)<<I1)|(g>>10)<<5)|(b>>11));//ILI3L1/NT35310/NT35510需要公式轉
else return LCD_BGR2RGB(r) ;//其他ic
字符顯示函式
void LcD_ShowChar(ul6 x,ul6 y,u8 num, u8 size,u8 mode)
{
u8 temp,tl,t;
ul6 yO=y;
u8 csize=(size/8+((size巹8)?1:0))*(size/2);.//得到字體一個字符對應點陣集所占的字
num=num-' ';//得到偏移后的值(AscII字庫是從空格開始取模,所以-·'就是對應字符的字庫)
for (t=0;t<csize;t++)
{
if(size==l2)temp=asc2_1206[num][t];//呼叫1206字體
else if(size==l6)temp=asc2_1608 [num][t];//呼叫1608字體
else if(size==24)temp=asc2_2412[num][t]; //呼叫2412字體
else return;
//沒有的字庫
for (tl=0;tl<8;tl++)
{
if (temp&0x80)LCD_Fast_DrawPoint (x,y,POINT_COLOR) ;
else if (mode==0)LCD_Fast_DrawPoint (x,y,BACK_COLOR);
temp<<=l;
y++;
if(y>=lcddev.height) return;//超區域
if( (y-y0 )==size)
{
y=y0;x++;
if(>=lcddev.width) return;//超區域
break;
}
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/292801.html
標籤:其他
上一篇:STM32學習(10)-定時器描述,三種計數方式,定時器的作業框圖,定時器時鐘來源,定時器相關暫存器和函式,通用定時器實作定時的步驟
