一、准备工作
1、STM32CubeMx 我使用的是4.25版本的,软件还没装上的自己去下载安装就可以了
2、下载F103最新的固件库,新建工程的时候,会自动提示让你下载的,不用另行下载
下载保存的地方可以在软件的project -> setting 页面的最底下看到
3、TFT屏幕,了解清楚平模的驱动IC型号(后面会用到),同时准备好此屏幕的驱动。注意这里只说明支持FSMC驱动的LCD屏幕(数据输出最少16个),为避免其它错误操作,应先确保驱动文件和屏幕都是好的,比如先跑个例程之类的。
4、编译环境Keil uVision5
二、添加文件
1、新建工程,我这里是F103VET6的芯片
2、配置FSMC,这里只有NE1可以选,那就选NE1了,不同的选择,会导致不同的代码,后面再说,这里先选上NE1
,寄存器的选择就选A16,也可以选其它,同样,不同的选择,会导致不同的代码,后面再说。注意数据选16位(这里只讲16位,8位的其实一样)。
注意一定要选上CRC校验,这里是ST的一个保护机制,没什么卵用,强制要求的,选上就是了。
屏幕一般都是由22个引脚来控制的,其中16个引脚是数据,6个是控制,对应关系:
FSMC_NOE LCD_RD 读
FSMC_NWE LCD_WR 写
FSMC_NEx LCD_CS 片选
FSMC_Ax LCD_RS 寄存器选择,注意不是复位
FSMC_D00~D15 对应 LCD_D0~D15 数据引脚
到这里,已经配置了LCD屏幕的20个引脚了,(16个数据引脚,4个控制引脚),还需要在配置LCD的RST和BK引脚,也就是复位和背光灯引脚,没有的话可以不配置,我这里有,配置为输出即可(默认推挽输出)
至此,引脚配置完。把时钟配置一下,就可以生成了。
3、把STemwin复制到工程文件
把整个STemwin复制到工程文件里面,要把SemWin文件夹改个名称,否则的话,在重新生成代码的时候,改文件夹可能会被删除
再工程新建一个分组STemwin,把这几个文件添加到工程:
把LCD驱动文件也放到工程里面,注意驱动文件的名称不能为lcd.c、lcd.h,因为emwin里有一个文件也叫lcd.c,改一下名称就好,我这里改为:
其中,ili9341是我屏幕的驱动IC,再次提醒,记住这个IC芯片的型号,把相应的头文件也加进去(个人习惯把头文件和源文件分开两个文件夹存放)
添加到工程里面,把相应的头文件路径加进去:
然后编译一下:
一堆错误(错误数量跟LCD的驱动文件有关),前面的都是一些体力活,真正要改代码的工作终于开始了。
三、修改代码
1、GUI_X.c
这里只需要修改一个代码,源码里面由这么一个变量:volatile GUI_TIMER_TIME OS_TimeMS;
这是整个emwin的心跳,必须要让它跳起来(我是直接把它放到了系统时钟里面,由兴趣的朋友可以放在定时器里面,注意是1ms的心跳):
这里系统会报错,提示GUI_TIMER_TIME这个数据类型未定义,很简单,在文件里加上 #include “GUI.h”就可以了
2、GUIConf.c
只需要把这个数据改小一点就可以了,我这里改成10*1024,也就是10K字节,具体看芯片的内存空间大小,大点小点都无所谓。
3、LCDConf_FlexColor_Template.c
先把LCD驱动头文件加进来:#include "bsp_ili9341_lcd.h"
屏幕分辨率,按实际屏幕分辨率大小修改就可以了
然后要修改这4个函数:
static void LcdWriteReg(U16 Data) ;
static void LcdWriteData(U16 Data);
static void LcdWriteDataMultiple(U16 * pData, int NumItems);
static void LcdReadDataMultiple(U16 * pData, int NumItems);
这时候需要回去看我们LCD的驱动代码了,先看头文件bsp_ili9341_lcd.h,找到类似下面定义的东西:
#define macFSMC_Addr_ILI9341_CMD ( ( uint32_t ) 0x60000000 ) //FSMC_Bank1_NORSRAM1用于LCD命令操作的地址
#define macFSMC_Addr_ILI9341_DATA ( ( uint32_t ) 0x60020000 ) //FSMC_Bank1_NORSRAM1用于LCD数据操作的地址
为何是0x60000000?这又牵连到了一开始我们配置的FSCM了,具体可以查看FSMC的相关时序,我们的LCD驱动协议,实际上跟FSMC是一毛一样的。这里只介绍怎么决定这个值就好:
NE1 0x600000000
NE2 0x640000000
NE3 0x680000000
NE4 0x6C0000000
然后0x60020000的决定方式:
0x600000000 | ( 0x1<<( 16 + 1 ) ) = 0x60020000;
其中的16就是A16,如果是A17,那就是17+1,结果为0x60040000
现在只要记住,写LCD命令是小的数值,写LCD数据是大的数值就好了。
然后定义两个宏定义:
#define LCD_WRITE_REG ( *(__IO uint16_t *) (macFSMC_Addr_ILI9341_CMD) )
#define LCD_WRITE_DATA ( *(__IO uint16_t *) (macFSMC_Addr_ILI9341_DATA) )
然后,写上代码:
static void LcdWriteReg(U16 Data) {
// ... TBD by user
LCD_WRITE_REG = Data;
}
static void LcdWriteData(U16 Data) {
// ... TBD by user
LCD_WRITE_DATA = Data;
}
static void LcdWriteDataMultiple(U16 * pData, int NumItems) {
while (NumItems--) {
// ... TBD by user
LCD_WRITE_DATA = *pData++;
}
}
static void LcdReadDataMultiple(U16 * pData, int NumItems) {
while (NumItems--) {
// ... TBD by user
*pData++ = LCD_WRITE_DATA;
}
}
在LCD_X_Config函数里面,加入一行代码
Config.NumDummyReads = 2;
表示第二个数据才是真实数据(不理解的话就先记住,以后慢慢会清楚)
第二个红框的就是由驱动芯片决定的,打开这个文档:
在1127页左右,找到你对应的芯片驱动IC,然后决定红框中的值取什么:
我这里是ili9341,所以要改成GUIDRV_FLEXCOLOR_F66709
GUIDRV_FLEXCOLOR_M16C0B16的意思页可以在文档中找到:
然后,把驱动文件的初始化函数放在这里:
剩下的,就是把LCD的驱动代码修改为HAL库的了,没什么难度,自行修改吧,注意要细心点。
至此,移植代码做完了,写个测试代码
四、测试代码
先加入头文件 #include "GUI.h"和lcd驱动#include "bsp_ili9341_lcd.h"
写入代码: