TFTLCD是薄膜晶體管液晶顯示器。TFTLCD具有亮度好,對比度高,層次感強,顏色鮮艷等優(yōu)點,是目前最主流的LCD顯示器 ,廣泛用于電視,手機,電腦,平板等各種的電子產(chǎn)品。
LCD原理圖

LCD_CS為芯片選擇輸入引腳(“低”啟用)。
RS用于在并行接口中選擇“數(shù)據(jù)或命令”,當RS為1時,數(shù)據(jù)被選中;當RS為0時,命令被選中。
WR作為寫信號,上升沿寫入數(shù)據(jù)。
RD作為讀取信號,上升沿讀取數(shù)據(jù)。
RST為硬復位LCD信號。
D0-D15為16位雙向數(shù)據(jù)線。
BL為背光燈控制信號。
MISO/MOSI/T_PEN/T_CS/CLK為觸摸屏接口信號,本節(jié)暫不做介紹。
引腳分配為:
LCD_CS:PG12、RS:PF12、WR:PD5、RD:PD4、RESET:PG15、BL:PB15、D0:PD14、D1:PD15、D2:PD0、D3:PD1、D4:PE7、D5:PE8、D6:PE9、D7:PE10、D8:PE11、D9:PE12、D10:PE13、D11:PE14、D12:PE15、D13:PD8、D14:PD9、D15:PD10。
由于開漏模式下電壓達不到LCD的要求,所以所有引腳配置為推挽模式,數(shù)據(jù)輸出時切換為輸出模式,接收數(shù)據(jù)時切換為輸入模式。
構造時序時經(jīng)常要對片選信號CS、數(shù)據(jù)/命令選擇RS、寫信號WR、讀信號RD、背光燈控制BL進行操作,為了更方便編寫程序,可以對這幾個信號進行宏定義。
#define LCD_CS_H()   do{GPIOG- >BSRRL = 0x1< 12;}while(0)  //片選失效
#define LCD_CS_L()   do{GPIOG- >BSRRH = 0x1< 12;}while(0)  //片選有效
#define RS_H()       do{GPIOF- >BSRRL = 0x1< 12;}while(0)  //選擇為參數(shù)狀態(tài)
#define RS_L()       do{GPIOF- >BSRRH = 0x1< 12;}while(0)  //選擇為命令狀態(tài)
#define WR_H()        do{GPIOD- >BSRRL = 0x1< 5;}while(0)    //寫失效
#define WR_L()         do{GPIOD- >BSRRH = 0x1< 5;}while(0)    //寫有效
#define RD_H()        do{GPIOD- >BSRRL = 0x1< 4;}while(0)    //讀失效
#define RD_L()        do{GPIOD- >BSRRH = 0x1< 4;}while(0)    //讀有效
#define BL_H()        do{GPIOB- >BSRRL = 0x1< 15;}while(0)  //關背光燈
#define BL_L()        do{GPIOB- >BSRRH = 0x1< 15;}while(0)  //開背光燈
接著編寫ILI9341GPIO口的初始化函數(shù)
static void ILI9341_GpioInit()
{
  //1. 開時鐘PB/D/E/F/G
  RCC- >AHB1ENR  |= 1< 1 | 0XF< 3;
  //2. 設置模式(輸出)
  //  BL:PB15
  GPIOB- >MODER &=~ (0x3< 30);
  GPIOB- >MODER |=  (0x1< 30);
  //  D2:PD0、D3:PD1、RD:PD4、WR:PD5、D13:PD8、D14:PD9、D15:PD10、D0:PD14、D1:PD15
  GPIOD- >MODER &=~ (0xf03f0f0f< 0);
  GPIOD- >MODER |=  (0x50150505< 0);
  //  D4:PE7、D5:PE8、D6:PE9、D7:PE10、D8:PE11、D9:PE12、D10:PE13、D11:PE14、D12:PE15
  GPIOE- >MODER &=~ (0xffffc000< 0);
  GPIOE- >MODER |=  (0x55554000< 0);
  //  RS:PF12
  GPIOF- >MODER &=~ (0x3< 24);
  GPIOF- >MODER |=  (0x1< 24);
  //  LCD_CS:PG12、RESET:PG15
  GPIOG- >MODER &=~ (0xc3000000< 0);
  GPIOG- >MODER |=  (0x41000000< 0);
  //3. 輸出類型:推挽輸出
  //  BL:PB15
  GPIOB- >OTYPER &=~ (0x1< 15);
  //  D2:PD0、D3:PD1、RD:PD4、WR:PD5、D13:PD8、D14:PD9、D15:PD10、D0:PD14、D1:PD15
  GPIOD- >OTYPER &=~ (0xc733< 0);
  //  D4:PE7、D5:PE8、D6:PE9、D7:PE10、D8:PE11、D9:PE12、D10:PE13、D11:PE14、D12:PE15
  GPIOE- >OTYPER &=~ (0xff80< 0);
  //  RS:PF12
  GPIOF- >OTYPER &=~ (0x1< 24);
  //  LCD_CS:PG12、RESET:PG15
  GPIOG- >OTYPER &=~ (0x9000< 0);
  //4. 速度(100Mhz)    
  //  BL:PB15
  GPIOB- >OSPEEDR |=  (0x3< 30);
  //  D2:PD0、D3:PD1、RD:PD4、WR:PD5、D13:PD8、D14:PD9、D15:PD10、D0:PD14、D1:PD15
  GPIOD- >OSPEEDR |=  (0xf03f0f0f< 0);
  //  D4:PE7、D5:PE8、D6:PE9、D7:PE10、D8:PE11、D9:PE12、D10:PE13、D11:PE14、D12:PE15
  GPIOE- >OSPEEDR |=  (0xffffc000< 0);
  //  RS:PF12
  GPIOF- >OSPEEDR |=  (0x3< 24);
  //  LCD_CS:PG12、RESET:PG15
  GPIOG- >OSPEEDR |=  (0xc3000000< 0);
  //5. 上下拉(上拉)
  //  BL:PB15
  GPIOB- >PUPDR &=~ (0x3< 30);
  //  D2:PD0、D3:PD1、RD:PD4、WR:PD5、D13:PD8、D14:PD9、D15:PD10、D0:PD14、D1:PD15
  GPIOD- >PUPDR &=~ (0xf03f0f0f< 0);
  //  D4:PE7、D5:PE8、D6:PE9、D7:PE10、D8:PE11、D9:PE12、D10:PE13、D11:PE14、D12:PE15
  GPIOE- >PUPDR &=~ (0xffffc000< 0);
  //  RS:PF12
  GPIOF- >PUPDR &=~ (0x3< 24);
  //  LCD_CS:PG12、RESET:PG15
  GPIOG- >PUPDR &=~ (0xc3000000< 0);
  //6. 引腳初始電平
  LCD_CS_H();    //片選失效
  RS_H();        //選擇為參數(shù)狀態(tài)
  WR_H();        //寫失效
  RD_H();        //讀失效
  BL_H();        //關背光燈
}
引腳初始化中,由于LCD模塊涉及的引腳相對比較多,最好在配置時先寫好每個寄存器的注釋,方便進行配置,也方便后面進行排錯。為方便數(shù)據(jù)的讀寫,添加數(shù)據(jù)引腳的輸入輸出模式切換函數(shù)。
//模式切換為輸入
void ILI9341_MODE_IN()
{
  //  D2:PD0、D3:PD1、D13:PD8、D14:PD9、D15:PD10、D0:PD14、D1:PD15
  GPIOD- >MODER &=~ (0xf03f000f< 0);
  //  D4:PE7、D5:PE8、D6:PE9、D7:PE10、D8:PE11、D9:PE12、D10:PE13、D11:PE14、D12:PE15
  GPIOE- >MODER &=~ (0xffffc000< 0);
}
//模式切換為輸出
void ILI9341_MODE_OUT()
{
  //  D2:PD0、D3:PD1、D13:PD8、D14:PD9、D15:PD10、D0:PD14、D1:PD15
  GPIOD- >MODER &=~ (0xf03f000f< 0);
  GPIOD- >MODER |=  (0x50150005< 0);
  //  D4:PE7、D5:PE8、D6:PE9、D7:PE10、D8:PE11、D9:PE12、D10:PE13、D11:PE14、D12:PE15
  GPIOE- >MODER &=~ (0xffffc000< 0);
  GPIOE- >MODER |=  (0x55554000< 0);
}
寫數(shù)據(jù)到ILI9341時要通過判斷16位數(shù)據(jù)來確定輸出數(shù)據(jù)線的高低電平。
void ILI9341_Write(u16 dat)
{
  //D0-D1:PD14/PD15
  GPIOD- >ODR  &= 0x3fff;
  GPIOD- >ODR  |= ((dat)&0x0003)< 14;
  //D2-D3:PD0/PD1
  GPIOD- >ODR  &= 0xfffc;
  GPIOD- >ODR  |= ((dat >?>2)&0x0003)< 0;
  //D4-D12:PE7-PE15
  GPIOE- >ODR  &= 0X007F;
  GPIOE- >ODR  |= ((dat >?>4)&0x01ff)< 7;
  
  //D13-D15:PD8-PD10
  GPIOD- >ODR  &= ~(0X7< 8);
  GPIOD- >ODR  |= (dat >?>13)< 8;
}
讀數(shù)據(jù)則通過判斷數(shù)據(jù)線輸入電平來確定輸入的16位數(shù)據(jù)。
u16 ILI9341_Read()
{
  u16 temp = 0;
  //D0-D1:PD14/PD15
  temp |= (GPIOD- >IDR & 0X3)< 0;
  //D2-D3:PD0/PD1
  temp |= (GPIOD- >IDR & 0X3)< 2;
  //D4-D12:PE7-PE15
  temp |= (GPIOE- >IDR  > >7)< 4;
  //D13-D15:PD8-PD10
  temp |= ((GPIOD- >IDR > >8)&0X7)< 13;
  return temp;
}

由于使用的數(shù)據(jù)線是16條,所以采用8080時序的16位總線操作進行寫命令、讀狀態(tài)、寫參數(shù)、讀參數(shù)。由表可以看出片選信號CS低電平時為使能。
根據(jù)表格8080時序寫出寫命令、讀狀態(tài)、寫參數(shù)、讀參數(shù)的函數(shù)。
//寫命令
void ILI9341_WriteCmd(u16 cmd)
{
  LCD_CS_L();              //片選有效
  RS_L();                  //選擇為命令狀態(tài)
  ILI9341_Write(cmd);
  WR_L();    //寫失效
  WR_H();    //寫有效
  LCD_CS_L();    //片選失效        
}
//讀狀態(tài)
u16 ILI9341_ReadStatus()
{
  u16 temp = 0;
  //模式切換為讀
  ILI9341_MODE_IN();
  LCD_CS_L();              //片選有效
  RS_H();                  //選擇為參數(shù)狀態(tài)
  //rd:PD4
  RD_H();          //讀失效
  RD_L();           //讀有效
  temp = ILI9341_Read();
  LCD_CS_L();    //片選失效                  
  //模式切換為讀
  ILI9341_MODE_OUT();
  return temp;
}
//寫參數(shù)
void ILI9341_WriteParam(u16 param)
{
  LCD_CS_L();              //片選有效
  RS_H();                  //選擇為參數(shù)狀態(tài)
  ILI9341_Write(param);
  //WR:PD5
  WR_L();    //寫失效
  WR_H();    //寫有效
  LCD_CS_L();    //片選失效                    
}
//讀參數(shù)
u16 ILI9341_ReadParam()
{
  u16 temp = 0;
  //模式切換為讀
  ILI9341_MODE_IN();
  LCD_CS_L();              //片選有效
  RS_H();                  //選擇為參數(shù)狀態(tài)
  //rd:PD4
  RD_H();          //讀失效
  RD_L();           //讀有效
  temp = ILI9341_Read();
  LCD_CS_L();    //片選失效                  
  //模式切換為讀
  ILI9341_MODE_OUT();
  return temp;
}
最后,完成ILI9341初始化函數(shù)。先初始化GPIO引腳,軟件復位,再添加屏幕廠家提供的初始化序列。
void ILI9341_Init()
{  
  u32 i = 0;
  //引腳初始化
  ILI9341_GpioInit();
  ILI9341_WriteCmd(0x01);  
  //初始化9341
  Delay_ms(120); // Delay 120 ms
//****Start Initial Sequence(以下代碼廠家提供) ****
    ILI9341_WriteCmd(0xCF);            //電源設置
    ILI9341_WriteParam(0x00);              //默認值
    ILI9341_WriteParam(0x81);              //默認值
    ILI9341_WriteParam(0X30);            //默認值
    ILI9341_WriteCmd(0xED);            //上電序列控制
    ILI9341_WriteParam(0x64);
    ILI9341_WriteParam(0x03);
    ILI9341_WriteParam(0X12);
    ILI9341_WriteParam(0X81);
    ILI9341_WriteCmd(0xE8);            //驅動時序控制
    ILI9341_WriteParam(0x85);
    ILI9341_WriteParam(0x01);
    ILI9341_WriteParam(0x79);
    ILI9341_WriteCmd(0xCB);            //電源控制A
    ILI9341_WriteParam(0x39);
    ILI9341_WriteParam(0x2C);
    ILI9341_WriteParam(0x00);
    ILI9341_WriteParam(0x34);
    ILI9341_WriteParam(0x02);  
    ILI9341_WriteCmd(0xF7);            //Pump ratio control 
    ILI9341_WriteParam(0x20);
    ILI9341_WriteCmd(0xEA);            //Driver timing control B
    ILI9341_WriteParam(0x00);
    ILI9341_WriteParam(0x00);
    ILI9341_WriteCmd(0xC0);             //Power control
    ILI9341_WriteParam(0x1D);             //VRH[5:0]
    ILI9341_WriteCmd(0xC1);             //Power control
    ILI9341_WriteParam(0x11);             //SAP[2:0];BT[3:0]
    ILI9341_WriteCmd(0xC5);             //VCM control
    ILI9341_WriteParam(0x33);
    ILI9341_WriteParam(0x34);
    ILI9341_WriteCmd(0xC7);             //VCM control2
    ILI9341_WriteParam(0Xbe);
//    ILI9341_MemoryAccessCtrl(SCAN_MODE,1);      //掃描模式,默認為L2R_U2D,顏色順序:RGB
    ILI9341_WriteCmd(0X36);
    ILI9341_WriteParam(0);  
    ILI9341_WriteCmd(0xB1);
    ILI9341_WriteParam(0x00);
    ILI9341_WriteParam(0x1B);
    ILI9341_WriteCmd(0xB6);             // Display Function Control
    ILI9341_WriteParam(0x0A);
    ILI9341_WriteParam(0xA2);
    ILI9341_WriteCmd(0xF2);             // 3Gamma Function Disable
    ILI9341_WriteParam(0x00);
    ILI9341_WriteCmd(0x26);             //Gamma curve selected
    ILI9341_WriteParam(0x01);
    ILI9341_WriteCmd(0xE0);             //Set Gamma
    ILI9341_WriteParam(0x0F);
    ILI9341_WriteParam(0x23);
    ILI9341_WriteParam(0x1F);
    ILI9341_WriteParam(0x09);
    ILI9341_WriteParam(0x0f);
    ILI9341_WriteParam(0x08);
    ILI9341_WriteParam(0x4B);
    ILI9341_WriteParam(0Xf2);
    ILI9341_WriteParam(0x38);
    ILI9341_WriteParam(0x09);
    ILI9341_WriteParam(0x13);
    ILI9341_WriteParam(0x03);
    ILI9341_WriteParam(0x12);
    ILI9341_WriteParam(0x07);
    ILI9341_WriteParam(0x04);
    ILI9341_WriteCmd(0XE1);             //Set Gamma
    ILI9341_WriteParam(0x00);
    ILI9341_WriteParam(0x1d);
    ILI9341_WriteParam(0x20);
    ILI9341_WriteParam(0x02);
    ILI9341_WriteParam(0x11);
    ILI9341_WriteParam(0x07);
    ILI9341_WriteParam(0x34);
    ILI9341_WriteParam(0x81);
    ILI9341_WriteParam(0x46);
    ILI9341_WriteParam(0x06);
    ILI9341_WriteParam(0x0e);
    ILI9341_WriteParam(0x0c);
    ILI9341_WriteParam(0x32);
    ILI9341_WriteParam(0x38);
    ILI9341_WriteParam(0x0F);
    //數(shù)據(jù)格式16bit設置
    ILI9341_WriteCmd(0x3a);
    ILI9341_WriteParam(0x55);              //RGB接口格式16bits/pixel,MCU接口格式16bits/pixel
//    ILI9341_ExitSleepMode();              //退出睡眠模式
    ILI9341_WriteCmd(0x11);
    Delay_ms(120);
    ILI9341_WriteCmd(0X2C);      //2CH
    for(i=0;i< 240*320;i++)
    {
      ILI9341_WriteParam(0xffff);          //顯示綠屏
    }
    ILI9341_WriteCmd(0X29);
    GPIOB- >BSRRL = 1< 15;                  //開背光  
}
最后在主文件調用ILI9341的初始化函數(shù),進行測試。
#include "stm32f4xx.h"
#include "core_cm4.h"
#include "delay.h"
#include "ili9341.h"
int main()
{
  ILI9341_Init();
  while(1);
}
編譯程序并燒入開發(fā)板,LCD亮并顯示綠色,ILI9341初始化成功。
ILI9341驅動LCD涉及的引腳比較多,所以在配置時一定要細心,一旦出錯也會很難排查,所以盡量一次寫成。
 電子發(fā)燒友App
                        電子發(fā)燒友App
                     
                 
                 
           
        
 
        












 
            
             
             
                 
             工商網(wǎng)監(jiān)
工商網(wǎng)監(jiān)
        
評論