打印
[STM32F4]

STM32F4+FreeRTOS+LVGL实现嵌入式快速开发(缝合怪)

[复制链接]
355|40
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
610u|  楼主 | 2023-6-27 11:36 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
极速进行项目开发,只需要懂一款芯片架构+一个操作系统+一个GUI。各种部件程序全靠抄


,成为究极缝合怪。本文用stm32f407+FreeRTOS+lvgl演示一些demo。

原文链接:STM32F4+FreeRTOS+LVGL实现快速开发(缝合怪)

lvgl官方的音乐播放器demo:


百问网的2048小游戏:





使用特权

评论回复
沙发
610u|  楼主 | 2023-6-27 11:38 | 只看该作者
1.STM32F407和FreeRTOS
STM32F407这款芯片就不多介绍了,挺老的MCU,架构为ARM_CM4F。随便一搜就有非常非常多的例程和项目。

会缝合的基础是对芯片架构非常了解,刚入门的同学建议先从基础学起,推荐学习ARM官方的权威指南。

在家中找到一个早之前的开发板,个人还挺喜欢的,只有最小系统,把pin引出来了,没有乱七八糟的外设,还找到一个240*320的LCD屏幕,ILI9341驱动。

使用特权

评论回复
板凳
610u|  楼主 | 2023-6-27 11:38 | 只看该作者

至于FreeRTOS,之前讲了FreeRTOS在STM32F4上的移植:STM32F4移植FreeRTOS光是MCU加上FreeRTOS就已经能做很多东西了,github上也有非常多的项目,直接git clone再随便改改就能做出很多东西。

FreeRTOS的系列讲解:FreeRTOS全解析-1.引入与RTOS简介

使用特权

评论回复
地板
610u|  楼主 | 2023-6-27 11:40 | 只看该作者
2.LVGL和FreeRTOS结合
都有显示屏了,当然得显示一下,增加一下逼格,但是自己画肯定不好看,也也没有那个必要,这就需要借助开源图形库了。

嵌入式GUI有非常多,LVGL是其中之一,很低的配置就可以实现非常好的效果。介绍就没必要了,就是一个C语言写的图形库,需要学习的可以去官网:https://lvgl.io/看手册。

使用特权

评论回复
5
610u|  楼主 | 2023-6-27 11:40 | 只看该作者
官网的一个demo:

我对LVGL了解不多,但通过手册可以知道,LVGL的底层是通过定时器来循环调用lv_tick_inc();函数,以获知系统时间,称为LVGL的心跳。再通过lv_task_handler();(新版的是lv_timer_handler())来调度LVGL的各种任务,包括显示、输入,各种事件。搞明白这个,我们就可以非常容易得将他与FreeRTOS结合了。

使用特权

评论回复
6
610u|  楼主 | 2023-6-27 11:40 | 只看该作者
2.1下载LVGL源码,并加入keil工程
去官网找到源码,找个需要的版本,我这里用git下了lvgl8.0。

只需要如下几个东西

使用特权

评论回复
7
610u|  楼主 | 2023-6-27 11:49 | 只看该作者
把lv_conf_template.h的文件名改成lv_conf.h。这是官方提供的配置样板,我们要改成适合自己的。开头的if 0改成1,使它生效。
#if 1 /*Set it to "1" to enable content*/

使用特权

评论回复
8
610u|  楼主 | 2023-6-27 11:54 | 只看该作者
显示屏的颜色,我的是16位的
/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH     16

使用特权

评论回复
9
610u|  楼主 | 2023-6-27 14:22 | 只看该作者
显示和输入(触屏、按钮等)的周期,按需要改。显示周期20ms就是50帧。

/*Default display refresh period. LVG will redraw changed ares with this period time*/
#define LV_DISP_DEF_REFR_PERIOD     20      /*[ms]*/

/*Input device read period in milliseconds*/
#define LV_INDEV_DEF_READ_PERIOD    30      /*[ms]*/
内存和CPU监控开一下,方便看效果,就是我上面demo中左下角和右下角的显示。

/*1: Show CPU usage and FPS count in the right bottom corner*/
#define LV_USE_PERF_MONITOR     1

/*1: Show the used memory and the memory fragmentation  in the left bottom corner
* Requires LV_MEM_CUSTOM = 0*/
#define LV_USE_MEM_MONITOR      1

使用特权

评论回复
10
610u|  楼主 | 2023-6-27 14:22 | 只看该作者
examples文件夹中只需要porting文件夹。

使用特权

评论回复
11
610u|  楼主 | 2023-6-27 14:22 | 只看该作者
里面的文件名中的template,全部删掉。

使用特权

评论回复
12
610u|  楼主 | 2023-6-27 14:22 | 只看该作者
以STM32F4移植FreeRTOS中的已经移植好FreeRTOS的keil工程为模板

新建文件夹

使用特权

评论回复
13
610u|  楼主 | 2023-6-27 14:23 | 只看该作者
LVGL放入src文件,LVGL_PORT放入porting中的文件,LVGL_APP放入example中随便复制的demo

然后在keil中把所有.c文件添加进去,这个过程就比较麻烦,要,需要一个个点。

使用特权

评论回复
14
610u|  楼主 | 2023-6-27 14:23 | 只看该作者
2.2调整显示接口
lv_port_disp.c为lvgl的显示接口第一步就是把它和lv_port_disp.h头文件中的第一行if 0改为1,使他们生效。

lv_port_disp.h文件中添加两行,表示我LCD的分辨率为240*320

#define MY_DISP_HOR_RES 240
#define MY_DISP_VER_RES 320
lv_port_disp.c中初始化函数disp_init中,加上自己的LCD初始化函数。

static void disp_init(void)
{
    /*You code here*/
      LCD_Init();
}

使用特权

评论回复
15
610u|  楼主 | 2023-6-27 14:24 | 只看该作者
刷屏函数中加上自己的画点函数,官方中的例子是这样的
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    int32_t x;
    int32_t y;
    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            /*Put a pixel to the display. For example:*/
           /*put_px(x, y, *color_p)*/
             color_p++;
        }
    }
    lv_disp_flush_ready(disp_drv);
}

使用特权

评论回复
16
610u|  楼主 | 2023-6-27 14:25 | 只看该作者
{
    int32_t x;
    int32_t y;
    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            /*Put a pixel to the display. For example:*/
           /*put_px(x, y, *color_p)*/
             color_p++;
        }
    }
    lv_disp_flush_ready(disp_drv);
}

使用特权

评论回复
17
610u|  楼主 | 2023-6-27 14:25 | 只看该作者
/*put_px(x, y, *color_p)*/改成你LCD的画点函数,不过这样很慢,推荐直接使用区域绘制
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);
    lv_disp_flush_ready(disp_drv);
}

使用特权

评论回复
18
610u|  楼主 | 2023-6-27 14:25 | 只看该作者
{
    LCD_Color_Fill(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);
    lv_disp_flush_ready(disp_drv);
}

使用特权

评论回复
19
610u|  楼主 | 2023-6-27 14:25 | 只看该作者
这样会更快。

我的LCD用FSMC,速度已经够快了,但是我想更快一点,就用DMA(提升不会特别大)。在这个函数中只放一个DMA传输函数。
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
  LCD_Start_DMA_Transfer(area->x1,area->y1,area->x2,area->y2,(u16*)color_p);
}

使用特权

评论回复
20
610u|  楼主 | 2023-6-27 14:27 | 只看该作者
在DMA完成中断函数中通知LVGL
void DMA2_Stream3_IRQHandler(void)
{
  if(DMA_GetITStatus(LCD_DMA_Stream,LCD_DMA_IT_TCIFx)!=RESET)
  {
       DMA_ClearITPendingBit(LCD_DMA_Stream,LCD_DMA_IT_TCIFx);
       lv_disp_flush_ready(&disp_drv);
  }
}

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

43

主题

373

帖子

0

粉丝