【简介】
本文实现了移植FreeRTOS与lvgl,并完成一个综合界面的开发。
【演示视频】
【FreeRTOS简介】
FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。由于RTOS需占用一定的系统资源(尤其是RAM资源),只有μC/OS-II、embOS、salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。相对μC/OS-II、embOS等商业操作系统,FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。
【LVGL简介】
LVGL(轻量级多功能图形库)是一个免费的开源图形库,提供创建嵌入式 GUI 所需的一切,具有易于使用的图形元素、精美的视觉效果和低内存占用。
主要特点:
- 强大的构建块,例如按钮、图表、列表、滑块、图像等。
- 具有动画、抗锯齿、不透明度、平滑滚动的高级图形
- 触摸板、鼠标、键盘、编码器等各种输入设备。
- 支持 UTF-8 编码的多语言
- 多显示器支持,即同时使用多个 TFT、单色显示器
- 完全可定制的图形元素,具有类似CSS的样式
- 独立于硬件:与任何微控制器或显示器一起使用
- 可扩展:能够在很少的内存下运行(64 kB 闪存,16 kB RAM)
- 支持操作系统、外部存储器和 GPU,但不是必需的
- 单帧缓冲操作,即使具有高级图形效果
- 用 C 语言编写以实现最大兼容性(C++ 兼容)
- 模拟器,用于在没有嵌入式硬件的 PC 上开始嵌入式 GUI 设计
- 绑定到 MicroPython
【显示功能实现】
GD为我们提供了很多例子,我们可以直接在提供的例子上进行修改就能得到期望的结果。
显示部分没啥好说的,主要注意一下显存地址就可以了。
初始化参考,这里我只使用了TLI的层0。
void app_lcd_init(void)
{
/* LCD configure and TLI enable */
lcd_config();
tli_layer_enable(LAYER0);
// tli_layer_enable(LAYER1);
tli_reload_config(TLI_REQUEST_RELOAD_EN);
tli_enable();
}
复制代码【FreeRTOS移植】
这个移植算是比较简单的了,基本复制过来加上文件就能用,有几个主要的点:
为了兼容官方原有的延时函数,需要对SysTick_Handler中断进行一下简单的配置。
/*!
\brief this function handles SysTick exception
\param[in] none
\param[out] none
\retval none
*/
void SysTick_Handler(void)
{
delay_decrement();
if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//系统已经运行
xPortSysTickHandler();
}
复制代码我使用的是AC6编译器,使用armclang编译器,需要调整一下port.c文件,使用下图框出来的位置
【LVGL移植】
需要注意几个接口的实现。
触摸接口
/* Will be called by the library to read the touchpad */
static void DEMO_ReadTouch(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
int16_t touch_x = 0;
int16_t touch_y = 0;
data->state = LV_INDEV_STATE_REL;
if(Read_ADS2(&touch_x,&touch_y) == 1)
{
data->state = LV_INDEV_STATE_PR;
}
/*Set the last pressed coordinates*/
data->point.y = touch_y;
data->point.x = touch_x;
}
复制代码显示接口
static void DEMO_FlushDisplay(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
lv_coord_t x1 = area->x1;
lv_coord_t y1 = area->y1;
lv_coord_t x2 = area->x2;
lv_coord_t y2 = area->y2;
int32_t length = (x2 - x1 + 1) * (y2 - y1 + 1) * LCD_FB_BYTE_PER_PIXEL;
int32_t x,y,i = 0;
for(y = y1; y <= y2; y++)
{
for(x = x1; x <= x2; x++)
{
*(uint16_t *)(SDRAM_LCD_BUFF_ADDR + 2 * ((480 * y) + x)) = *(uint16_t *)(color_p + i);
i++;
}
}
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(disp_drv);
}
复制代码定时调用lv_tick_inc函数
/*!
* @brief FreeRTOS tick hook.
*/
void vApplicationTickHook(void)
{
if (s_lvgl_initialized)
{
lv_tick_inc(1);
}
}
复制代码初始化显示任务
if (pdPASS != xTaskCreate(AppTask, "lvgl", configMINIMAL_STACK_SIZE + 800, NULL, tskIDLE_PRIORITY + 2, NULL))
{
printf("Failed to create lvgl task");
while (1)
;
}
vTaskStartScheduler();
复制代码【界面开发】
设计车机控制界面的时候,我使用了设计器,还是很方便的。
【演示】
运行Widgets Demo
车机电池界面
车机拨号界面
车机呼叫界面
车机A/C控制界面