stm32f10x 点亮LCD例程1
1. 项目:使用stm32f10x点亮LCD,并显示图形。
2. 代码:
主函数:main.c
#include "stm32f10x.h" #include "./usart/bsp_usart.h" #include "./led/bsp_led.h" #include "./lcd/bsp_ili9341_lcd.h"
/*主函数*/ int main(void) { ILI9341_Init(); /*需优先配置,不然执行异常*/ LED_GPIO_Config(); LED_BLUE; /* 配置串口为:波特率115200 8-N-1 */ USART_Config(); printf("\r\n---这是一个stm32点亮LCD的实验---\r\n"); printf("\r\n0x0C命令返回值测试:0x%x",Read_Pixel_Format()); /*DBI[2:0]:101(16位/像素点)*/ ILI9341_DrawRectangle(10,20,80,40,1); /*x=10,y=20,width=80,height=40,Fillcolor=1(填充)*/ ILI9341_DrawRectangle(150,20,80,40,1); /*x=150,y=20,width=80,height=40,Fillcolor=0(不填充)*/ while(1); }
ILI9341 LCD功能定义函数: bsp_ili9341_lcd.c
#include "./lcd/bsp_ili9341_lcd.h" /*根据液晶扫描方向而变化的XY像素宽度*/ /*调用ILI9341_GramScan函数设置方向时会自动更改*/ uint16_t LCD_X_LENGTH = ILI9341_LESS_PIXEL; uint16_t LCD_Y_LENGTH = ILI9341_MORE_PIXEL;
static uint16_t CurrentTextColor = BLACK; /*显示色*/
static uint16_t CurrentTextColor2 = BLUE; /*显示色2*/
static uint16_t CurrentBackColor = WHITE; /*背景色*/ __inline void ILI9341_Write_Cmd ( uint16_t usCmd ); __inline void ILI9341_Write_Data ( uint16_t usData ); __inline uint16_t ILI9341_Read_Data ( void ); static void ILI9341_Delay ( __IO uint32_t nCount ); static void ILI9341_GPIO_Config ( void ); static void ILI9341_FSMC_Config ( void ); static void ILI9341_REG_Config ( void ); static __inline void ILI9341_FillColor ( uint32_t ulAmout_Point, uint16_t usColor );/*FSMC的GPIO初始化函数*/ void ILI9341_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; // 打开GPIO的时钟 RCC_APB2PeriphClockCmd(ILI9341_CS_CLK|ILI9341_RST_CLK|ILI9341_BK_CLK|ILI9341_RD_CLK| ILI9341_WR_CLK|ILI9341_DC_CLK|ILI9341_D0_CLK|ILI9341_D1_CLK|ILI9341_D2_CLK| ILI9341_D3_CLK|ILI9341_D4_CLK|ILI9341_D5_CLK|ILI9341_D6_CLK|ILI9341_D7_CLK| ILI9341_D8_CLK|ILI9341_D9_CLK|ILI9341_D10_CLK|ILI9341_D11_CLK|ILI9341_D12_CLK| ILI9341_D13_CLK|ILI9341_D14_CLK|ILI9341_D15_CLK , ENABLE); // 将BK, RST的GPIO配置为推挽模式 GPIO_InitStructure.GPIO_Pin = ILI9341_BK_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(ILI9341_BK_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ILI9341_RST_PIN; GPIO_Init(ILI9341_RST_PORT, &GPIO_InitStructure); // 将CS, RD, WR, DC的GPIO配置为推挽复用模式 GPIO_InitStructure.GPIO_Pin = ILI9341_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(ILI9341_CS_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ILI9341_RD_PIN; GPIO_Init(ILI9341_RD_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ILI9341_WR_PIN; GPIO_Init(ILI9341_WR_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = ILI9341_DC_PIN; GPIO_Init(ILI9341_DC_PORT, &GPIO_InitStructure); //配置FSMC相对应的数据线,FSMC-D0~D15 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Pin = ILI9341_D0_PIN; GPIO_Init ( ILI9341_D0_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D1_PIN; GPIO_Init ( ILI9341_D1_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D2_PIN; GPIO_Init ( ILI9341_D2_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D3_PIN; GPIO_Init ( ILI9341_D3_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D4_PIN; GPIO_Init ( ILI9341_D4_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D5_PIN; GPIO_Init ( ILI9341_D5_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D6_PIN; GPIO_Init ( ILI9341_D6_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D7_PIN; GPIO_Init ( ILI9341_D7_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D8_PIN; GPIO_Init ( ILI9341_D8_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D9_PIN; GPIO_Init ( ILI9341_D9_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D10_PIN; GPIO_Init ( ILI9341_D10_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D11_PIN; GPIO_Init ( ILI9341_D11_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D12_PIN; GPIO_Init ( ILI9341_D12_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D13_PIN; GPIO_Init ( ILI9341_D13_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D14_PIN; GPIO_Init ( ILI9341_D14_PORT, & GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = ILI9341_D15_PIN; GPIO_Init ( ILI9341_D15_PORT, & GPIO_InitStructure ); } //配置FSMC模式 /*把 FSMC 配置成异步 NOR FLASH 使用的模式 B,使用该方式模拟 8080 时序控制液晶屏*/ void ILI9341_FSMC_Config(void) { FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef readWriteTiming; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE); /*使能FSMC外设时钟*/ readWriteTiming.FSMC_AddressSetupTime = 0x01; //地址建立时间(ADDSET)为1个HCLK= 2/72MHz = 28ns readWriteTiming.FSMC_DataSetupTime = 0x04; //数据保持时间(DATAST)+1个HCLK = 5/72MHz = 70ns readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_B; //选择匹配SRAM的模式
/*以下配置与模式B无关*/ //地址保持时间(ADDHLD)模式B未用到 readWriteTiming.FSMC_AddressHoldTime = 0x00; //设置总线转换周期,仅用于复用模式的NOR操作 readWriteTiming.FSMC_BusTurnAroundDuration = 0x00; //设置时钟分频,仅用于同步类型的存储器 readWriteTiming.FSMC_CLKDivision = 0x00; //数据保持时间,仅用于NOR readWriteTiming.FSMC_DataLatency = 0x00; // 选择FSMC映射的存储区域: Bank1 NORSRAMx FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_BANK_NORSRAMx; //设置地址总线与数据总线是否复用,仅用于NOR FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; //设置要控制的存储器类型:NOR类型 FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_NOR; //存储器数据宽度:16位 FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; //设置是否使用突发访问模式,仅用于同步类型的存储器 FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable; //设置是否使能等待信号,仅用于同步类型的存储器 FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable; //设置等待信号的有效极性,仅用于同步类型的存储器 FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; //设置是否支持把非对齐的突发操作,仅用于同步类型的存储器 FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable; //设置等待信号插入的时间,仅用于同步类型的存储器 FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState; //存储器写使能 FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable; //不使用等待信号 FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable; // 不使用扩展模式,读写使用相同的时序 FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable; //突发写操作 FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; //读写时序配置 FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //读写同样时序,使用扩展模式时这个配置才有效 FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming; //初始化FSMC配置 FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); // 使能BANK FSMC_NORSRAMCmd(FSMC_BANK_NORSRAMx, ENABLE); } //向ILI9341写入命令 //usCmd :要写入的命令(表寄存器地址) __inline void ILI9341_Write_Cmd(uint16_t usCmd) { * ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_CMD ) = usCmd; } //向ILI9341写入数据 //usData :要写入的数据 __inline void ILI9341_Write_Data(uint16_t usData) { *( __IO uint16_t * ) ( FSMC_Addr_ILI9341_DATA ) = usData; } //从ILI9341读取数据 __inline uint16_t ILI9341_Read_Data ( void ) { return ( * ( __IO uint16_t * ) ( FSMC_Addr_ILI9341_DATA ) ); } //初始化ILI9341寄存器(向液晶屏写入初始化配置) static void ILI9341_REG_Config ( void ) { /* Power control B (CFh) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xCF ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x81 ); ILI9341_Write_Data ( 0x30 ); /* Power on sequence control (EDh) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xED ); ILI9341_Write_Data ( 0x64 ); ILI9341_Write_Data ( 0x03 ); ILI9341_Write_Data ( 0x12 ); ILI9341_Write_Data ( 0x81 ); /* Driver timing control A (E8h) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xE8 ); ILI9341_Write_Data ( 0x85 ); ILI9341_Write_Data ( 0x10 ); ILI9341_Write_Data ( 0x78 ); /* Power control A (CBh) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xCB ); ILI9341_Write_Data ( 0x39 ); ILI9341_Write_Data ( 0x2C ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x34 ); ILI9341_Write_Data ( 0x02 ); /* Pump ratio control (F7h) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xF7 ); ILI9341_Write_Data ( 0x20 ); /* Driver timing control B */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xEA ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x00 ); /* Frame Rate Control (In Normal Mode/Full Colors) (B1h) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xB1 ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x1B ); /* Display Function Control (B6h) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xB6 ); ILI9341_Write_Data ( 0x0A ); ILI9341_Write_Data ( 0xA2 ); /* Power Control 1 (C0h) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xC0 ); ILI9341_Write_Data ( 0x35 ); /* Power Control 2 (C1h) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0xC1 ); ILI9341_Write_Data ( 0x11 ); /* VCOM Control 1 (C5h) */ ILI9341_Write_Cmd ( 0xC5 ); ILI9341_Write_Data ( 0x45 ); ILI9341_Write_Data ( 0x45 ); /* VCOM Control 2 (C7h) */ ILI9341_Write_Cmd ( 0xC7 ); ILI9341_Write_Data ( 0xA2 ); /* Enable 3G (F2h) */ ILI9341_Write_Cmd ( 0xF2 ); ILI9341_Write_Data ( 0x00 ); /* Gamma Set (26h) */ ILI9341_Write_Cmd ( 0x26 ); ILI9341_Write_Data ( 0x01 ); DEBUG_DELAY (); /* Positive Gamma Correction */ ILI9341_Write_Cmd ( 0xE0 ); //Set Gamma ILI9341_Write_Data ( 0x0F ); ILI9341_Write_Data ( 0x26 ); ILI9341_Write_Data ( 0x24 ); ILI9341_Write_Data ( 0x0B ); ILI9341_Write_Data ( 0x0E ); ILI9341_Write_Data ( 0x09 ); ILI9341_Write_Data ( 0x54 ); ILI9341_Write_Data ( 0xA8 ); ILI9341_Write_Data ( 0x46 ); ILI9341_Write_Data ( 0x0C ); ILI9341_Write_Data ( 0x17 ); ILI9341_Write_Data ( 0x09 ); ILI9341_Write_Data ( 0x0F ); ILI9341_Write_Data ( 0x07 ); ILI9341_Write_Data ( 0x00 ); /* Negative Gamma Correction (E1h) */ ILI9341_Write_Cmd ( 0XE1 ); //Set Gamma ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x19 ); ILI9341_Write_Data ( 0x1B ); ILI9341_Write_Data ( 0x04 ); ILI9341_Write_Data ( 0x10 ); ILI9341_Write_Data ( 0x07 ); ILI9341_Write_Data ( 0x2A ); ILI9341_Write_Data ( 0x47 ); ILI9341_Write_Data ( 0x39 ); ILI9341_Write_Data ( 0x03 ); ILI9341_Write_Data ( 0x06 ); ILI9341_Write_Data ( 0x06 ); ILI9341_Write_Data ( 0x30 ); ILI9341_Write_Data ( 0x38 ); ILI9341_Write_Data ( 0x0F ); /* memory access control set */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0x36 ); ILI9341_Write_Data ( 0xC8 ); /*竖屏 左上角到 (起点)到右下角 (终点)扫描方式*/ DEBUG_DELAY (); /* column address control set */ ILI9341_Write_Cmd ( CMD_SetCoordinateX ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0xEF ); /* page address control set */ DEBUG_DELAY (); ILI9341_Write_Cmd ( CMD_SetCoordinateY ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x00 ); ILI9341_Write_Data ( 0x01 ); ILI9341_Write_Data ( 0x3F ); /* Pixel Format Set (3Ah) */ DEBUG_DELAY (); ILI9341_Write_Cmd ( 0x3a ); ILI9341_Write_Data ( 0x55 ); /* Sleep Out (11h) */ ILI9341_Write_Cmd ( 0x11 ); ILI9341_Delay ( 0xAFFf<<2 ); DEBUG_DELAY (); /* Display ON (29h) */ ILI9341_Write_Cmd ( 0x29 ); } /*在ILI9341显示器上开辟一个窗口*/ void ILI9341_OpenWindow(uint16_t usX,uint16_t usY,uint16_t usWidth,uint16_t usHeight) { /*usX: 起始X坐标值, usY: 起始Y坐标值; usWidth: 窗口宽度值, usHeight: 窗口高度值*/ /* column address control set */ ILI9341_Write_Cmd ( CMD_SetCoordinateX ); ILI9341_Write_Data ( (usX&0xFF00) >> 8 ); /*先高8位,再低8位*/ ILI9341_Write_Data ( (usX&0x00FF) ); ILI9341_Write_Data ( ((usX+usWidth-1)&0xFF00) >> 8 ); /*设置起始点和结束点*/ ILI9341_Write_Data ( ((usX+usWidth-1)&0x00FF) ); ILI9341_Write_Cmd ( CMD_SetCoordinateY ); ILI9341_Write_Data ( (usY&0xFF00) >> 8 ); ILI9341_Write_Data ( (usY&0x00FF) ); ILI9341_Write_Data ( ((usY+usHeight-1)&0xFF00) >> 8 ); ILI9341_Write_Data ( ((usY+usHeight-1)&0x00FF) ); } //读取像素格式 uint16_t Read_Pixel_Format(void) { ILI9341_Write_Cmd(0x0C); ILI9341_Read_Data(); return ILI9341_Read_Data(); } //ILI9341背光LED控制 //enumState :决定是否使能背光LED //该参数为以下值之一: //ENABLE :使能背光LED //DISABLE :禁用背光LED void ILI9341_BackLed_Control ( FunctionalState enumState ) { if ( enumState ) GPIO_ResetBits ( ILI9341_BK_PORT, ILI9341_BK_PIN ); else GPIO_SetBits ( ILI9341_BK_PORT, ILI9341_BK_PIN ); } //用于 ILI9341 简单延时函数 //nCount :延时计数值 static void ILI9341_Delay ( __IO uint32_t nCount ) { for ( ; nCount != 0; nCount -- ); } //ILI9341 软件复位 void ILI9341_Rst ( void ) { GPIO_ResetBits ( ILI9341_RST_PORT, ILI9341_RST_PIN ); //低电平复位 ILI9341_Delay ( 0xAFF ); GPIO_SetBits ( ILI9341_RST_PORT, ILI9341_RST_PIN ); ILI9341_Delay ( 0xAFF ); } //像素颜色填充函数 static __inline void ILI9341_FillColor(uint32_t ulAmount_Point, uint16_t usColor) { uint32_t i=0; /*memory write*/ ILI9341_Write_Cmd(CMD_SetPixel); for(i=0; i<ulAmount_Point; i++) { ILI9341_Write_Data(usColor); } } //设定ILI9341光标坐标 static void ILI9341_SetCursor(uint16_t usX, uint16_t usY) /*usX: 在特定扫描方向下改点的X坐标*/ { /*usY: 在特定扫描方向下改点的Y坐标*/ ILI9341_OpenWindow(usX, usY, 1, 1); } //对显示器某点以某种颜色填充 void ILI9341_SetPointPixel(uint16_t usX, uint16_t usY) { if((usX<LCD_X_LENGTH) && (usY<LCD_Y_LENGTH)) { ILI9341_SetCursor(usX, usY); ILI9341_FillColor(1,CurrentTextColor); } } /** * @brief 在 ILI9341 显示器上画一个矩形 * @param usX_Start :在特定扫描方向下矩形的起始点X坐标 * @param usY_Start :在特定扫描方向下矩形的起始点Y坐标 * @param usWidth:矩形的宽度(单位:像素) * @param usHeight:矩形的高度(单位:像素) * @param ucFilled :选择是否填充该矩形 * 该参数为以下值之一: * @arg 0 :空心矩形 * @arg 1 :实心矩形 * @note 可使用LCD_SetBackColor、LCD_SetTextColor、LCD_SetColors函数设置颜色 * @retval 无 */ void ILI9341_DrawRectangle ( uint16_t usX_Start, uint16_t usY_Start, uint16_t usWidth, uint16_t usHeight, uint8_t ucFilled ) { if ( ucFilled ) { ILI9341_OpenWindow ( usX_Start, usY_Start, usWidth, usHeight ); ILI9341_FillColor ( usWidth * usHeight ,CurrentTextColor); }
else
{
ILI9341_OpenWindow(usX_Start, usY_Start, usWidth, usHeight);
ILI9341_FillColor(usWidth * usHeight, CurrentTextColor2);
}
} //初始化LCD void ILI9341_Init(void) { ILI9341_GPIO_Config(); ILI9341_FSMC_Config(); ILI9341_BackLed_Control(ENABLE); /*点亮LCD背光*/ ILI9341_Rst(); ILI9341_REG_Config(); } /*ILI9341显示器的某一窗口以某种颜色进行清屏*/ void ILI9341_Clear(uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight) { ILI9341_OpenWindow(usX, usY, usWidth, usHeight); ILI9341_FillColor(usWidth * usHeight, CurrentBackColor); }
头文件定义:bsp_ili9341_lcd.h
#ifndef __ILI9341_LCD_H #define __ILI9341_LCD_H #include "stm32f10x.h" /*FSMC_Bank1_NORSRAM用于LCD命令操作的地址*/ #define FSMC_Addr_ILI9341_CMD ((uint32_t) 0x60000000) /*FSMC_Bank1_NORSRAM用于LCD数据操作的地址*/ #define FSMC_Addr_ILI9341_DATA ((uint32_t) 0x60020000) #define USE_ZNZ 1 /*LCD控制信号****************************/ #ifdef USE_ZNZ /*指南者开发板*/ /*由片选引脚决定的NOR/SRAM块*/ #define FSMC_BANK_NORSRAMx FSMC_Bank1_NORSRAM1 #define ILI9341_CMD_ADDR (__IO uint16_t*)(0x60000000) #define ILI9341_DATA_ADDR (__IO uint16_t*)(0x60020000) #define ILI9341_CS_CLK RCC_APB2Periph_GPIOD #define ILI9341_CS_PORT GPIOD #define ILI9341_CS_PIN GPIO_Pin_7 #define ILI9341_RST_CLK RCC_APB2Periph_GPIOE #define ILI9341_RST_PORT GPIOE #define ILI9341_RST_PIN GPIO_Pin_1 #define ILI9341_BK_CLK RCC_APB2Periph_GPIOD #define ILI9341_BK_PORT GPIOD #define ILI9341_BK_PIN GPIO_Pin_12 #define ILI9341_RD_CLK RCC_APB2Periph_GPIOD #define ILI9341_RD_PORT GPIOD #define ILI9341_RD_PIN GPIO_Pin_4 #define ILI9341_WR_CLK RCC_APB2Periph_GPIOD #define ILI9341_WR_PORT GPIOD #define ILI9341_WR_PIN GPIO_Pin_5 #define ILI9341_DC_CLK RCC_APB2Periph_GPIOD #define ILI9341_DC_PORT GPIOD #define ILI9341_DC_PIN GPIO_Pin_11 #else /*霸道开发板*/ #define FSMC_BANK_NORSRAMx FSMC_Bank1_NORSRAM4 #define ILI9341_CMD_ADDR (__IO uint16_t*)(0x6c000000) #define ILI9341_DATA_ADDR (__IO uint16_t*)(0x6d000000) #define ILI9341_CS_CLK RCC_APB2Periph_GPIOG #define ILI9341_CS_PORT GPIOG #define ILI9341_CS_PIN GPIO_Pin_12 #define ILI9341_RST_CLK RCC_APB2Periph_GPIOG #define ILI9341_RST_PORT GPIOG #define ILI9341_RST_PIN GPIO_Pin_11 #define ILI9341_BK_CLK RCC_APB2Periph_GPIOG #define ILI9341_BK_PORT GPIOG #define ILI9341_BK_PIN GPIO_Pin_6 #define ILI9341_RD_CLK RCC_APB2Periph_GPIOD #define ILI9341_RD_PORT GPIOD #define ILI9341_RD_PIN GPIO_Pin_4 #define ILI9341_WR_CLK RCC_APB2Periph_GPIOD #define ILI9341_WR_PORT GPIOD #define ILI9341_WR_PIN GPIO_Pin_5 #define ILI9341_DC_CLK RCC_APB2Periph_GPIOE #define ILI9341_DC_PORT GPIOE #define ILI9341_DC_PIN GPIO_Pin_2 #endif #define ILI9341_D0_CLK RCC_APB2Periph_GPIOD #define ILI9341_D0_PORT GPIOD #define ILI9341_D0_PIN GPIO_Pin_14 #define ILI9341_D1_CLK RCC_APB2Periph_GPIOD #define ILI9341_D1_PORT GPIOD #define ILI9341_D1_PIN GPIO_Pin_15 #define ILI9341_D2_CLK RCC_APB2Periph_GPIOD #define ILI9341_D2_PORT GPIOD #define ILI9341_D2_PIN GPIO_Pin_0 #define ILI9341_D3_CLK RCC_APB2Periph_GPIOD #define ILI9341_D3_PORT GPIOD #define ILI9341_D3_PIN GPIO_Pin_1 #define ILI9341_D4_CLK RCC_APB2Periph_GPIOE #define ILI9341_D4_PORT GPIOE #define ILI9341_D4_PIN GPIO_Pin_7 #define ILI9341_D5_CLK RCC_APB2Periph_GPIOE #define ILI9341_D5_PORT GPIOE #define ILI9341_D5_PIN GPIO_Pin_8 #define ILI9341_D6_CLK RCC_APB2Periph_GPIOE #define ILI9341_D6_PORT GPIOE #define ILI9341_D6_PIN GPIO_Pin_9 #define ILI9341_D7_CLK RCC_APB2Periph_GPIOE #define ILI9341_D7_PORT GPIOE #define ILI9341_D7_PIN GPIO_Pin_10 #define ILI9341_D8_CLK RCC_APB2Periph_GPIOE #define ILI9341_D8_PORT GPIOE #define ILI9341_D8_PIN GPIO_Pin_11 #define ILI9341_D9_CLK RCC_APB2Periph_GPIOE #define ILI9341_D9_PORT GPIOE #define ILI9341_D9_PIN GPIO_Pin_12 #define ILI9341_D10_CLK RCC_APB2Periph_GPIOE #define ILI9341_D10_PORT GPIOE #define ILI9341_D10_PIN GPIO_Pin_13 #define ILI9341_D11_CLK RCC_APB2Periph_GPIOE #define ILI9341_D11_PORT GPIOE #define ILI9341_D11_PIN GPIO_Pin_14 #define ILI9341_D12_CLK RCC_APB2Periph_GPIOE #define ILI9341_D12_PORT GPIOE #define ILI9341_D12_PIN GPIO_Pin_15 #define ILI9341_D13_CLK RCC_APB2Periph_GPIOD #define ILI9341_D13_PORT GPIOD #define ILI9341_D13_PIN GPIO_Pin_8 #define ILI9341_D14_CLK RCC_APB2Periph_GPIOD #define ILI9341_D14_PORT GPIOD #define ILI9341_D14_PIN GPIO_Pin_9 #define ILI9341_D15_CLK RCC_APB2Periph_GPIOD #define ILI9341_D15_PORT GPIOD #define ILI9341_D15_PIN GPIO_Pin_10 /*************************************** 调试预用 ******************************************/ #define DEBUG_DELAY() /****************************** ILI9341显示区域的起始坐标********************************/ #define ILI9341_LESS_PIXEL 240 //液晶屏较短方向的像素宽度 #define ILI9341_MORE_PIXEL 320 //液晶屏较长方向的像素宽度 /*******************************定义ILI9341常用颜色***********************************/ #define BACKGROUND BLACK /*默认黑色*/ #define WHITE 0XFFFF #define BLACK 0X0000 #define GREY 0XF7DE #define BLUE 0X001F #define BLUE2 0X051F #define RED 0XF800 #define MAGENTA 0XF81F #define GREEN 0X07E0 #define CYAN 0X7FFF #define YELLOW 0XFFE0 #define BRED 0XF81F #define GRED 0XFFE0 #define GBLUE 0X07FF /******************************* 定义 ILI934 常用命令 ********************************/ #define CMD_SetCoordinateX 0x2A //设置X坐标,Columu Address Set命令 #define CMD_SetCoordinateY 0x2B //设置Y坐标,Page Address Set命令 #define CMD_SetPixel 0x2C //填充像素 /**************************声明ILI9341函数************************************************/ void ILI9341_Init(void); void ILI9341_Rst(void); void ILI9341_BackLed_Control(FunctionalState enumState); void ILI9341_OpenWindow( uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight ); void ILI9341_Clear( uint16_t usX, uint16_t usY, uint16_t usWidth, uint16_t usHeight ); void ILI9341_SetPointPixel( uint16_t usX, uint16_t usY ); void ILI9341_DrawRectangle( uint16_t usX_Start, uint16_t usY_Start, uint16_t usWidth, uint16_t usHeight,uint8_t ucFilled ); uint16_t Read_Pixel_Format(void); #endif /* __ILI9341_LCD_H */
3. 执行结果:
- LCD显示两个不同颜色对称的矩形图案;
- 串口调试助手输出
---这是一个stm32点亮LCD的实验---
0x0C命令返回值测试:0x5
4. 参考资料
- 原理图
- 液晶结构
-
液晶控制原理
-
液晶传输时序
-
液晶屏有一个显示指针,它指向将要显示的像素。显示指针的扫描方向方向从左到右、从上到下,一个像素点一个像素点地描绘图形。
-
显存
-
液晶屏中的每个像素点都是数据,在实际应用中需要把每个像素点的数据缓存起来,再传输给液晶屏,一般会使用 SRAM 或 SDRAM 性质的存储器,而这些专门用于存储显示数据的存储器,则被称为显存。
-
本液晶屏内部包含有一个液晶控制芯片 ILI9341,它的内部结构非常复杂,见图 ILI9341 控制器内部框图 。该芯片最主核心部分是位于中间的 GRAM(Graphics RAM),它就是显存。GRAM 中每个存储单元都对应着液晶面板的一个像素点。它右侧的各种模块共同作用把 GRAM 存储单元的数据转化成液晶面板的控制信号,使像素点现特定的颜色,而像素点组合起来则成为一幅完整的图像。
- ILI9341内部框图
-
使用 STM32 的 FSMC 模拟 8080 接口时序
-
ILI9341 的 8080 通讯接口时序可以由 STM32 使用普通 I/O 接口进行模拟,但这样效率太低,STM32 提供了一种特别的控制方法——使用 FSMC 接口实现 8080 时序。
5. FSMC
The FSMC block is able to interface with synchronous and asynchronous memories and 16-bit PC memory cards. Its main purpose is to:
FSMC模块可以与同步和异步存储器以及16位 pc 存储卡进行交互。主要目的如下:
•Translate the AHB transactions into the appropriate external device protocol
将AHB传输信号转换到适当的外部设备协议
•Meet the access timing requirements of the external devices
满足外部设备的访问时序要求
All external memories share the addresses, data and control signals with the controller.Each external device is accessed by means of a unique chip select. The FSMC performs only one access at a time to an external device.
所有外部存储器与控制器共享地址、数据和控制信号。每个外部设备都通过一个独特的芯片选择进行访问。FSMC一次只能访问一个外部设备。
-
FSMC是 Flexible Static Memory Controller 灵活的静态存储控制器
-
STM32F1 系列芯片使用 FSMC 外设来管理扩展的存储器,它可以用于驱动包括 SRAM、NOR FLASH 以及 NAND FLSAH 类型的存储器,不能驱动如 SDRAM 这种动态的存储器。
-
只有大容量产品才具有FSMC功能,大容量产品是指闪存存储器容量在256K至512K字节之间的STM32F101xx和STM32F103xx微控制器。
-
由于 FSMC 外设可以用于控制扩展的外部存储器,而 MCU 对液晶屏的操作实际上就是把显示数据写入到显存中,与控制存储器非常类似,且 8080 接口的通讯时序完全可以使用 FSMC 外设产生,因而非常适合使用 FSMC 控制液晶屏。
- FSMC外设结构图
-
-
控制 LCD 时,是使用 FSMC 的 NORPSRAM 模式的,而且控制 LCD 时使用的是NOR FLASH 类型的模式 B.
6. stm32f10x与ILI9341通讯
7. 总结:
- stm32f10x单片机控制LCD显示时,需要通过stm32中的FSMC模拟8080时序控制ILI9341(显存芯片)进行存储需要显示的图片信息,然后再通过RGB接口将图像信息传输给LCD显示。