对于主函数来数,只需要
int main(void) { SystemInit(); SysTick_Init(); LCD_Init(); while(1){ Delay(10); } }即可,初始化系统,系统时钟,初始化LCD屏。
system_stm32f4xx.c文件中有SystemInit()函数,里面的内容不用改,直接拿来可以用。
SysTick_Init函数是自己实现的
void SysTick_Init(void) { while(SysTick_Config(SystemCoreClock/1000000)!=0); //设置系统节拍时钟为1us中断一次 }下面是关键的LCD初始化函数
首先,需要知道,硬件是如何连接的,下面是我的连接线方式:
PD14 -----FSMC_D0 ----D0
PD15 -----FSMC_D1 ----D1
PD0 -----FSMC_D2 ----D2
PD1 -----FSMC_D3 ----D3
PE7 -----FSMC_D4 ---D4
PE8 -----FSMC_D5 ---D5
PE9 -----FSMC_D6 ---D6
PE10 -----FSMC_D7 ----D7
PE11 -----FSMC_D8 ----D8
PE12 -----FSMC_D9 ----D9
PE13 -----FSMC_D10 ----D10
PE14 -----FSMC_D11 ----D11
PE15 -----FSMC_D12 ----D12
PD8 -----FSMC_D13 ----D13
PD9 -----FSMC_D14 ----D14
PD10 -----FSMC_D15 ----D15
PD4 -----FSMC_NOE -----RD
PD5 -----FSMC_NWE ----WR
PD7 -----FSMC_NE1 ----CS
PE3 -----FSMC_A19 ----RS
没有背光控制,我直接让背光常亮,RESET引脚我连接到了单片机RESET引脚上了。使用了NE1。
#define LCD_RAM *(vu16*)((u32)0x60100000) //disp Data ADDR
#define LCD_REG *(vu16*)((u32)0x60000000) //disp Reg ADDR
下面是我的能用的 初始化 函数
void LCD_Init(void) { LCD_FSMC_Config(); delay_nms(50); LCD_WR_REG(0x0011); //退出睡眠模式,0x0010为进入 delay_nms(50); LCD_WR_REG(0x0013); //进入普通显示模式 LCD_WR_REG(0x00D0); //设置电源参数,后续3个参数 LCD_WR_DATA(0x0007); //1.0xVci 07 LCD_WR_DATA(0x0042); //40 LCD_WR_DATA(0x0018); //1c LCD_WR_REG(0x00D1); //Vcom Control 后续三个参数 LCD_WR_DATA(0x0000); //00 LCD_WR_DATA(0x0007); //18 LCD_WR_DATA(0x0010); //1d LCD_WR_REG(0x00D2); //设置普通模式下的电源参数,后续两个参数 LCD_WR_DATA(0x0001); //01 LCD_WR_DATA(0x0011); //11 LCD_WR_REG(0x00C0); //Panel Driving setting 后续5个参数 LCD_WR_DATA(0x0010); //设置扫描模式 00 LCD_WR_DATA(0x003B); //设定行数480行 3B LCD_WR_DATA(0x0000); //00 LCD_WR_DATA(0x0002); //5frames 02 LCD_WR_DATA(0x0011); //11 LCD_WR_REG(0x00C1); //Timing setting 后续3个参数 LCD_WR_DATA(0x0010); //10 LCD_WR_DATA(0x000B); //0B LCD_WR_DATA(0x0088); //88 LCD_WR_REG(0x00C5); //Frame Rate and Inversion Control 后续一个参数 LCD_WR_DATA(0x0001); //100hz LCD_WR_REG(0x00C8); //伽马校正,后续12个参数 //00 30 36 45 04 16 37 75 77 54 0f 00 LCD_WR_DATA(0x0000);LCD_WR_DATA(0x0032);LCD_WR_DATA(0x0036); LCD_WR_DATA(0x0045);LCD_WR_DATA(0x0006);LCD_WR_DATA(0x0016); LCD_WR_DATA(0x0037);LCD_WR_DATA(0x0075);LCD_WR_DATA(0x0077); LCD_WR_DATA(0x0054);LCD_WR_DATA(0x000f);LCD_WR_DATA(0x0000); LCD_WR_REG(0x0036);LCD_WR_DATA(0x000a); LCD_WR_REG(0x003A);LCD_WR_DATA(0x0055); LCD_WR_REG(0x002A); //00 00 01 3F LCD_WR_DATA(0x0000); LCD_WR_DATA(0x0000); LCD_WR_DATA(0x0001); LCD_WR_DATA(0x003F); LCD_WR_REG(0x002B); //00 00 01 DF LCD_WR_DATA(0x0000); LCD_WR_DATA(0x0000); LCD_WR_DATA(0x0001); LCD_WR_DATA(0x00df); delay_nms(50); LCD_WR_REG(0x0029); //开显示 LCD_WR_REG(0x002C); //开始写数据 LCD_Clear(WHITE); }这里面的参数都是卖家给我的例程上面的,其中C0后面的第一个参数在我这里能影响颜色显示
这里面,delay_nms()函数也是比较重要的
void delay_nms(u32 n) { while(n--)delay_1ms(); }
void delay_1ms(void) { TimingDelay=1000; while(TimingDelay!=0); }这里面关键的参数是TimingDelay,能够操作它的在stm32f4xx_it.c中的时钟中断处理函数
void SysTick_Handler(void) { TimingDelay_Decrement(); }然后,TimingDelay_Decrement函数是自己写的
void TimingDelay_Decrement(void) { if (TimingDelay != 0x00) { TimingDelay--; } }这样就解决了延时问题
然后涉及到LCD_WR_REG函数和LCD_WR_DATA函数
void LCD_WR_REG(u16 regval) { LCD_REG=regval;//写入要写的寄存器序号 }
void LCD_WR_DATA(u16 data) { LCD_RAM=data; }
void LCD_Clear(uint16_t Color) { uint32_t index = 0; LCD_SetCursor(0x00,0x0000); //设置光标位置 LCD_WR_REG(0x002C); for(index=0;index<153600;index++) LCD_WR_DATA(Color); }
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos) { #if HORIZONTAL LCD_WR_REG(0x002A);LCD_WR_DATA(Ypos>>8); LCD_WR_DATA(0x00FF&Ypos); //设定X坐标 LCD_WR_DATA(0x0001);LCD_WR_DATA(0x003F); LCD_WR_REG(0x002B);LCD_WR_DATA((480-Xpos)>>8); LCD_WR_DATA(0x00FF&(480-Xpos)); //设定Y坐标 LCD_WR_DATA(0x0001);LCD_WR_DATA(0x00df); #else LCD_WR_REG(0x002A);LCD_WR_DATA(Xpos>>8); LCD_WR_DATA(0x00FF&Xpos); //设定X坐标 LCD_WR_DATA(0x0001);LCD_WR_DATA(0x003F); LCD_WR_REG(0x002B);LCD_WR_DATA(Ypos>>8); LCD_WR_DATA(0x00FF&Ypos); //设定Y坐标 LCD_WR_DATA(0x0001);LCD_WR_DATA(0x00df); #endif }这样,就能够将整个屏幕绘制某个颜色了
剩下就是要配置FSMC功能了LCD_FSMC_Config();函数来完成
static void LCD_FSMC_Config(void) { FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef p; LCD_GPIO_Config(); //LCD管脚配置 RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); p.FSMC_AddressSetupTime = 5; //地址建立时间 p.FSMC_AddressHoldTime = 0; //地址保持时间 p.FSMC_DataSetupTime = 9; //数据建立时间 p.FSMC_BusTurnAroundDuration = 0; p.FSMC_CLKDivision = 0; p.FSMC_DataLatency = 0; p.FSMC_AccessMode = FSMC_AccessMode_A; // 用模式A控制LCD FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1; FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM; 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 = &p; FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &p; FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); }这里面,5-0-9,这三个时间还是很重要的。
另外就是LCD_GPIO_Config()函数了
static void LCD_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; //定义GPIO初始化结构体 /* 使能FSMC的AHB3时钟,这里注意,不同芯片总线会不同 */ RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC, ENABLE); /* 配置基于FSMC的液晶屏的数据线 * 液晶屏数据线:FSMC-D0~D15: PD 14 15 0 1,PE 7 8 9 10 11 12 13 14 15,PD 8 9 10 */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //设置翻转速度为100Mhz GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //设置管脚模式为复用模式 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_Init(GPIOD, &GPIO_InitStructure); //初始化GPIOB的Pin_0,Pin_,Pin_2, GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; GPIO_Init(GPIOE, &GPIO_InitStructure); /* 配置基于FSMC的液晶屏控制线 * PD4-FSMC_NOE :LCD-RD * PD5-FSMC_NWE :LCD-WR * PD7-FSMC_NE1 :LCD-CS * PE3-FSMC_A19 :LCD-DC */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOD, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ; GPIO_Init(GPIOE, &GPIO_InitStructure); GPIO_AF_FSMC_Config(); //在F407中必须加上这个复用连接配置,否则不能连接到FSMC }然后,就可以让LCD开始工作了~~
做个记录,可能有些地方没有写道~,有需要再添加。