STEmwin教程零:STM32 STEmwin移植(裸机&FreeRTOS系统)

目录

一、资料准备

二、目录简介

三、裸机移植

3.1 添加文件

 3.2 修改文件

四、含FreeRTOS移植

五、测试

5.1 裸机测试

5.2 含系统测试


一、资料准备

裸机时空工程:stm32H743+0.96寸OLED 屏幕

FreeRTOS空工程:stm32H743+0.96寸OLED 屏幕+FreeRTOS

STEmwin:STemWin_Library_V1.2.0:https://www.st.com/en/embedded-software/stemwin.htmlhttps://www.st.com/en/embedded-software/stemwin.html

二、目录简介

STemWin_Library_V1.2.0\Libraries\STemWinLibrary532

  1. Config文件夹:LCD接口以及emwin配置文件,移植时使用
  2. Documentation:STEmwin的函数说明文件
  3. inc:STEmwin函数的头文件,移植时使用
  4. Lib:STEmwin的函数库,移植时使用我们是H7,内核是CM7,开发环境为Keil。所以裸机程序选用STemWin532_CM7_Keil.lib,OS是选用STemWin532_CM7_OS_Keil.lib
  5. OS:裸机情况下的驱动文件:选用GUI_X.c,使用OS是使用GUI_X_OS.c
  6. Simulation:仿真用到的文件
  7. Software:STEmwin开发使用到的软件

三、裸机移植

3.1 添加文件

将STemWinLibrary532文件复制到工程文件夹中,并重名为STEmwin文件夹,

向工程里添加文件: 

 添加头文件路径后进行编译,发现提示没有LCDConf.h,我们自己新建一个该文件放到STEmwin下的Config文件夹中。再编译就没有报错了。

CUI_X.c:GUI所依赖的外部配置;

CUIConf.c:GUI初始化配置;

CUIConf.h:GUI配置设置;

CUIDRV_Template.c:GUI读点、画点、画线等函数配置,需要我们根据自己的LCD驱动函数进行修改;

LCDConf_FlexColor_Template.c:LCD的初始化配置

STemWin532_CM7_Keil.lib:裸机对应的STEmwin函数库文件

 3.2 修改文件

GUIConf.h:

设置是否使用操作系统、是否支持触摸、默认字体、显示的最大层数等参数。由于是裸机,设置OS_SUPPORT为0,而0.96寸的OLED 屏幕不支持触摸,则设置GUI_SUPPORT_TOUCH为0, 设置默认字体 GUI_DEFAULT_FONT为 &GUI_Font6x8;其他参数如下。


#ifndef GUICONF_H
#define GUICONF_H

#define GUI_NUM_LAYERS            2    // Maximum number of available layers
#define OS_SUPPORT                0
#define GUI_SUPPORT_TOUCH       	0

#ifdef OS_SUPPORT
 #define GUI_OS                    (1)  // Compile with multitasking support
#else
 #define GUI_OS                    (0)
#endif

#ifndef   GUI_SUPPORT_TOUCH
  #define GUI_SUPPORT_TOUCH       (1)  // Support touchscreen
#endif


#define GUI_DEFAULT_FONT          &GUI_Font6x8


#define GUI_SUPPORT_MOUSE             (0)    /* Support a mouse */
#define GUI_WINSUPPORT                (1)    /* Use window manager */
#define GUI_SUPPORT_MEMDEV            (1)    /* Memory device package available */
#define GUI_SUPPORT_DEVICES           (1)    /* Enable use of device pointers */

#endif  /* Avoid multiple inclusion */

GUIConf.c:定义了STEmwin所使用的的内存,并使用申请此内存。

#include "GUI.h"

#define GUI_NUMBYTES  30*1024
#define GUI_BLOCKSIZE 0x80

void GUI_X_Config(void) {
  
    static U32 aMemory[GUI_NUMBYTES / 4];
  
    GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);
    GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);
  
    GUI_SetDefaultFont(GUI_FONT_6X8);
}

GUIDRV_Template.c中需要修改两个函数_SetPixelIndex、_GetPixelIndex。

_SetPixelIndex为画点函数,其中需要我们自己修改,添加OLED 屏幕驱动的画点函数,

static void _SetPixelIndex(GUI_DEVICE * pDevice, int x, int y, int PixelIndex) {
    #if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
      int xPhys, yPhys;

      xPhys = LOG2PHYS_X(x, y);
      yPhys = LOG2PHYS_Y(x, y);
    #else
      #define xPhys x
      #define yPhys y
    #endif
    GUI_USE_PARA(pDevice);
    GUI_USE_PARA(x);
    GUI_USE_PARA(y);
    GUI_USE_PARA(PixelIndex);
    {
			OLED_DrawPoint(xPhys,yPhys,PixelIndex);//0.96寸OLED 屏幕画点函数
    }
    #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
      #undef xPhys
      #undef yPhys
    #endif
}

_GetPixelIndex为读点函数,其中也需要我们自己修改,添加OLED 屏幕驱动的读点函数,

static unsigned int _GetPixelIndex(GUI_DEVICE * pDevice, int x, int y) {
  unsigned int PixelIndex;
    #if (LCD_MIRROR_X == 1) || (LCD_MIRROR_Y == 1) || (LCD_SWAP_XY == 1)
      int xPhys, yPhys;

      xPhys = LOG2PHYS_X(x, y);
      yPhys = LOG2PHYS_Y(x, y);
    #else
      #define xPhys x
      #define yPhys y
    #endif
    GUI_USE_PARA(pDevice);
    GUI_USE_PARA(x);
    GUI_USE_PARA(y);
    {
        //PixelIndex = 0;
        PixelIndex = OLED_GetPixel(xPhys,yPhys);//0.96寸OLED 屏幕读点函数
    }
    #if (LCD_MIRROR_X == 0) && (LCD_MIRROR_Y == 0) && (LCD_SWAP_XY == 0)
      #undef xPhys
      #undef yPhys
    #endif
  return PixelIndex;
}

编译通过

四、含FreeRTOS移植

基本与裸机移植一致,不一样的是

  1. 裸机程序选用STemWin532_CM7_Keil.lib,现在OS是选用STemWin532_CM7_OS_Keil.lib
  2. 裸机选用GUI_X.c,现在OS是选用GUI_X_OS.c

最重要的现在使用的FreeRTOS,所以GUI_X_OS.c具体选用GUI_X_FreeRTOS.c文件。

/*File        : GUI_X_FreeRTOS.C*/
#include "GUI.h"

/* FreeRTOS头文件 */
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

static xSemaphoreHandle xQueueMutex = NULL;
static xSemaphoreHandle xSemaTxDone = NULL;

int GUI_X_GetTime(void)
{
	return ((int) xTaskGetTickCount());
}

void GUI_X_Delay(int ms)
{
  vTaskDelay( ms );
}


void GUI_X_Init(void) {
}

void GUI_X_ExecIdle(void) {
}


void GUI_X_InitOS(void)
{ 
  /* 创建互斥信号量 用于资源共享 */
  xQueueMutex = xSemaphoreCreateMutex();
  configASSERT (xQueueMutex != NULL);
	/* 创建二值信号量 用于事件触发 */
  vSemaphoreCreateBinary( xSemaTxDone );
  configASSERT ( xSemaTxDone != NULL );
}

void GUI_X_Unlock(void)
{
	/* 给出互斥量 */
  xSemaphoreGive(xQueueMutex);
}

void GUI_X_Lock(void)
{
  if(xQueueMutex == NULL)
  {
    GUI_X_InitOS();
  }
	/* 获取互斥量 */
  xSemaphoreTake(xQueueMutex,   /* 互斥量句柄 */
								 portMAX_DELAY);/* 阻塞等待 */
}

/* Get Task handle */
U32 GUI_X_GetTaskId(void) 
{ 
  return ((U32) xTaskGetCurrentTaskHandle());
}


void GUI_X_WaitEvent (void) 
{
  /* 获取信号量 */
  while(xSemaphoreTake(xSemaTxDone,              /* 信号量句柄 */
								       portMAX_DELAY) != pdTRUE);/* 阻塞等待 */
}


void GUI_X_SignalEvent (void) 
{
  /* 给出信号量 */
  xSemaphoreGive(xSemaTxDone);
}


void GUI_X_Log (const char *s) { }
void GUI_X_Warn (const char *s) { }
void GUI_X_ErrorOut(const char *s) { }

五、测试

5.1 裸机测试

#include "sys.h"
#include "delay.h"
#include "timer.h"
#include "oled.h"
#include "GUI.h"

int main(void)
{
    Cache_Enable();                			//打开L1-Cache
    HAL_Init();				        		//初始化HAL库
    Stm32_Clock_Init(160,5,2,4);  		    //设置时钟,400Mhz
    delay_init(400);						//延时初始化

    TIM3_Init(50000-1,200-1);      	//定时器3初始化,定时器时钟为200M,分频系数为20000-1,  50ms  刷新屏幕
    __HAL_RCC_CRC_CLK_ENABLE();//使能CRC时钟,否则STemWin不能使用
    GUI_Init();
    GUI_SetBkColor(GUI_WHITE);		//设置背景颜色
	GUI_Clear();//全部显示背景色
	GUI_DispStringAt("hello world",0,0);
    while(1)
    {
			delay_ms(1000);
    }
}

5.2 含系统测试

//main.c
#include "sys.h"
#include "delay.h"
#include "timer.h"
#include "oled.h"
#include "GUI.h"
#include "textdisplay.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);



//任务优先级
#define Screen_update_TASK_PRIO		2
//任务堆栈大小	
#define Screen_update_STK_SIZE 		50  
//任务句柄
TaskHandle_t Screen_update_Task_Handler;
//任务函数
void Screen_update_task(void *pvParameters);



int main(void)
{
    Cache_Enable();                			//打开L1-Cache
    HAL_Init();				        		//初始化HAL库
    Stm32_Clock_Init(160,5,2,4);  		    //设置时钟,400Mhz
    delay_init(400);						//延时初始化
    TIM3_Init(50000-1,200-1);      	//定时器3初始化,定时器时钟为200M,分频系数为20000-1,  50ms  刷新屏幕
    __HAL_RCC_CRC_CLK_ENABLE();//使能CRC时钟,否则STemWin不能使用
		 
	//创建开始任务
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度

}
//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    //创建LED0任务
    xTaskCreate((TaskFunction_t )Screen_update_task,     	
                (const char*    )"Screen_update_task",   	
                (uint16_t       )Screen_update_STK_SIZE, 
                (void*          )NULL,				
                (UBaseType_t    )Screen_update_TASK_PRIO,	
                (TaskHandle_t*  )&Screen_update_Task_Handler);   
    vTaskDelete(StartTask_Handler); //删除开始任务
								    GUI_Init();
    emwin_texttest();
    taskEXIT_CRITICAL();            //退出临界区
}

void Screen_update_task(void *pvParameters)
{
    while(1)
    {
        vTaskDelay(50);  //50ms
			OLED_Refresh_Gram();
    }
}
#include "textdisplay.h"
#include "GUI.h"
void emwin_texttest(void)
{
	GUI_SetBkColor(GUI_BLUE);		//设置背景颜色
	GUI_Clear();					//清屏
	GUI_SetPenSize(10);				//设置笔大小
	GUI_SetFont(&GUI_Font8_ASCII); //设置字体
	GUI_DispStringHCenterAt("HELLO WORD!",63,0);
	GUI_SetTextMode(GUI_TM_REV);	//反转文本
	GUI_DispStringHCenterAt("GUI_TM_REV"   ,63,8);
	GUI_SetTextMode(GUI_TM_TRANS);	//透明文本
	GUI_DispStringHCenterAt("GUI_TM_TRANS" ,63,16);
	GUI_SetTextMode(GUI_TM_XOR);   	//异或文本
	GUI_DispStringHCenterAt("GUI_TM_XOR"   ,63,24);
	GUI_SetTextMode(GUI_TM_TRANS|GUI_TM_REV);//透明反转文本
	GUI_DispStringHCenterAt("GUI_EM_TRANS|GUI_TM_REV",63,32);
}

  • 7
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值