从零开始学习FreeRTOS之在STM32上移植FreeRTOS(五)

这次我们已经将上次的屏幕换成了240*320的触摸屏,不知道怎么移植触摸屏的可以看我的另一篇文章:
电容触摸屏移植: 电容触摸屏移植
注意每个卖家卖的触摸屏驱动IC不一定一样,但是通讯方式都是大同小异的,所以记得问卖家要资料,然后再根据通讯方式修改。

本期我们要实现的目标是用GUI_guider软件实现一个温控灯界面,还可以显示温度和湿度的界面框架。

一、 GUI_GUIDER的安装

安装包链接如下:
GUI_GUIDER官网链接: GUI_GUIDER官网链接
离线安装包如下:
GUI_GUIDER离线安装包: GUI_GUIDER离线安装包
建议大家还是用官网链接,因为LVGL的版本一直在变,新的和旧的可能不兼容。
打开界面是这样的:

从上到下分别是:创建一个新项目,打开一个最近的项目,导入一个当地的项目。我们先创建一个新项目。

版本选择8.3.10

这里可以选择你的运行环境,因为NXP公司自己也出板子,所以这里提供了很多他们公司自己的板子。但是我们现在用的是STM32,所以我们就选Simulator(仿真)

在这里可以选择很多软件提供的DEMO,我这里用的是EMPTY_UI。

再点击creat就可以成功创建出来了。

你可以在软件右上角将语言调成中文。

二、 用GUI_GUIDER设计UI界面

  1. 开始创建容器。
  2. 添加拾色器
  3. 添加其他标签
  4. 添加文本
  5. 添加按钮
  6. 添加事件


右键点击按钮,选择添加事件。看中下方。


以此类推,创建其他两个按钮和事件。

  1. 运行验证

    运行的结果和预想一致。

三、 将GUI_GUIDER生成的代码接入STM32

  1. 导出代码
    在左上角,如图:

    点进生成文件的src文件夹里,里面应该如图:

    我们要将这两个文件移植到上一章我们完成的项目里。

    我将他们放在了APP文件夹内。

  2. 接入项目
    将custom和generated文件夹里面的所有C文件加入项目中。
    头文件如下:

    有些人会出现以下定义报错:

    因为实际上我们没使用到,所以我们定义一个空的数据类型让他调用。
    我们点开这个函数之前调用的回调函数,然后定义一个如下的数据类型:

//delete,new defination
typedef void (*lv_anim_deleted_cb_t)(struct _lv_anim_t * anim);

然后再在event_init.c文件中定义一个变量:

lv_ui guider_ui;

注意这里变量名尽量不要变,他是被gui_guider.h头文件声明了可被外部引用的:

extern lv_ui guider_ui;

此时我们再编译就没有报错了。
打开生成的代码文件中的main.c文件
将以下两句复制过来:

	setup_ui(&guider_ui);
   	events_init(&guider_ui);

再在FreeRTOS中将lvgl的运行程序改为:

/**
 * @brief       LVGL运行例程
 * @param       pvParameters : 传入参数(未用到)
 * @retval      无
 */
void lv_demo_task(void *pvParameters)
{
    pvParameters = pvParameters;
    
    setup_ui(&guider_ui);
   	events_init(&guider_ui);
    
    while(1)
    {
        lv_timer_handler(); /* LVGL计时器 */
        vTaskDelay(5);
    }
}

(不得不说,FreeRTOS移植是真的好爽)
再在main.c中复制头文件:

#include "../generated/gui_guider.h"
#include "../generated/events_init.h"

然后修改以下加载到项目头文件中:

#include "gui_guider.h"
#include "events_init.h"

如果现在烧录到单片机上,你可以通过三个按钮来控制当前颜色。

  1. 修改生成代码
    事件触发主要由event_init.c这个文件控制,我们可以打开它看看。
static void screen_btn_1_event_handler (lv_event_t *e)
{
	// 获取事件代码
    lv_event_code_t code = lv_event_get_code(e);
    switch (code) {
	case LV_EVENT_PRESSED:
	{
		// 设置屏幕的背景颜色为0xff0000
		lv_obj_set_style_bg_color(guider_ui.screen_temp_color, lv_color_hex(0xff0000), LV_PART_MAIN);
		break;
	}
    default:
        break;
    }
}

这是红色按钮的事件回调函数,注释已经写好了。
然后在下面的函数中将回调函数和对应的对象链接在一起:

void events_init_screen (lv_ui *ui)
{
	lv_obj_add_event_cb(ui->screen_temp_color, screen_temp_color_event_handler, LV_EVENT_ALL, ui);
	lv_obj_add_event_cb(ui->screen_btn_1, screen_btn_1_event_handler, LV_EVENT_ALL, ui);
	lv_obj_add_event_cb(ui->screen_btn_2, screen_btn_2_event_handler, LV_EVENT_ALL, ui);
	lv_obj_add_event_cb(ui->screen_btn_3, screen_btn_3_event_handler, LV_EVENT_ALL, ui);
}

打开函数原型,如下:

struct _lv_event_dsc_t * lv_obj_add_event_cb(lv_obj_t * obj, lv_event_cb_t event_cb, lv_event_code_t filter,
                                             void * user_data)
{
    LV_ASSERT_OBJ(obj, MY_CLASS);
    lv_obj_allocate_spec_attr(obj);

    obj->spec_attr->event_dsc_cnt++;
    obj->spec_attr->event_dsc = lv_mem_realloc(obj->spec_attr->event_dsc,
                                               obj->spec_attr->event_dsc_cnt * sizeof(lv_event_dsc_t));
    LV_ASSERT_MALLOC(obj->spec_attr->event_dsc);

    obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].cb = event_cb;
    obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].filter = filter;
    obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1].user_data = user_data;

    return &obj->spec_attr->event_dsc[obj->spec_attr->event_dsc_cnt - 1];
}

很明显第一个是我们需要控制的对象,第二个是事件回调函数,第三个是行为事件定义,第四个是是将数据传给回调函数的参数。
我们现在想通过控制拾色器来控制当前颜色,那么我们就需要在这这个函数的基础上再写一个函数:

// 颜色拾取器的事件处理函数
static void screen_cpicker_event_handler(lv_event_t *e)
{
    // 获取当前的事件代码
    lv_event_code_t code = lv_event_get_code(e);

    switch (code) {
        case LV_EVENT_VALUE_CHANGED:  // 颜色变化事件
        {
            // 获取颜色拾取器对象
            lv_obj_t * colorwheel = lv_event_get_target(e);

            // 获取当前选中的颜色
            lv_color_t selected_color = lv_colorwheel_get_rgb(colorwheel);

            // 将选中的颜色应用到便签背景颜色上
            lv_obj_set_style_bg_color(guider_ui.screen_temp_color, selected_color, LV_PART_MAIN);
            break;
        }
        default:
            break;
    }
}

然后再在注册函数中添加:

  lv_obj_add_event_cb(ui->screen_cpicker_1, screen_cpicker_event_handler, LV_EVENT_VALUE_CHANGED, NULL);

编译无报错,实验结果如下:

LVGL_4: LVGL_4
文章参考视频:https://www.bilibili.com/video/BV1vn4y197HW/?spm_id_from=333.880.my_history.page.click

作者:YUki又叫6777

物联沃分享整理
物联沃-IOTWORD物联网 » 从零开始学习FreeRTOS之在STM32上移植FreeRTOS(五)

发表回复