打印
[STM32F4]

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

[复制链接]
楼主: 610u
手机看帖
扫描二维码
随时随地手机跟帖
21
610u|  楼主 | 2023-6-27 14:27 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
然后就是为LVGL选择一种显存,在这个函数:

void lv_port_disp_init(void)

中,提供了三种显存方案,第一种是十行,第二种是双十行显存,第三种是双全屏显存,stm32f407sram只有192k,开不了全屏显存。

我选择第二种,双显存,因为我开启了DMA,传输的时候CPU可以去计算,并存入第二块显存。

使用特权

评论回复
22
610u|  楼主 | 2023-6-27 14:28 | 只看该作者
用不到的代码注释掉就行。如下: /* Example for 1) */
//    static lv_disp_draw_buf_t draw_buf_dsc_1;
//    static lv_color_t buf_1[MY_DISP_HOR_RES * 10];                          /*A buffer for 10 rows*/
//    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10);   /*Initialize the display buffer*/

    /* Example for 2) */
    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_2_1[MY_DISP_HOR_RES * 80];                        /*A buffer for 10 rows*/
    static lv_color_t buf_2_2[MY_DISP_HOR_RES * 80];                        /*An other buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 80);   /*Initialize the display buffer*/

//    /* Example for 3) also set disp_drv.full_refresh = 1 below*/
//    static lv_disp_draw_buf_t draw_buf_dsc_3;
//    static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*A screen sized buffer*/
//    static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*An other screen sized buffer*/
//    lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2, MY_DISP_VER_RES * LV_VER_RES_MAX);   /*Initialize the displ

    static lv_disp_draw_buf_t draw_buf_dsc_1;
    static lv_color_t buf_2_1[MY_DISP_HOR_RES * 80];                        /*A buffer for 10 rows*/
    static lv_color_t buf_2_2[MY_DISP_HOR_RES * 80];                        /*An other buffer for 10 rows*/
    lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_2_1, buf_2_2, MY_DISP_HOR_RES * 80);   /*Initialize the display buffer*/

//    /* Example for 3) also set disp_drv.full_refresh = 1 below*/
//    static lv_disp_draw_buf_t draw_buf_dsc_3;
//    static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*A screen sized buffer*/
//    static lv_color_t buf_3_1[MY_DISP_HOR_RES * MY_DISP_VER_RES];            /*An other screen sized buffer*/
//    lv_disp_draw_buf_init(&draw_buf_dsc_3, buf_3_1, buf_3_2, MY_DISP_VER_RES * LV_VER_RES_MAX);   /*Initialize the display buffer*/[/code]

使用特权

评论回复
23
610u|  楼主 | 2023-6-27 14:28 | 只看该作者
同时,比较旧的lvgl在这个函数中,还需要注册一下,新的不用

    /*Set up the functions to access to your display*/
    /*Set the resolution of the display*/
    disp_drv.hor_res = MY_DISP_HOR_RES;
    disp_drv.ver_res = MY_DISP_VER_RES;
其实就是加上分辨率。

使用特权

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

lvgl支持触摸屏,按键,编码器等输入,我用触摸屏,只需要修改touchpad相关

static void touchpad_init(void)
{
   /*Your code comes here*/
  tp_dev.init();
}
/*Return true is the touchpad is pressed*/
static bool touchpad_is_pressed(void)
{
    tp_dev.scan(0);
    if(tp_dev.sta&TP_PRES_DOWN)
      return true;
    return false;
}

/*Get the x and y coordinates if the touchpad is pressed*/
static void touchpad_get_xy(lv_coord_t * x, lv_coord_t * y)
{
    (*x) = tp_dev.x[0];
    (*y) = tp_dev.y[0];
}

使用特权

评论回复
25
610u|  楼主 | 2023-6-27 14:29 | 只看该作者
分别是初始化、扫描确实是否有按下,和获取按下的点的值。

我的触摸屏是电阻屏,驱动从正点原子的触摸屏实验例程中来,该驱动中用到了SysTick定时器来延时微秒,我们的工程是含有FreeRTOS的,会造成冲突,我也懒得优化细改了,用了个比较粗糙简单的方法,直接在延时前把几个寄存器保存一下,延时后再恢复。

使用特权

评论回复
26
610u|  楼主 | 2023-6-27 14:30 | 只看该作者
void delay_us(u32 nus)
{   
  u32 temp;  
  u32  tickload = SysTick->LOAD;
  u32  tickval = SysTick->VAL;
  u32  tickctrl = SysTick->CTRL;
  
  SysTick->LOAD=nus*fac_us;         //ʱ¼ä¼ÓÔØ         
  SysTick->VAL=0x00;                //Çå¿Õ¼ÆÊýÆ÷
  SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //¿ªÊ¼µ¹Êý   
  do
  {
    temp=SysTick->CTRL;
  }while((temp&0x01)&&!(temp&(1<<16)));  //µÈ´ýʱ¼äµ½´ï   
  SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //¹Ø±Õ¼ÆÊýÆ÷
  SysTick->VAL =0X00;               //Çå¿Õ¼ÆÊýÆ÷
  
  SysTick->LOAD  = tickload;
  SysTick->VAL  = tickval;
  SysTick->CTRL  = tickctrl;
}

使用特权

评论回复
27
610u|  楼主 | 2023-6-27 14:30 | 只看该作者
读数据TP_Read_AD中加入临界区保护,就可以完美使用。
u16 TP_Read_AD(u8 CMD)    
{   
  taskENTER_CRITICAL();
  略
  taskEXIT_CRITICAL();     
  return(Num);   
}

使用特权

评论回复
28
610u|  楼主 | 2023-6-27 14:30 | 只看该作者
2.4main函数
开头说了,将LVGL与FreeRTOS结合的重点其实就是再讲lv_tick_inc()和lv_task_handler()两个函数与FreeRTOS结合起来。

FreeRTOS也有心跳Tick,我们在FreeRTOS的FreeRTOSConfig.h中开启TICK钩子:

#define configUSE_TICK_HOOK        1

每次FreeRTOS发生tick都会去调用钩子函数,在钩子函数中放入LVGL的心跳就可以了:

void vApplicationTickHook(void)
{
  lv_tick_inc(1);
}

使用特权

评论回复
29
610u|  楼主 | 2023-6-27 14:31 | 只看该作者
数字1的意思是告诉LVGL每1ms执行一次。

至于lv_task_handler(),我们开一个任务去执行它

因为LVGL线程不安全,所以调用到LVGL的API时需要加互斥锁。

主函数:

  MutexSemaphore=xSemaphoreCreateMutex();
  xTaskCreate(lvgl_handler, "lvgl_handler", 1000, NULL, 4, NULL);

使用特权

评论回复
30
610u|  楼主 | 2023-6-27 14:31 | 只看该作者
任务:

static void lvgl_handler( void *pvParameters )
{
  for( ;; )
  {   
    xSemaphoreTake(MutexSemaphore,portMAX_DELAY);  
    lv_task_handler();
    xSemaphoreGive(MutexSemaphore);
//    vTaskDelay(pdMS_TO_TICKS(20));
  }
}
到这了就是完全移植成功了。

使用特权

评论回复
31
610u|  楼主 | 2023-6-27 14:31 | 只看该作者
现在你需要的就是个应用代码,github上有特别多的LVGL相关例子,官方也有很多,随便一抄,稍微修改,就可以完成一个小项目,这就是缝合的威力。

lvgl官方的压力测试demo:

使用特权

评论回复
32
公羊子丹| | 2024-2-1 07:09 | 只看该作者

PCB也会使电源工作不稳定

使用特权

评论回复
33
万图| | 2024-2-1 08:12 | 只看该作者

这些交流电流的峰值有可能是连续输入或输出直流电流的2~5倍

使用特权

评论回复
34
Uriah| | 2024-2-1 09:15 | 只看该作者

让PCB顶层和底层一样,将它们通过一些过孔(或通孔)连接

使用特权

评论回复
35
帛灿灿| | 2024-2-1 11:11 | 只看该作者

输出滤波电容存储来自输出整流器的高频能量

使用特权

评论回复
36
Bblythe| | 2024-2-1 12:14 | 只看该作者

电源中都有一个交流电压最大的节点

使用特权

评论回复
37
周半梅| | 2024-2-1 14:10 | 只看该作者

功率开关管交流电流环路

使用特权

评论回复
38
Pulitzer| | 2024-2-1 15:13 | 只看该作者

一个地是连接控制集成电路和与之相关的无源器件的地

使用特权

评论回复
39
童雨竹| | 2024-2-1 17:09 | 只看该作者

传送交流信号的引线要尽可能短且宽

使用特权

评论回复
40
Wordsworth| | 2024-2-1 18:12 | 只看该作者

引线上的电压降比较大

使用特权

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

本版积分规则