之前在小熊派上移植过一个裸机版本的STemWin,耍了不少例程:
1.获取项目:
git clone https://gitee.com/morixinguan/bear-pi.git
以下是其中一到两个裸机项目的显示效果:
2.渐变色条显示实验
多文本控件实验:
后面计划在小熊派的屏幕上实现一个串口终端,支持RT-Thread的shell哈,那一定非常有趣!
目前RTOS的使用率越来越高,STemWin也提供了RTOS的配置模板:
源文件如下:
#include "GUI.h" /* FreeRTOS include files */ #include "cmsis_os.h" /********************************************************************* * * Global data */ //定义一个互斥锁 static osMutexId osMutex; //定义一个信号量 static osSemaphoreId osSemaphore; /********************************************************************* * * Timing: * GUI_X_GetTime() * GUI_X_Delay(int) Some timing dependent routines require a GetTime and delay function. Default time unit (tick), normally is 1 ms. */ //获取Tick int GUI_X_GetTime(void) { return ((int) xTaskGetTickCount()); } //GUI延时函数 void GUI_X_Delay(int ms) { vTaskDelay( ms ); } /********************************************************************* * * GUI_X_Init() * * Note: * GUI_X_Init() is called from GUI_Init is a possibility to init * some hardware which needs to be up and running before the GUI. * If not required, leave this routine blank. */ //一般不填写 void GUI_X_Init(void) { } /********************************************************************* * * GUI_X_ExecIdle * * Note: * Called if WM is in idle state */ //WM空闲状态接口 void GUI_X_ExecIdle(void) {} /********************************************************************* * * Multitasking: * * GUI_X_InitOS() * GUI_X_GetTaskId() * GUI_X_Lock() * GUI_X_Unlock() * * Note: * The following routines are required only if emWin is used in a * true multi task environment, which means you have more than one * thread using the emWin API. * In this case the * #define GUI_OS 1 * needs to be in GUIConf.h */ //针对OS通信需要初始化的内容 /* Init OS */ void GUI_X_InitOS(void) { /* Create Mutex lock */ osMutexDef(MUTEX); /* Create the Mutex used by the two threads */ osMutex = osMutexCreate(osMutex(MUTEX)); /* Create Semaphore lock */ osSemaphoreDef(SEM); /* Create the Semaphore used by the two threads */ osSemaphore= osSemaphoreCreate(osSemaphore(SEM), 1); } //给出互斥量 void GUI_X_Unlock(void) { osMutexRelease(osMutex); } //获取互斥量 void GUI_X_Lock(void) { osMutexWait(osMutex , osWaitForever) ; } //获取当前线程句柄 /* Get Task handle */ U32 GUI_X_GetTaskId(void) { return ((U32) osThreadGetId()); } //获取信号量 void GUI_X_WaitEvent (void) { osSemaphoreWait(osSemaphore , osWaitForever) ; } //释放信号量 void GUI_X_SignalEvent (void) { osMutexRelease(osSemaphore); } /********************************************************************* * * Logging: OS dependent Note: Logging is used in higher debug levels only. The typical target build does not use logging and does therefor not require any of the logging routines below. For a release build without logging the routines below may be eliminated to save some space. (If the linker is not function aware and eliminates unreferenced functions automatically) */ //LOG相关,一般不实现 void GUI_X_Log (const char *s) { } void GUI_X_Warn (const char *s) { } void GUI_X_ErrorOut(const char *s) { } /*************************** End of file ****************************/
那么如何用RT-Thread的接口来代替呢??只要按照要求实现如下常用的接口就行了,其它不常用的就不用管:
int GUI_X_GetTime(void); void GUI_X_Delay(int ms); void GUI_X_Init(void); void GUI_X_ExecIdle(void); void GUI_X_InitOS(void); void GUI_X_Unlock(void); void GUI_X_Lock(void); U32 GUI_X_GetTaskId(void) ; void GUI_X_WaitEvent (void) ; void GUI_X_SignalEvent (void) ; void GUI_X_Log (const char *s); void GUI_X_Warn (const char *s); void GUI_X_ErrorOut(const char *s);
于是,我们复制GUI_X_OS这个文件,然后改名为GUI_X_RT_Thread,也就相当于定义了一个基于RT-Thread的配置模板,然后基于新的配置模板对一些接口的实现和修改:
然后只要按照要求实现以下常用的接口就行了:
int GUI_X_GetTime(void); void GUI_X_Delay(int ms); void GUI_X_ExecIdle(void); void GUI_X_InitOS(void); void GUI_X_Unlock(void); void GUI_X_Lock(void); U32 GUI_X_GetTaskId(void) ; void GUI_X_WaitEvent (void) ; void GUI_X_SignalEvent (void) ;
接下来对文件的内容进行修改:
- 包含对应的头文件
/* RT-Thread include files */ //#include "cmsis_os.h" #include <rtthread.h>
- 将全局变量定义进行修改
//static osMutexId osMutex; //static osSemaphoreId osSemaphore; /*定义一个互斥锁*/ static rt_mutex_t osMutex = RT_NULL; /*定义一个信号量*/ static rt_sem_t osSemaphore = RT_NULL;
- 实现GUI_X_GetTime和GUI_X_Delay函数
int GUI_X_GetTime(void) //主要用于时机触发,代替裸机下的OS_TimeMS变量 { //return ((int) xTaskGetTickCount()); //使用RT-Thread的rt_tick_get函数获取tick return rt_tick_get(); } void GUI_X_Delay(int ms) { //vTaskDelay( ms ); //使用RT-Thread的延时函数,单位ms rt_thread_mdelay(ms); }
- 实现GUI_X_ExecIdle函数
void GUI_X_ExecIdle(void) { //空闲状态下1ms延时即可 GUI_X_Delay(1); }
- 实现GUI_X_InitOS函数
void GUI_X_InitOS(void) { /*创建互斥信号量,用于资源共享*/ osMutex = rt_mutex_create("osMutex", RT_IPC_FLAG_FIFO); RT_ASSERT(osMutex != RT_NULL); /*创建信号量,用于事件触发*/ osSemaphore = rt_sem_create("osSem", 0, RT_IPC_FLAG_FIFO); RT_ASSERT(osSemaphore != RT_NULL); }
- 实现GUI_X_Unlock函数
void GUI_X_Unlock(void) { //osMutexRelease(osMutex); //给出互斥量 rt_mutex_release(osMutex); }
- 实现GUI_X_Lock函数
void GUI_X_Lock(void) { //osMutexWait(osMutex , osWaitForever) ; if(osMutex == RT_NULL) { GUI_X_InitOS(); } //获取互斥量 rt_mutex_take(osMutex, RT_WAITING_FOREVER); }
- 实现GUI_X_GetTaskId函数
U32 GUI_X_GetTaskId(void) { //return ((U32) osThreadGetId()); /*获取当前线程句柄*/ return (U32) rt_thread_self(); }
- 实现GUI_X_WaitEvent函数
void GUI_X_WaitEvent (void) { // osSemaphoreWait(osSemaphore , osWaitForever) ; /*获取信号量*/ while(rt_sem_take(osSemaphore, RT_WAITING_FOREVER) != RT_EOK); }
- 实现GUI_X_SignalEvent函数
void GUI_X_SignalEvent (void) { //osMutexRelease(osSemaphore); /*给出信号量*/ rt_sem_release(osSemaphore); }
这样模板就修改完了,接下来,将之前裸机的工程的EMWIN目录拷贝到我移植好的RT-Thread工程上:(移植的工程来源于以下作品,我把里面很多逻辑裁掉了)
开源作品:基于RT-Thread 智慧农业监测系统产品级开发
并添加好对应的文件:
然后GUIConf.h中,要让GUI支持OS,则需要在Keil菜单对定义一个全局宏,使其全局生效,这样STemWin就支持RTOS了,其它配置参数和裸机驱动STemWin配置毫无二致,参考文初那篇文章的配置方法就可以了,唯一不同的地方就是使用的模板不同。
最后我定义了一个任务,编写了一个简单的STemWin显示实验和按键切换背景色的demo,实现效果如下:
获取项目:
git clone https://gitee.com/morixinguan/bear-pi.git
往期精彩
开源作品:基于RT-Thread 智慧农业监测系统产品级开发