1) i80-system MPU 接口(8-/9-/16-/18-bit bus width)
2) serial data transfer 接口(SPI)
3) RGB 6-/16-/18-bit 接口(DOTCLK, VSYNC, HSYNC, ENABLE, DB[17:0]).
此屏的ILI9341的18位RGB赋值与 LCD GRAM的对应关系如图所示:
从图中可以看出,ILI9341 在16 位模式下面,GRAM Data有用的是:D17~D13 和 D11~D1, D12和 D0 没有用到,实际上在我们 LCD 模块里面, ILI9341 的 D12 和 D0没有引出,ILI9341 的 D17~D13 和 D11~D1对应 MCU 的 D15~D0。MCU 的 16 位数据,最低 5 位代表蓝色,中间 6 位为绿色,最高 5 位为红色;数值越大,表示该颜色越深。
8080接口是由英特尔设计,是一种并行、异步、半双工通信协议,作用是用于外扩RAM、ROM,后面也用于LCD接口。
RD:写使能(将信息写入寄存器) WR:读使能(从寄存器读出信息) DC(RS):数据/命令(1为数据读写,0为命令读写) CS:片选
引脚号 | 标识 | 描述 | 功能 |
1 | 5V | 5V电源 | 当5V供电时(1,2脚接5V电源),3.3V端(33,34脚输出3.3V电压) |
2 | GND | 接地 | GND |
3 | D0 | 数据线 | D0-D15 |
4 | D1 | ||
5 | D2 | ||
6 | D3 | ||
7 | D4 | ||
8 | D5 | ||
9 | D6 | ||
10 | D7 | ||
11 | D8 | ||
12 | D9 | ||
13 | D10 | ||
14 | D11 | ||
15 | D12 | ||
16 | D13 | ||
17 | D14 | ||
18 | D15 | ||
19 | CS | LCD片选信号 | 低电平选择LCD |
20 | RS | 指令/数据 寄存器选择 | RS = 0:指令寄存器 RS = 1:数据寄存器 |
21 | WR | 写动作 | WR = 0,RD = 1 |
22 | RD | 读动作 | WR = 1,RD = 0 |
23 | RESET | 芯片重启 | 低电平重启芯片 |
24 | NC | ||
25 | BLVCC | 5V或3.3V | 背光灯VCC |
26 | BLGND | 接地 | 背光灯GND |
27 | BLCNT | 背光灯亮度调节 | 可以使用PWM来控制背光灯亮度 |
28 | TP_IRQ | 触摸面板中断 | 检测到触摸面板有按下则为低电平 |
29 | TP_CS | 触摸面板片选信号 | 低电平选择触摸面板 |
30 | TP_SCK | 触摸面板SPI时钟信号 | 连接到SPI的SCK |
31 | TP_SI | 触摸面板SPI数据输入 | 连接到SPI的MOSI |
32 | TP_SO | 触摸面板SPI数据输出 | 连接到SPI的MISO |
33 | 3.3V | +3.3电源 | 当3.3V供电时(33,34脚输入3.3V) 1,2脚悬空 |
34 | GND | 接地 |
本手册使用主控芯片STM32F103RCT6的开发板说明本款LCD的基本使用方法。用户也可以采用其他类似的开发板进行开发。
3.2inch 320x240 Touch LCD (D)和STM32F103RCT6连接接口图:
程序流程:
源代码解析:
/*下面宏定义的是图像的旋转角度跟设置控制线*/<br /> //#define DISP_ORIENTATION 0 //#define DISP_ORIENTATION 90 //#define DISP_ORIENTATION 180 #define DISP_ORIENTATION 270 #define Set_Cs GPIOC->BSRR = GPIO_Pin_6 //CS=1 #define Clr_Cs GPIOC->BRR = GPIO_Pin_6 //CS=0 #define Set_Rs GPIOC->BSRR = GPIO_Pin_7 //RS=1 #define Clr_Rs GPIOC->BRR = GPIO_Pin_7 //RS=0 #define Set_nWr GPIOC->BSRR = GPIO_Pin_1 //WR=1 #define Clr_nWr GPIOC->BRR = GPIO_Pin_1 //WR=0 #define Set_nRd GPIOC->BSRR = GPIO_Pin_2 //RD=1 #define Clr_nRd GPIOC->BRR = GPIO_Pin_2 //RD=0 /* 写命令函数 */ __inline void LCD_WriteIndex(uint16_t index) { Clr_Rs; //RS=0 Set_nRd; //RD=0 LCD_Delay(0); //延时 GPIOB->ODR = index; /*写命令 */ LCD_Delay(0); //延时 Clr_nWr; //WR=0 Set_nWr; //WR=1 } /* 写数据函数 */ __inline void ILI9341_LCD_WriteData(uint16_t data) { Clr_Cs; //CS=1 Set_Rs; //RS=1 LCD_Delay(0); //delay GPIOB->ODR = data; /* GPIO_Write(GPIOB,data); */ LCD_Delay(0); //delay Clr_nWr; //WR=0 Set_nWr; //WR=1 Set_Cs; //CS=1 } /* 读数据函数 */ __inline uint16_t LCD_ReadData(void) { uint16_t value; Set_Rs; Set_nWr; Clr_nRd; GPIOB->CRH = 0x44444444; //设置PB0-PB15为输入 GPIOB->CRL = 0x44444444; value = GPIOB->IDR; //读取数据 GPIOB->CRH = 0x33333333; //设置PB0-PB15为输出 GPIOB->CRL = 0x33333333; Set_nRd; return value; } /****************************************************************************** 指定的地址写入数据,LCD_Reg是地址,LCD_RegValue是写入的值。 ******************************************************************************/ __inline void LCD_WriteReg(uint16_t LCD_Reg,uint16_t LCD_RegValue) { Clr_Cs; LCD_WriteIndex(LCD_Reg); //写指令;即要写入数据的地址; LCD_WriteData(LCD_RegValue); //数据写入; Set_Cs; } /****************************************************************************** 从指定的地址读取数据,LCD_Reg是地址,函数返回读取出来的值。 <pre> ******************************************************************************/ __inline uint16_t LCD_ReadReg(uint16_t LCD_Reg) { uint16_t LCD_RAM; Clr_Cs; LCD_WriteIndex(LCD_Reg); //写指令;即要读出数据的地址; LCD_RAM = LCD_ReadData(); //数据读出; Set_Cs; return LCD_RAM; } //以上是最基本的读写函数;IO模拟操作,如果想STM32的FSMC来控制的,参考另外一个例程LCD + TouchPanel(8080 FSMC) /****************************************************************************** LCD寄存器的初始化,以下寄存器的初始化值由LCD原厂家提供,按照如下配置就可以正常显示,寄存器请参考芯片手册。 ******************************************************************************/ void LCD_Initializtion(void) { uint16_t DeviceCode; LCD_Configuration(); //管脚初始化 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);//改变指定管脚的映射 GPIO_ResetBits(GPIOC, GPIO_Pin_0); /* LCD复位*/ delay_ms(100); GPIO_SetBits(GPIOC, GPIO_Pin_0); GPIO_SetBits(GPIOA, GPIO_Pin_3); /*使能背光 */ DeviceCode = LCD_ReadReg(0x0000); /* 读取ID */ if(DeviceCode == 0 || DeviceCode == 0xffff) { ILI9341_LCD_WriteReg(0XD3); Clr_Cs; DeviceCode = LCD_ReadData(); DeviceCode = LCD_ReadData(); DeviceCode = LCD_ReadData(); DeviceCode <<= 8; DeviceCode |= LCD_ReadData(); Set_Cs; } if(DeviceCode == 0x9341) { LCD_Code = ILI9341; ILI9341_LCD_WriteReg(0x3A); ILI9341_LCD_WriteData(0x55); ILI9341_LCD_WriteReg(0xB5); ILI9341_LCD_WriteData(0X04); ILI9341_LCD_WriteData(0X04); ILI9341_LCD_WriteData(0X0A); ILI9341_LCD_WriteData(0x14); ILI9341_LCD_WriteReg(0x35); ILI9341_LCD_WriteData(0x00); ILI9341_LCD_WriteReg(0xCF); ILI9341_LCD_WriteData(0x00); ILI9341_LCD_WriteData(0xEA); ILI9341_LCD_WriteData(0XF0); ILI9341_LCD_WriteReg(0xED); ILI9341_LCD_WriteData(0x64); ILI9341_LCD_WriteData(0x03); ILI9341_LCD_WriteData(0X12); ILI9341_LCD_WriteData(0X81); ILI9341_LCD_WriteReg(0xE8); ILI9341_LCD_WriteData(0x85); ILI9341_LCD_WriteData(0x10); ILI9341_LCD_WriteData(0x78); ILI9341_LCD_WriteReg(0xCB); ILI9341_LCD_WriteData(0x39); ILI9341_LCD_WriteData(0x2C); ILI9341_LCD_WriteData(0x00); ILI9341_LCD_WriteData(0x33); ILI9341_LCD_WriteData(0x06); ILI9341_LCD_WriteReg(0xF7); ILI9341_LCD_WriteData(0x20); ILI9341_LCD_WriteReg(0xEA); ILI9341_LCD_WriteData(0x00); ILI9341_LCD_WriteData(0x00); ILI9341_LCD_WriteReg(0xC0); //Power control ILI9341_LCD_WriteData(0x21); //VRH[5:0] ILI9341_LCD_WriteReg(0xC1); //Power control ILI9341_LCD_WriteData(0x10); //SAP[2:0];BT[3:0] ILI9341_LCD_WriteReg(0xC5); //VCM control ILI9341_LCD_WriteData(0x4F); //3F ILI9341_LCD_WriteData(0x38); //3C ILI9341_LCD_WriteReg(0xC7); //VCM control2 ILI9341_LCD_WriteData(0XB7); ILI9341_LCD_WriteReg(0x36); // Memory Access Control if (DISP_ORIENTATION == 0) ILI9341_LCD_WriteData(0x08 | 0x00); else if (DISP_ORIENTATION == 90) ILI9341_LCD_WriteData(0x08 | 0xa0); else if(DISP_ORIENTATION == 180) ILI9341_LCD_WriteData(0x08 | 0xc0); else ILI9341_LCD_WriteData(0x08 | 0x60); ILI9341_LCD_WriteReg(0xB1); ILI9341_LCD_WriteData(0x00); ILI9341_LCD_WriteData(0x13); ILI9341_LCD_WriteReg(0xB6); // Display Function Control ILI9341_LCD_WriteData(0x0A); ILI9341_LCD_WriteData(0xA2); ILI9341_LCD_WriteReg(0xF2); // 3Gamma Function Disable ILI9341_LCD_WriteData(0x02); ILI9341_LCD_WriteReg(0x26); //Gamma curve selected ILI9341_LCD_WriteData(0x01); ILI9341_LCD_WriteReg(0xE0); //Set Gamma ILI9341_LCD_WriteData(0x0F); ILI9341_LCD_WriteData(0x27); ILI9341_LCD_WriteData(0x24); ILI9341_LCD_WriteData(0x0C); ILI9341_LCD_WriteData(0x10); ILI9341_LCD_WriteData(0x08); ILI9341_LCD_WriteData(0x55); ILI9341_LCD_WriteData(0X87); ILI9341_LCD_WriteData(0x45); ILI9341_LCD_WriteData(0x08); ILI9341_LCD_WriteData(0x14); ILI9341_LCD_WriteData(0x07); ILI9341_LCD_WriteData(0x13); ILI9341_LCD_WriteData(0x08); ILI9341_LCD_WriteData(0x00); ILI9341_LCD_WriteReg(0XE1); //Set Gamma ILI9341_LCD_WriteData(0x00); ILI9341_LCD_WriteData(0x0F); ILI9341_LCD_WriteData(0x12); ILI9341_LCD_WriteData(0x05); ILI9341_LCD_WriteData(0x11); ILI9341_LCD_WriteData(0x06); ILI9341_LCD_WriteData(0x25); ILI9341_LCD_WriteData(0x34); ILI9341_LCD_WriteData(0x37); ILI9341_LCD_WriteData(0x01); ILI9341_LCD_WriteData(0x08); ILI9341_LCD_WriteData(0x07); ILI9341_LCD_WriteData(0x2B); ILI9341_LCD_WriteData(0x34); ILI9341_LCD_WriteData(0x0F); ILI9341_LCD_WriteReg(0x11); //Exit Sleep delay_ms(120); ILI9341_LCD_WriteReg(0x29); //display on } delay_ms(50); } /****************************************************************************** 设置显示窗口的位置X、Y; *****************************************************************************/ void LCD_Address_Set(u16 x1,u16 y1,u16 x2,u16 y2) { ILI9341_LCD_WriteReg(0x2a);//Column address setting 列地址设置 ILI9341_LCD_WriteData(x1>>8); ILI9341_LCD_WriteData(x1&0xff); ILI9341_LCD_WriteData(x2>>8); ILI9341_LCD_WriteData(x2&0xff); ILI9341_LCD_WriteReg(0x2b);//Line address Setting 行地址设置 ILI9341_LCD_WriteData(y1>>8); ILI9341_LCD_WriteData(y1&0xff); ILI9341_LCD_WriteData(y2>>8); ILI9341_LCD_WriteData(y2&0xff); ILI9341_LCD_WriteReg(0x2c);//Write in memory 写入内存 } static void LCD_SetCursor( uint16_t Xpos, uint16_t Ypos ) { uint16_t temp; #if (DISP_ORIENTATION == 0) #elif (DISP_ORIENTATION == 90) temp = Xpos; Xpos =Ypos; Ypos = MAX_X - 1 - temp; #elif (DISP_ORIENTATION == 180) Xpos = MAX_X - 1 - Xpos; Ypos = MAX_Y - 1 - Ypos; #elif (DISP_ORIENTATION == 270) temp = Ypos; Ypos = Xpos; Xpos = MAX_Y - 1 - temp; #endif ILI9341_LCD_WriteReg(0x2a); //Column address setting 列地址设置 ILI9341_LCD_WriteData(Xpos>>8); ILI9341_LCD_WriteData(Xpos&0xff); ILI9341_LCD_WriteReg(0x2b); //Line address Setting 行地址设置 ILI9341_LCD_WriteData(Ypos>>8); ILI9341_LCD_WriteData(Ypos&0xff); } /****************************************************************************** 清屏函数,作用是让整个屏显示某一种颜色, *****************************************************************************/ void LCD_Clear(uint16_t Color) { uint32_t index=0; LCD_Address_Set(0,0,MAX_X-1,MAX_Y-1);//Set Display range Set the display range 设置显示范围 for( index = 0; index < MAX_X * MAX_Y; index++ ) { ILI9341_LCD_WriteData(Color); } } int main(void) { //延时和初始化系统 LCD_Initializtion(); //LCD初始化 //LCD触摸板初始化 LCD_Clear(Red); //清屏为红色 //您可以编写函数来校准屏幕。 /* Infinite loop */ while (1) { //您可以编写函数,把触摸点坐标显示在 LCD 上 } }