简介
基于STM32F746使用FreeRTOS移植TouchGFX,学习图形界面开发,通过STM32CubeMX直接配置FreeRTOS和TouchGFX,利用TouchGFX Designer设计界面。
开发平台
硬件平台:STM32F746 Discovery Kit
开发环境:MDK V5.28
工程配置:STM32CubeMX V5.6
界面设计:TouchGFX 4.13
创建工程
芯片选择
打开STM32CubeMX,通过芯片型号选择STM32F746NGHx,开始工程。
System Core配置
-
选择
RCC
配置晶振:HSE选择BYPASS Clock Source
,LSE选择Crystal/Ceramic Resonator
,点击NVIC Settings
勾选RCC global interrupt
-
选择
SYS
配置系统时间:Debug选择Serial Wire
,开启仿真,SWD接口;Timebase Source选择TIM6
用于给系统提供时间基准
Connectivity配置
-
选择
FMC
并展开SDRAM 1
栏,Clock and chip enable选择SDCKE0 + SDNE0
,Internal bank number选择4 banks
,Address选择12 bits
,Data选择16 bits
,Byte enable选择16-bit byte enable
-
点击
SDRAM 1
项配置SDRAM的相关参数,点击NVIC Settings
勾选FMC global interrupt
,点击GPIO Setttings
确定接口与实际电路一致
Multimedia配置
-
选择
DMA2D
勾选Mode栏下的Actived
,点击Parameter Settings
选择适合自己的Color Mode,点击NVIC Settings
勾选DMA2D global interrupt
-
选择
LTDC
并下拉Display Type选择与硬件对应的屏幕类型,此处选择RGB888(24 bits)
,点击Parameter Settings
设置对应参数
设置Layer Settings
对应参数
点击NVIC Settings
勾选LTDC global interrupt
,点击GPIO Settings
确定接口是否与实际电路一致
Computing配置
选择CRC
勾选Actived
,参数保持默认即可
Middleware配置
-
选择
FreeRTOS
在Mode栏下选择CMSIS_V1
,点击Tasks and Queues
配置一个任务,该任务用于TouchGFX -
点击
Config parameters
对FreeRTOS进行配置,主要配置Kernel和Memory
Additional Software配置
-
点击顶栏
Clock Configuration
下方的Additional Software
准备开启TouchGFX,要提前下载好TouchGFX包 -
在弹出界面的Packs框内逐步展开并选择TouchGFX,此界面拉小后可以看到右下角的
OK
键 -
第2步确定后选择左侧栏新增加的
Additional Software
并点击TouchGFX.4.13.0勾选Graphics Application
,配置TouchGFX的参数
额外引脚配置
LCD需要增加三个GPIO,PI12控制显示使能,低电平进入Sleep模式,高电平进入正常模式;PK3控制背光,低电平关闭背光,高电平打开背光;PI1控制LD1。GPIO output level选择High
,GPIO mode选择Output Push Pull
,默认拉高。
时钟配置
点击界面上方Clock Configuration
配置系统时钟
代码生成
点击界面上方Project Manager
设置工程名称和路径,以及IDE的类型,点击右上角GENERATE CODE
生成工程代码
设计界面
打开工程根目录下的/Src/ApplicationTemplate.touchgfx.part
文件开始制作界面,编辑完成后点击右上角的Generate Code
按钮生成代码,此时.part
文件同目录下会生成.touchgfx
文件,以后可以直接打开该文件进行界面设计
代码设计
- 手动添加SDRAM的初始化代码,并放到FMC初始化之后运行。先定义相关参数
/* USER CODE BEGIN PD */
#define SDRAM_MODEREG_BURST_LENGTH_1 ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2 ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4 ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8 ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2 ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3 ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE ((uint16_t)0x0200)
/* USER CODE END PD */
SDRAM初始化代码
static void MX_SDRAM_Init(void)
{
__IO uint32_t tmpmrd = 0;
FMC_SDRAM_CommandTypeDef Command;
/* Step 1: Config clock */
Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
/* Step 2: Insert Delay */
HAL_Delay(1);
/* Step 3: Config pall */
Command.CommandMode = FMC_SDRAM_CMD_PALL;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
/* Step 3: Config auto refresh */
Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 8;
Command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
/* Step 4: Config memory mode */
tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1 | //设置突发长度:1(可以是1/2/4/8)
SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL | //设置突发类型:连续(可以是连续/交错)
SDRAM_MODEREG_CAS_LATENCY_3 | //设置CAS值:3(可以是2/3)
SDRAM_MODEREG_OPERATING_MODE_STANDARD | //设置操作模式:0,标准模式
SDRAM_MODEREG_WRITEBURST_MODE_SINGLE; //设置突发写模式:1,单点访问
Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
Command.AutoRefreshNumber = 1;
Command.ModeRegisterDefinition = tmpmrd;
HAL_SDRAM_SendCommand(&hsdram1, &Command, 0xFFFF);
/* Step 5: Set refresh rate */
HAL_SDRAM_ProgramRefreshRate(&hsdram1, 1800);
}
- 在defaulttask内启动TouchGFX
void StartDefaultTask(void const * argument)
{
/* USER CODE BEGIN 5 */
MX_TouchGFX_Process();
/* Infinite loop */
for(;;)
{
osDelay(1);
}
/* USER CODE END 5 */
}
- 额外创建一个任务用于LD1闪烁。声明任务句柄;定义任务块然后启动任务;实现任务入口函数。
/* USER CODE BEGIN PV */
osThreadId userTaskHandle;
/* USER CODE END PV */
void StartUserTask(void const *argument);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
osThreadDef(userTask, StartUserTask, osPriorityNormal, 0, 128);
userTaskHandle = osThreadCreate(osThread(userTask), NULL);
/* USER CODE END RTOS_THREADS */
void StartUserTask(void const *argument)
{
for(;;)
{
HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET);
osDelay(500);
HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_RESET);
osDelay(500);
}
}
下载验证
注意
工程中配置的代码要卸载BEGIN END
两行之间,避免重新生成代码后被清除。
来源:oschina
链接:https://my.oschina.net/u/4418610/blog/4302846