学习STM32编程LCD显示实验
关键代码:
lcd.c//写寄存器函数 //regval:寄存器值 void LCD_WR_REG(vu16 regval) { regval=regval; //使用-O2优化的时候,必须插入的延时 LCD->LCD_REG=regval;//写入要写的寄存器序号 } //写LCD数据 //data:要写入的值 void LCD_WR_DATA(vu16 data) { data=data; //使用-O2优化的时候,必须插入的延时 LCD->LCD_RAM=data; } //读LCD数据 //返回值:读到的值 u16 LCD_RD_DATA(void) { vu16 ram; //防止被优化 ram=LCD->LCD_RAM; return ram; } //写寄存器 //LCD_Reg:寄存器地址 //LCD_RegValue:要写入的数据 void LCD_WriteReg(u16 LCD_Reg,u16 LCD_RegValue) { LCD->LCD_REG = LCD_Reg; //写入要写的寄存器序号 LCD->LCD_RAM = LCD_RegValue;//写入数据 } //读寄存器 //LCD_Reg:寄存器地址 //返回值:读到的数据 u16 LCD_ReadReg(u16 LCD_Reg) { LCD_WR_REG(LCD_Reg); //写入要读的寄存器序号 delay_us(5); return LCD_RD_DATA(); //返回读到的值 } //开始写GRAM void LCD_WriteRAM_Prepare(void) { LCD->LCD_REG=lcddev.wramcmd; } //LCD写GRAM //RGB_Code:颜色值 void LCD_WriteRAM(u16 RGB_Code) { LCD->LCD_RAM = RGB_Code;//写十六位GRAM } //读取个某点的颜色值 //x,y:坐标 //返回值:此点的颜色 u16 LCD_ReadPoint(u16 x,u16 y) { u16 r=0,g=0,b=0; if(x>=lcddev.width||y>=lcddev.height)return 0; //超过了范围,直接返回 LCD_SetCursor(x,y); if (lcddev.id == 0X5510) //5510 发送读GRAM指令 { LCD_WR_REG(0X2E00); } else //其他IC(9341/5310/1963/7789)发送读GRAM指令 { LCD_WR_REG(0X2E); } r=LCD_RD_DATA(); //dummy Read if (lcddev.id == 0X1963) //对1963来说,是真读 { return r; //1963直接读就可以 } r = LCD_RD_DATA(); //实际坐标颜色 //9341/5310/5510/7789 要分2次读出 b = LCD_RD_DATA(); g = r & 0XFF; //对于 9341/5310/5510/7789, 第一次读取的是RG的值,R在前,G在后,各占8位 g <<= 8; return (((r >> 11) << 11) | ((g >> 10) << 5) | (b >> 11)); // 9341/5310/5510/7789 需要公式转换一下 } //LCD开启显示 void LCD_DisplayOn(void) { if (lcddev.id == 0X5510) //5510开启显示指令 { LCD_WR_REG(0X2900); //开启显示 } else //9341/5310/1963/7789 等发送开启显示指令 { LCD_WR_REG(0X29); //开启显示 } } //LCD关闭显示 void LCD_DisplayOff(void) { if (lcddev.id == 0X5510) //5510关闭显示指令 { LCD_WR_REG(0X2800); //关闭显示 } else //9341/5310/1963/7789 等发送关闭显示指令 { LCD_WR_REG(0X28); //关闭显示 } } //设置光标位置 //Xpos:横坐标 //Ypos:纵坐标 void LCD_SetCursor(u16 Xpos, u16 Ypos) { //9341/5310/7789等设置坐标 { LCD_WR_REG(lcddev.setxcmd); LCD_WR_DATA(Xpos >> 8); LCD_WR_DATA(Xpos & 0XFF); LCD_WR_REG(lcddev.setycmd); LCD_WR_DATA(Ypos >> 8); LCD_WR_DATA(Ypos & 0XFF); } } //画点 //x,y:坐标 //POINT_COLOR:此点的颜色 void LCD_DrawPoint(u16 x,u16 y) { LCD_SetCursor(x,y); //设置光标位置 LCD_WriteRAM_Prepare(); //开始写入GRAM LCD->LCD_RAM=POINT_COLOR; } //SSD1963 背光设置 //pwm:背光等级,0~100.越大越亮. void LCD_SSD_BackLightSet(u8 pwm) { LCD_WR_REG(0xBE); //配置PWM输出 LCD_WR_DATA(0x05); //1设置PWM频率 LCD_WR_DATA(pwm*2.55);//2设置PWM占空比 LCD_WR_DATA(0x01); //3设置C LCD_WR_DATA(0xFF); //4设置D LCD_WR_DATA(0x00); //5设置E LCD_WR_DATA(0x00); //6设置F } //初始化lcd //该初始化函数可以初始化各种ILI93XX液晶,但是其他函数是基于ILI9320的!!! //在其他型号的驱动芯片上没有测试! void LCD_Init(void) { vu32 i=0; GPIO_InitTypeDef GPIO_InitStructure; FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure; FSMC_NORSRAMTimingInitTypeDef readWriteTiming; FSMC_NORSRAMTimingInitTypeDef writeTiming; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOD|RCC_AHB1Periph_GPIOE|RCC_AHB1Periph_GPIOF|RCC_AHB1Periph_GPIOG, ENABLE);//使能PD,PE,PF,PG时钟 RCC_AHB3PeriphClockCmd(RCC_AHB3Periph_FSMC,ENABLE);//使能FSMC时钟 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;//PB15 推挽输出,控制背光 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//普通输出模式 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化 //PB15 推挽输出,控制背光 GPIO_InitStructure.GPIO_Pin = (3<<0)|(3<<4)|(7<<8)|(3<<14);//PD0,1,4,5,8,9,10,14,15 AF OUT GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOD, &GPIO_InitStructure);//初始化 GPIO_InitStructure.GPIO_Pin = (0X1FF<<7);//PE7~15,AF OUT GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PF12,FSMC_A6 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//PF12,FSMC_A6 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用输出 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉 GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化 GPIO_PinAFConfig(GPIOD,GPIO_PinSource0,GPIO_AF_FSMC);//PD0,AF12 GPIO_PinAFConfig(GPIOD,GPIO_PinSource1,GPIO_AF_FSMC);//PD1,AF12 GPIO_PinAFConfig(GPIOD,GPIO_PinSource4,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD,GPIO_PinSource5,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD,GPIO_PinSource8,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD,GPIO_PinSource9,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD,GPIO_PinSource10,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD,GPIO_PinSource14,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOD,GPIO_PinSource15,GPIO_AF_FSMC);//PD15,AF12 GPIO_PinAFConfig(GPIOE,GPIO_PinSource7,GPIO_AF_FSMC);//PE7,AF12 GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_FSMC); GPIO_PinAFConfig(GPIOE,GPIO_PinSource15,GPIO_AF_FSMC);//PE15,AF12 GPIO_PinAFConfig(GPIOF,GPIO_PinSource12,GPIO_AF_FSMC);//PF12,AF12 GPIO_PinAFConfig(GPIOG,GPIO_PinSource12,GPIO_AF_FSMC); readWriteTiming.FSMC_AddressSetupTime = 0XF; //地址建立时间(ADDSET)为16个HCLK 1/168M=6ns*16=96ns readWriteTiming.FSMC_AddressHoldTime = 0x00; //地址保持时间(ADDHLD)模式A未用到 readWriteTiming.FSMC_DataSetupTime = 60; //数据保存时间为60个HCLK =6*60=360ns readWriteTiming.FSMC_BusTurnAroundDuration = 0x00; readWriteTiming.FSMC_CLKDivision = 0x00; readWriteTiming.FSMC_DataLatency = 0x00; readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A writeTiming.FSMC_AddressSetupTime =9; //地址建立时间(ADDSET)为9个HCLK =54ns writeTiming.FSMC_AddressHoldTime = 0x00; //地址保持时间(A writeTiming.FSMC_DataSetupTime = 8; //数据保存时间为6ns*9个HCLK=54ns writeTiming.FSMC_BusTurnAroundDuration = 0x00; writeTiming.FSMC_CLKDivision = 0x00; writeTiming.FSMC_DataLatency = 0x00; writeTiming.FSMC_AccessMode = FSMC_AccessMode_A; //模式A FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;// 这里我们使用NE4 ,也就对应BTCR[6],[7]。 FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable; // 不复用数据地址 FSMC_NORSRAMInitStructure.FSMC_MemoryType =FSMC_MemoryType_SRAM;// FSMC_MemoryType_SRAM; //SRAM FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;//存储器数据宽度为16bit FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;// FSMC_BurstAccessMode_Disable; FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable; 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_Enable; // 读写使用不同的时序 FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable; FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming; //读写时序 FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &writeTiming; //写时序 FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置 FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE); // 使能BANK1 delay_ms(50); // delay 50 ms //尝试9341 ID的读取 LCD_WR_REG(0XD3); lcddev.id=LCD_RD_DATA(); //dummy read lcddev.id=LCD_RD_DATA(); //读到0X00 lcddev.id=LCD_RD_DATA(); //读取93 lcddev.id<<=8; lcddev.id|=LCD_RD_DATA(); //读取41 if(lcddev.id==0X9341||lcddev.id == 0X7789 ||lcddev.id==0X5310||lcddev.id==0X5510||lcddev.id==0X1963)//如果是这几个IC,则设置WR时序为最快 { //重新配置写时序控制寄存器的时序 FSMC_Bank1E->BWTR[6]&=~(0XF<<0);//地址建立时间(ADDSET)清零 FSMC_Bank1E->BWTR[6]&=~(0XF<<8);//数据保存时间清零 FSMC_Bank1E->BWTR[6]|=3<<0; //地址建立时间(ADDSET)为3个HCLK =18ns if(lcddev.id == 0X7789) { FSMC_Bank1E->BWTR[6]|=3<<8; //数据保存时间(DATAST)为6ns*3个HCLK=18ns } else { FSMC_Bank1E->BWTR[6]|=2<<8; //数据保存时间(DATAST)为6ns*3个HCLK=18ns } } printf(" LCD ID:%xr ",lcddev.id); //打印LCD ID if(lcddev.id==0X9341) //9341初始化 { LCD_WR_REG(0xCF); LCD_WR_DATA(0x00); LCD_WR_DATA(0xC1); LCD_WR_DATA(0X30); LCD_WR_REG(0xED); LCD_WR_DATA(0x64); LCD_WR_DATA(0x03); LCD_WR_DATA(0X12); LCD_WR_DATA(0X81); LCD_WR_REG(0xE8); LCD_WR_DATA(0x85); LCD_WR_DATA(0x10); LCD_WR_DATA(0x7A); LCD_WR_REG(0xCB); LCD_WR_DATA(0x39); LCD_WR_DATA(0x2C); LCD_WR_DATA(0x00); LCD_WR_DATA(0x34); LCD_WR_DATA(0x02); LCD_WR_REG(0xF7); LCD_WR_DATA(0x20); LCD_WR_REG(0xEA); LCD_WR_DATA(0x00); LCD_WR_DATA(0x00); LCD_WR_REG(0xC0); //Power control LCD_WR_DATA(0x1B); //VRH[5:0] LCD_WR_REG(0xC1); //Power control LCD_WR_DATA(0x01); //SAP[2:0];BT[3:0] LCD_WR_REG(0xC5); //VCM control LCD_WR_DATA(0x30); //3F LCD_WR_DATA(0x30); //3C LCD_WR_REG(0xC7); //VCM control2 LCD_WR_DATA(0XB7); LCD_WR_REG(0x36); // Memory Access Control LCD_WR_DATA(0x48); LCD_WR_REG(0x3A); LCD_WR_DATA(0x55); LCD_WR_REG(0xB1); LCD_WR_DATA(0x00); LCD_WR_DATA(0x1A); LCD_WR_REG(0xB6); // Display Function Control LCD_WR_DATA(0x0A); LCD_WR_DATA(0xA2); LCD_WR_REG(0xF2); // 3Gamma Function Disable LCD_WR_DATA(0x00); LCD_WR_REG(0x26); //Gamma curve selected LCD_WR_DATA(0x01); LCD_WR_REG(0xE0); //Set Gamma LCD_WR_DATA(0x0F); LCD_WR_DATA(0x2A); LCD_WR_DATA(0x28); LCD_WR_DATA(0x08); LCD_WR_DATA(0x0E); LCD_WR_DATA(0x08); LCD_WR_DATA(0x54); LCD_WR_DATA(0XA9); LCD_WR_DATA(0x43); LCD_WR_DATA(0x0A); LCD_WR_DATA(0x0F); LCD_WR_DATA(0x00); LCD_WR_DATA(0x00); LCD_WR_DATA(0x00); LCD_WR_DATA(0x00); LCD_WR_REG(0XE1); //Set Gamma LCD_WR_DATA(0x00); LCD_WR_DATA(0x15); LCD_WR_DATA(0x17); LCD_WR_DATA(0x07); LCD_WR_DATA(0x11); LCD_WR_DATA(0x06); LCD_WR_DATA(0x2B); LCD_WR_DATA(0x56); LCD_WR_DATA(0x3C); LCD_WR_DATA(0x05); LCD_WR_DATA(0x10); LCD_WR_DATA(0x0F); LCD_WR_DATA(0x3F); LCD_WR_DATA(0x3F); LCD_WR_DATA(0x0F); LCD_WR_REG(0x2B); LCD_WR_DATA(0x00); LCD_WR_DATA(0x00); LCD_WR_DATA(0x01); LCD_WR_DATA(0x3f); LCD_WR_REG(0x2A); LCD_WR_DATA(0x00); LCD_WR_DATA(0x00); LCD_WR_DATA(0x00); LCD_WR_DATA(0xef); LCD_WR_REG(0x11); //Exit Sleep delay_ms(120); LCD_WR_REG(0x29); //display on } LCD_Display_Dir(0); //默认为竖屏 LCD_LED=1; //点亮背光 LCD_Clear(WHITE); } //清屏函数 //color:要清屏的填充色 void LCD_Clear(u16 color) { u32 index = 0; u32 totalpoint = lcddev.width; totalpoint *= lcddev.height; //得到总点数 LCD_SetCursor(0x00, 0x0000); //设置光标位置 LCD_WriteRAM_Prepare(); //开始写入GRAM for (index = 0; index < totalpoint; index++) { LCD->LCD_RAM=color; } }
main.cint main(void) { u8 x=0; u8 lcd_id[12]; //存放LCD ID字符串 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2 delay_init(168); //初始化延时函数 uart_init(115200); //初始化串口波特率为115200 LED_Init(); //初始化LED LCD_Init(); //初始化LCD FSMC接口 POINT_COLOR=RED; //画笔颜色:红色 sprintf((char*)lcd_id,"LCD ID:%04X",lcddev.id);//将LCD ID打印到lcd_id数组。 while(1) { switch(x) { case 0:LCD_Clear(WHITE);break; case 1:LCD_Clear(BLACK);break; case 2:LCD_Clear(BLUE);break; case 3:LCD_Clear(RED);break; case 4:LCD_Clear(MAGENTA);break; case 5:LCD_Clear(GREEN);break; case 6:LCD_Clear(CYAN);break; case 7:LCD_Clear(YELLOW);break; case 8:LCD_Clear(BRRED);break; case 9:LCD_Clear(GRAY);break; case 10:LCD_Clear(LGRAY);break; case 11:LCD_Clear(BROWN);break; } POINT_COLOR=RED; LCD_ShowString(30,40,210,24,24,"Explorer STM32F4"); LCD_ShowString(30,70,200,16,16,"TFTLCD TEST"); LCD_ShowString(30,90,200,16,16,"ATOM@ALIENTEK"); LCD_ShowString(30,110,200,16,16,lcd_id); //显示LCD ID LCD_ShowString(30,130,200,12,12,"2014/5/4"); x++; if(x==12)x=0; LED0=!LED0; delay_ms(1000); } }