基于Clion开发(stm32移植FreeRTOS+LVGL)

嵌入式单片机开发中,通常使用 Keil IAR 或 芯片厂商提供的IDE,这类IDE界面风格还停留在十几年前XP风,代码编辑实在让人难受,所以很多时候笔者都是采用VSCode编辑,然后再用这类IDE下载调试使用,另外像keilIAR 几万块价格也让很多人劝退(使用盗版,未收到律师函忽略)。那么有价格便宜,界面编辑优秀,又能跨平台的IDE吗?这里推荐VSCode(免费)和本章介绍的Clion

Clion环境搭建网上已经有很多文章出了教程,这里不做过多描述,本章主要介绍借助Clion平台开发某款芯片的流程。

配置CLion用于STM32开发【优雅の嵌入式开发】 - 知乎 (zhihu.com)

前期准备(文章末尾提供源码)

软件环境:

  • Windows 10
  • STM32CubeMX ------ ST官方代码生成工具(辅助使用,后期熟悉可脱离该工具)
  • Clion-2022.3.2
  • MinGW ------ 编译器套件
  • OpenOCD ------ 调试工具
  • arm-none-eabi-gcc -------- 交叉编译工具链
  • 调试器驱动(具体看用的哪种调试器)

硬件环境:

  • STM32L475VET6(正点原子潘多拉开发板)
  • ST-Link (J-link /dap 都可以)

工程移植搭建

1.工程初步生成

这里有两种方式:借助STM32CubeMX,快速生成;自行下载库从零搭建。

推荐使用CubeMX,因为会生成CMakeLists.txt文件,不用自己一个一个写,当然后期形成模板,完全可以脱离CubeMX

基于Clion开发(stm32移植FreeRTOS+LVGL)_第1张图片

2.CMakeLists.txt 修改(CMake部分提前说明如何修改,后面移植就不提了)

伴随着工程文件添加,需要在CMakeLists.txt 中添加需要编译的文件信息,类似于Keil IAR工作空间中添加文件。

实际添加起来会比以往的IDE便捷很多

基于Clion开发(stm32移植FreeRTOS+LVGL)_第2张图片

3.FreeRTOS移植

FreeRTOS - Free RTOS Source Code Downloads, the official FreeRTOS zip file release download

这里笔者使用的是V10.3.0版本,修改FreeRTOSConfig.h文件和SysTick_Handler函数

//根据需要确定系统堆大小
#define configTOTAL_HEAP_SIZE                   ((size_t)(16 * 1024))
//lvgl需要使用,这里打开
#define configUSE_TICK_HOOK                     1

//屏蔽 xPortSysTickHandler
//#define xPortSysTickHandler SysTick_Handler

/**
  * @brief This function handles System tick timer.
  */
void SysTick_Handler(void)
{
    extern void xPortSysTickHandler(void);
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)
    {
        xPortSysTickHandler();
    }
}

4.lvgl移植

LVGL - Light and Versatile Embedded Graphics Library

mirrors / lvgl / lvgl · GitCode

复制一份lv_conf_template.h 命名为 lv_conf.h,开启宏

基于Clion开发(stm32移植FreeRTOS+LVGL)_第3张图片

因为使用的开发板屏幕分辨率是:240*240 若做整个屏幕16bit刷新,那需要的缓存是:115200字节,显然在RAM只有128K的单片机上使用是不现实的,针对RAM较小的单片机只能做部分缓冲,如下操作:

/*******************************************************************************
 * Definitions
 ******************************************************************************/
#define LCD_WIDTH             240
#define LCD_HEIGHT            240
#define LCD_FB_BYTE_PER_PIXEL 2

/* The virtual buffer for DBI panel, it should be ~1/10 screen size. */
#define LCD_VIRTUAL_BUF_SIZE (LCD_WIDTH * LCD_HEIGHT / 10)

/*******************************************************************************
 * Variables
 ******************************************************************************/
static uint8_t s_frameBuffer[2][LCD_VIRTUAL_BUF_SIZE * LCD_FB_BYTE_PER_PIXEL];

void lv_port_disp_init(void)
{
    static lv_disp_draw_buf_t disp_buf;

    lv_disp_draw_buf_init(&disp_buf, s_frameBuffer[0], NULL, LCD_VIRTUAL_BUF_SIZE);  //s_frameBuffer[1]

    /*-------------------------
     * Initialize your display
     * -----------------------*/
    xSYS_ST7789_Init();

    /*-----------------------------------
     * Register the display in LittlevGL
     *----------------------------------*/
    static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
    lv_disp_drv_init(&disp_drv);   /*Basic initialization*/

    /*Set the resolution of the display*/
    disp_drv.hor_res = LCD_WIDTH;
    disp_drv.ver_res = LCD_HEIGHT;

    /*Used to copy the buffer's content to the display*/
    disp_drv.flush_cb = DEMO_FlushDisplay;

    /*Set a display buffer*/
    disp_drv.draw_buf = &disp_buf;

    /* Partial refresh */
    disp_drv.full_refresh = 1;

    /*Finally register the driver*/
    lv_disp_drv_register(&disp_drv);
}

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;

    uint32_t size = (x2 - x1 + 1) * (y2 - y1 + 1) * 2;

    //LCD_Fill(x1,y1,x2,y2,color_p);
    LCD_Address_Set(x1,y1,x2,y2);

    xSYS_LCD_Fill((uint8_t*)color_p,size);

    lv_disp_flush_ready(disp_drv);
}

除此之外添加如下代码:

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

void xGUI_MainTask(void *pvParameters)
{
	lv_port_pre_init();
    lv_init();
    lv_port_disp_init();   //显示初始化

	s_lvgl_initialized = true;

	pMainWidget = lv_scr_act();  //主体 Widget 创建

    lv_timer_create(lv_timer_user_callback,500,NULL);

    while(1)
    {	
        lv_task_handler();  //lvgl 任务处理函数
        vTaskDelay(5);
    }
}

static void lv_timer_user_callback(lv_timer_t * timer)
{
    static uint32_t colorCnt;
    lv_obj_set_style_bg_color(pMainWidget, lv_palette_main((lv_palette_t)colorCnt),LV_PART_MAIN);
    colorCnt++;
    colorCnt = colorCnt%12;
}
5.其他注意事项

每次添加了文件,需要刷新CMake再执行编译,否则会移植报错(原因是CMake Cache需要刷新)

基于Clion开发(stm32移植FreeRTOS+LVGL)_第4张图片

6.输出结果

STM32L475-Clion: clion搭建stm32工程 (gitee.com)

CSDN源码下载地址:STM32_Clion_RTOS_LVGL

你可能感兴趣的:(lvgl,RTOS,stm32,ide)