在STM32F407上使用TouchGFX用于软件SPI的0.96寸OLED
一、TouchGFX必要的简单价绍
TouchGFX是一款针对STM32微控制器进行了优化的免费高级图形软件框架。只能用于STM32的芯片,TouchGFX会检测芯片。TouchGFX目前了解的用于STM32G0、STM32F4及以上的处理器。所以常用的STM32F103C8T6不能使用TouchGFX。 实际上STM32CubeMX也不会提供针对C8T6的TouchGFX的功能选项。TouchGFX是使用C++编写的图形框架。二、全过程使用的开发工具
核心板:STM32F407VET6;显示屏:SPI协议的0.96寸OLED;软件:STM32CubeMX;Keil5 ARM;TouchGFX Designer;
三、使用STM32CubeMX生成基础工程
1.新建工程选择STM32F407VET6。双击型号,转到工程页面。2.首先,选择左侧“System Core”下的“SYS”。选择“Debug”为“Serial Wire”。
3.选择左侧“System Core”下的“RCC”。选择“High Speed Clock(HSE)”为“Crystal/Ceramic Resonator”。
4.紧接着,选择蓝色菜单上面一行的“Clock Configuration”,转到时钟树页面。设置外部晶振(HSE左侧的Input frequency)为8MHz,设置HCLK为最大值168MHz。 之后会弹出窗口,选择确定,进行自动配置。
5.选回“Pinout & Configuration”。选择左侧“System Core”下的“GPIO”。点击右侧引脚并设置成GPIO_Output。对应下图命名。
6.选择左侧“Timers”下的任意定时器(这里选择TIM7)。设定如图数值,约为20ms。然后选择其下的“NVIC Setting”选项,开启定时器中断。
7.选择左侧“Middleware and Software Packs”,拖到最下面,选择“X-CUBE_TOUCHGFX”。首先会弹出下图一的界面,进行如下对应设置(如果是灰色的则需要安装)。
对下图右侧红色箭头按从上到下的解释。①启动图形应用,选择打勾。②显示设备选择客制化,即Custom。③0.96OLED屏幕只能二值显示,所以选择黑白。即“BW”。④宽度和高度按显示屏的实际选择。
8.初步的框架完成。然后选择蓝色菜单上面一行的“Project Manager”。在Project页面和Code Generator页面进行如下设置。
下图箭头解释:①生成工程保存的位置;②将要使用的编程工具。
下图箭头解释:①复制所有用到的库到工程文件夹;②外设初始化生成对应的“.c”和“.h”文件;③重新生成代码时,保留用户自定义的代码。
9.点击界面右上角的“GENERATE CODE”生成项目代码。
四、使用TouchGFX Designer设计简单的图像
1.找到上一步STM32CubeMX生成的工程文件夹。具体位置在上一大步的第8小步中有设置过。找到,如:F407_096_SPI_SOFT_TouchGFX(工程文件夹)/TouchGFX/ApplicationTemplate.touchgfx.part。 双击ApplicationTemplate.touchgfx.part文件,就会自动打开TouchGFX Designer软件。正式进入页面设计步骤。第一次打开可能会先置顶展示一个窗口,这个窗口可以直接关闭。打开TouchGFX Designer后,有如下图二界面。2.如下图所示,选择Shapes中的Box,作为背景。颜色选择为黑色。
3.同理,参考第二小步的图一。选择Shapes中的Shape,产生一个白色菱形,摆放进去使之成为一个特殊图形。如下图所示。
4.这样,一个简单的例子界面就完成了。然后,按界面右下角的,形如“° </>”的代码生成按钮。这样界面就制作完成且生成进之前创建的工程了。
五、使用Keil5 ARM修改相关函数
需要特别注意:在C++的文件(*.cpp)和C语言的文件(*.c)之间相互调用,需要特别的编译标记。这里主要修改Keil5的右侧工程目录的Application/User/TouchGFX/target下的TouchGFXHAL.cpp文件。
修改TouchGFXHAL.cpp的void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect)函数。这个函数传递了要显示的内容,在这里把内容显示在屏幕上。
以下的OLED_DrawBMP();函数是定义在oled.c文件的。要在cpp的文件中调用,需要对声明这些函数的“*.h”文件添加如代码段2的内容。
//代码段1 //注意,以下代码有问题。会把图形压窄,然后在屏幕上重复显示8遍。有驱动程序错误待修改。 //在C++中包含用C语言编写的头文件,用以下格式。 extern "C"{ #include “oled.h” } void TouchGFXHAL::flushFrameBuffer(const touchgfx::Rect& rect) { const unsigned char *bitmap = (const unsigned char*) getClientFrameBuffer(); OLED_DrawBMP(0,0,127,7,(unsigned char*)bitmap); }
//代码段2 #ifndef __OLED_H #define __OLED_H #include "main.h" /****************需要添加的内容以及对应位置****************/ //包含的声明的C语言函数会在TouchGFXHAL.cpp文件内调用。 #ifdef _cplusplus extern C { #endif /*******************************************************/ //一些必要的宏定义 //OLED控制用函数 void OLED_WR_Byte(uint8_t dat,uint8_t cmd); void OLED_Set_Pos(unsigned char x, unsigned char y); ... void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]); /****************需要添加的内容以及对应位置****************/ #ifdef _cplusplus_ } #endif /*******************************************************/ #endif然后,之前设置的定时器是用于TouchGFX刷新屏幕计时的。在添加的定时器中断回调函数void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)中需要调用自己编写的void touchgfxTickHandler()函数。
//在TouchGFXHAL.cpp的最后添加。下面的函数会在C语言的文件中调用。 //定时器回调函数会调用它。 //包含以下头文件,OSWrappers字段才能使用。 #include “touchgfx/hal/OSWrappers.hpp” //以下在TouchGFXHAL.cpp文件中定义的函数,C文件stm32f4xx_it.c会调用。 //所以加头extern "C" extern "C" void touchgfxTickHandler() { touchgfx::HAL::getInstance()->vSync(); touchgfx::OSWrappers::signalVSync(); }定时器中断回调函数个人习惯放在stm32f4xx_it.c的文件中。代码内容如下。
extern void touchgfxTickHandler(); void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance==TIM7) { touchgfxTickHandler(); } }最后,在“main.c”文件中开启定时器中断。
HAL_TIM_Base_Start_IT(&htim7);之后Keil5就可以编译了。
另注:在使用硬件SPI且打开硬件片选信号下,OLED_WR_Byte()函数需要改写成如下形式。
void OLED_WR_Byte(uint8_t dat,uint8_t cmd) { if(cmd) OLED_DC_Set(); else OLED_DC_Clr(); HAL_SPI_Transmit(&hspi1,&dat,1,0x00ff); OLED_DC_Set(); }
六、目前代码的实物现象
问题:同一个图像重复显示了8次。需要求改TouchGFXHAL::flushFrameBuffer函数。完善后,持续更新... ...