看原理图就可以知道,这是想用FSMC来驱动液晶。在STM32F107中是没有FSMC的,而GD32F107中带有FSMC,所以在使用固件库的时候需要修改一处地方:
将RCC_AHBPeriph_FSMC移到#ifndef STM32F10X_CL上面。这也表明GD32的片内资源比STM32的同等型号丰富。那么接着就按照FSMC的方式来驱动液晶。
1、首先来确定地址:
更具原理图可以看出RS引脚是接在 EXMC_A23 , CS引脚是接在EXMC_NE1
将LCD当做SRAM操作,在存储块1 HADDR[27.26] = 00 地址范围:0x6000,0000~0x63ff,ffff
根据上图红线所标记的地方,来确定LCD的读写地址。
typedef struct { u16 Lcd_Command; u16 Lcd_Data; }LcdTypedef; #define LCD_ADDR_BASE ((u32)(0X60000000 | 0X00FFFFFE)) #define MY_LCD ((LcdTypedef *)LCD_ADDR_BASE)
RS引脚是接在A23处,所以对于HADDR的第24位,按照上面代码的定义方式,就可以这样操作LCD:
void LcdWriteCommand(u16 cmd) { MY_LCD->Lcd_Command = cmd; } void LcdWriteData(u16 dat) { MY_LCD->Lcd_Data = dat; } u16 LcdReadData() { return MY_LCD->Lcd_Data; }
在底层函数完成后,开始来操作TFT液晶。先读取液晶的ID,看其控制芯片是什么型号,在线调试读出的ID值为0X8989。附上一份资料SSD1289(ID8989).zip
完成读写寄存器的函数:
void LcdWriteRegist(u16 addr,u16 dat) { MY_LCD->Lcd_Command = addr; MY_LCD->Lcd_Data = dat; } u16 LcdReadRegist(u16 addr) { MY_LCD->Lcd_Command = addr; return MY_LCD->Lcd_Data; }
那么初始化TFT液晶:
1、初始化IO口
2、初始化FSMC
3、初始化TFT液晶
void LcdInit() { GPIO_InitTypeDef GPIO_InitStruct; FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStruct; FSMC_NORSRAMTimingInitTypeDef FSMC_WriteTimingStruct; FSMC_NORSRAMTimingInitTypeDef FSMC_ReadTimingStruct; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE ); RCC_APB2PeriphClockCmd (RCC_LCD_GPIO,ENABLE); GPIO_InitStruct.GPIO_Pin = LCD_RS_Pin; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz ; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP ; GPIO_Init (LCD_RS_GPIO,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = LCD_WR_Pin; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz ; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP ; GPIO_Init (LCD_WR_GPIO,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = LCD_RD_Pin; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz ; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP ; GPIO_Init (LCD_RD_GPIO,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = LCD_CS_Pin; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz ; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP ; GPIO_Init (LCD_CS_GPIO,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = LCD_DAT_Pin_Part1; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz ; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP ; GPIO_Init (LCD_DAT_GPIO_Part1,&GPIO_InitStruct); GPIO_InitStruct.GPIO_Pin = LCD_DAT_Pin_Part2; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz ; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP ; GPIO_Init (LCD_DAT_GPIO_Part2,&GPIO_InitStruct); /**************************************************************************************/ FSMC_ReadTimingStruct.FSMC_AddressSetupTime = 0X01; FSMC_ReadTimingStruct.FSMC_AddressHoldTime = 0X00; FSMC_ReadTimingStruct.FSMC_DataSetupTime = 0X0F; FSMC_ReadTimingStruct.FSMC_BusTurnAroundDuration = 0X00; FSMC_ReadTimingStruct.FSMC_CLKDivision = 0X00; FSMC_ReadTimingStruct.FSMC_DataLatency = 0X00; FSMC_ReadTimingStruct.FSMC_AccessMode = FSMC_AccessMode_A ; FSMC_WriteTimingStruct.FSMC_AddressSetupTime = 0X00; FSMC_WriteTimingStruct.FSMC_AddressHoldTime = 0X00; FSMC_WriteTimingStruct.FSMC_DataSetupTime = 0X03; FSMC_WriteTimingStruct.FSMC_BusTurnAroundDuration = 0X00; FSMC_WriteTimingStruct.FSMC_CLKDivision = 0X00; FSMC_WriteTimingStruct.FSMC_DataLatency = 0X00; FSMC_WriteTimingStruct.FSMC_AccessMode = FSMC_AccessMode_A ; FSMC_NORSRAMInitStruct.FSMC_Bank = LCD_FSMC_Bank ; FSMC_NORSRAMInitStruct.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable ; FSMC_NORSRAMInitStruct.FSMC_MemoryType = FSMC_MemoryType_SRAM ; FSMC_NORSRAMInitStruct.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b; FSMC_NORSRAMInitStruct.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable ; FSMC_NORSRAMInitStruct.FSMC_AsynchronousWait = FSMC_AsynchronousWait_Disable ; FSMC_NORSRAMInitStruct.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low; FSMC_NORSRAMInitStruct.FSMC_WrapMode = FSMC_WrapMode_Disable ; FSMC_NORSRAMInitStruct.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState ; FSMC_NORSRAMInitStruct.FSMC_WriteOperation = FSMC_WriteOperation_Enable ; FSMC_NORSRAMInitStruct.FSMC_WaitSignal = FSMC_WaitSignal_Disable ; FSMC_NORSRAMInitStruct.FSMC_ExtendedMode = FSMC_ExtendedMode_Enable; FSMC_NORSRAMInitStruct.FSMC_WriteBurst = FSMC_WriteBurst_Disable ; FSMC_NORSRAMInitStruct.FSMC_ReadWriteTimingStruct = &FSMC_ReadTimingStruct; FSMC_NORSRAMInitStruct.FSMC_WriteTimingStruct = &FSMC_WriteTimingStruct; FSMC_NORSRAMInit (&FSMC_NORSRAMInitStruct); FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1,ENABLE ); DelayMs(50); LcdWriteRegist(0x0000,0x0001); DelayMs(50); Lcd_InfoStruct.id = LcdReadRegist(0x0000); if(Lcd_InfoStruct.id < 0XFF || Lcd_InfoStruct.id == 0XFFFF || Lcd_InfoStruct.id == 0X9300) { LcdWriteCommand(0XD3); LcdReadData(); //dummy read LcdReadData(); Lcd_InfoStruct.id=LcdReadData(); Lcd_InfoStruct.id <<= 8; Lcd_InfoStruct.id |= LcdReadData(); } if(Lcd_InfoStruct.id == MYLCD_ID) { Lcd_InfoStruct.b_color = RED; Lcd_InfoStruct.f_color = WHITE; Lcd_InfoStruct.gram_cmd = R34; Lcd_InfoStruct.height = 320; Lcd_InfoStruct.mode = V_Screen; Lcd_InfoStruct.width = 240; Lcd_InfoStruct.xcmd = 0X4E; Lcd_InfoStruct.ycmd = 0X4F; LcdWriteRegist(0x0000,0x0001); LcdWriteRegist(0x0003,0xA8A4); LcdWriteRegist(0x000C,0x0000); LcdWriteRegist(0x000D,0x080C); LcdWriteRegist(0x000E,0x2B00); LcdWriteRegist(0x001E,0x00B0); LcdWriteRegist(0x0001,0x2B3F); LcdWriteRegist(0x0002,0x0600); LcdWriteRegist(0x0010,0x0000); LcdWriteRegist(0x0011,0x6078); LcdWriteRegist(0x0005,0x0000); LcdWriteRegist(0x0006,0x0000); LcdWriteRegist(0x0016,0xEF1C); LcdWriteRegist(0x0017,0x0003); LcdWriteRegist(0x0007,0x0233); LcdWriteRegist(0x000B,0x0000); LcdWriteRegist(0x000F,0x0000); LcdWriteRegist(0x0041,0x0000); LcdWriteRegist(0x0042,0x0000); LcdWriteRegist(0x0048,0x0000); LcdWriteRegist(0x0049,0x013F); LcdWriteRegist(0x004A,0x0000); LcdWriteRegist(0x004B,0x0000); LcdWriteRegist(0x0044,0xEF00); LcdWriteRegist(0x0045,0x0000); LcdWriteRegist(0x0046,0x013F); LcdWriteRegist(0x0030,0x0707); LcdWriteRegist(0x0031,0x0204); LcdWriteRegist(0x0032,0x0204); LcdWriteRegist(0x0033,0x0502); LcdWriteRegist(0x0034,0x0507); LcdWriteRegist(0x0035,0x0204); LcdWriteRegist(0x0036,0x0204); LcdWriteRegist(0x0037,0x0502); LcdWriteRegist(0x003A,0x0302); LcdWriteRegist(0x003B,0x0302); LcdWriteRegist(0x0023,0x0000); LcdWriteRegist(0x0024,0x0000); LcdWriteRegist(0x0025,0x8000); LcdWriteRegist(0x004f,0); LcdWriteRegist(0x004e,0); } }
此液晶型号的资料以及寄存器的介绍都在上面的附件中,当初始化完成后,剩下的操作就是设置坐标,写入颜色。下面是清屏的函数:
void LcdSetPart(u16 xS,u16 yS,u16 xE,u16 yE) { LcdWriteRegist(0x0044,((xE << 8) | xS)); LcdWriteRegist(0x0045,yS); LcdWriteRegist(0x0046,yE); } void LcdClearScreen(u16 Color) { u32 i = 0; LcdSetPart(0,0,Lcd_InfoStruct.width - 1,Lcd_InfoStruct.height - 1); LcdWriteCommand(Lcd_InfoStruct.gram_cmd); for(i = 0;i < 76800;i++) { LcdWriteData(Color); } }
主函数:
int main() { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); LedPinInit(); SysTickInit(); LcdInit(); LcdClearScreen(Lcd_InfoStruct.b_color); LcdDispString(0,0,(u8 *)"hello world",0,Lcd_InfoStruct.b_color,Lcd_InfoStruct.f_color); LcdDispString(0,20,(u8 *)"www.eepw.com.cn",0,Lcd_InfoStruct.b_color,Lcd_InfoStruct.f_color); LcdDispString(0,40,(u8 *)"liklon -->GD32107V-EVAL",0,Lcd_InfoStruct.b_color,Lcd_InfoStruct.f_color); while(1) { ; } }
函数比较多,不一一贴出,,将在导航帖附上代码。
效果图:
通过查看效果,刷屏速度也是相当不错,也可以看出GD32对比STM32同等型号的片子,其资源相对更加丰富,操作起来更方便。那GD32F107与STM32F107想比较,GD32在资源方面就占了优势。