前言
恩智浦“FRDM-MCXN947”评测活动由安富利和与非网协同举办。本篇内容由与非网用户发布,已获转载许可。原文可在与非网(eefocus)工程师社区查看。
背景
终于来到了最后一个任务,设计一个基于LVGL的GUI应用,可以在UI上拖动滑动条控制电机转速,点击按键切换点击旋转方向。
GUI设计采用NXP出品的Gui Guider工具,我电脑上安装的版本是v1.8.0版本。
界面设计
打开Gui Guider工具,当前v1.8.0只支持lvgl v8.3.10版本,然后选择模拟器,屏幕分辨率为 320x240。
01Gui Guider界面设计
创建工程时没有截图,在打开工程后以在下方状态栏找到Project控件点击展开,工程属性如下图所示:

设计的最终界面如下图所示,屏幕最上方是标题MCXN947 Motor Control,中间是一个NXP图片,再往下是3个按键,分别控制电机左转、停止、右转,最下方是两个文字标签和一个活动条,左右文字标签分别在电机左转和右转的时候单独显示。

我最早接触Gui Guider是v1.3.1版本,那个时候Gui Guider软件界面和当前版本有挺大差异的。当前软件版本的设计界面如上图所示:
UI编辑区,点击左边的星星图标展开或者收缩控件列表;以前的版本是固定在左侧的;
界面差异很大的是Event区,以前放在上图(4)的位置,和Attributes各自成一个Tab,如今挪到下方的状态栏,一开始还找不到,令人着急;
此外添加Event的方式也大有改善,可以给一个事件添加多个目标,参见下图。
02设置 Event
当前版本添加Event的方式很优秀,可以给一个对象添加多个事件,每个事件可以作用于多个目标控件,每个目标控件可以修改多个属性。
下图演示了Right按键添加clicked时间,作用于3个目标控件,并且添加了一个自定义代码,详细的描述是:
Right按键点击时,标签label_speed_left不可见;
Right按键点击时,标签label_speed_right变成可见状态;
Right按键点击时,滑动条slider_speed添加了一个标志,即LV_OBJ_FLAG_CLICKABLE,即可以点击(我的代码逻辑是Stop按键单击后不允许滑动条拖动,再点击Left或者Right按键之后才可以拖动)。

虽说Gui Guider方便了LVGL UI设计,但是也有一些不足之处,我的使用经验如下:
部分控件支持的属性不够丰富,例如给目标slider控件设置value值,居然找不到;
添加custom_code,代码自动补全功能不够完整;
添加了目标控件之后不能改变顺序,这一点还是有一些必要的,因为custom_code依赖一些控件状态,对代码顺序是有要求的;
不能从外部修改generated目录下的文件,因为每次生成都会被Gui Guider生成的文件覆盖掉,这个还有一些缺陷,毕竟在编辑器里写代码要比在Gui Guider里写代码速度快。

03模拟器运行
在UI设计完毕,现在电脑运行模拟器,如下图点击菜单栏上的编译按键,选择C语言版本,编译通过之后弹出模拟器界面。

编译通过,运行模拟器。

代码编写
上面说明Event添加方式不够灵活,还是需要手动修改代码。
我设计的GUI有以下逻辑:
界面初始化之后,滑动条数值为0不允许滑动,且左右两个速度标签是隐藏的,只有当电机左转或者右转时才单独显示一个对应的标签;
只有点击Left或者Right才能激活滑条,然后拖动滑条控制电机转动并调速;
点击Stop让滑条归零,两个速度标签隐藏,并且电机停转。
01初始化界面
初始化界面的代码放在custom.c文件中,代码如下,添加了两个变量,分别表示电机转速和电机转动方向:
/**********************
* STATIC VARIABLES
**********************/
uint32_t speed_value =0;
uint32_t direction =DIR_LEFT;
/**
* Create a demo application
*/
void custom_init(lv_ui *ui)
{
/* Add your codes here */
// 滑条不允许滑动
lv_obj_clear_flag(ui->pageStatic_slider_speed, LV_OBJ_FLAG_CLICKABLE);
// 两个速度标签不显示
lv_obj_add_flag(ui->pageStatic_label_speed_left, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(ui->pageStatic_label_speed_right, LV_OBJ_FLAG_HIDDEN);
}
02按键事件
三个按键和一个滑条的事件都放在events_init.c文件中。
2.1 滑条滑动事件
首先获取滑条位置转换为电机速度,保存在变量speed_value中;然后根据电机方向变量direction的值,分别控制电机左转或右转,并分别显示左右标签页显示电机速度。
static void pageStatic_slider_speed_event_handler(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
switch (code) {
caseLV_EVENT_VALUE_CHANGED:
{
speed_value = lv_slider_get_value(guider_ui.pageStatic_slider_speed);
switch (direction) {
caseDIR_LEFT:
lv_label_set_text_fmt(guider_ui.pageStatic_label_speed_left, "%d%%", speed_value);
motor_left(speed_value);
break;
caseDIR_RIGHT:
lv_label_set_text_fmt(guider_ui.pageStatic_label_speed_right, "%d%%", speed_value);
motor_right(speed_value);
break;
default:
break;
}
break;
}
default:
break;
}
}
2.2 left按键事件
单击Left按键,首先取消左侧的速度标签隐藏属性,即让其可见;
让右侧的速度标签页隐藏;
让滑条可以单击;
改变速度方向变量为DIR_LEFT方向;
设置滑条数值为speed_value数值;
让左侧速度标签页显示速度;
调用motor_left(speed_value)函数让电机向左转动并设置速度。
static void pageStatic_btn_left_event_handler(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
switch (code) {
caseLV_EVENT_CLICKED:
{
lv_obj_clear_flag(guider_ui.pageStatic_label_speed_left, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(guider_ui.pageStatic_label_speed_right, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(guider_ui.pageStatic_slider_speed, LV_OBJ_FLAG_CLICKABLE);
direction =DIR_LEFT;
lv_slider_set_value(guider_ui.pageStatic_slider_speed, speed_value, LV_ANIM_ON);
lv_label_set_text_fmt(guider_ui.pageStatic_label_speed_left, "%d%%", speed_value);
motor_left(speed_value);
break;
}
default:
break;
}
}
2.3 right按键事件
同Left按键事件,逻辑是反的,最后调用motor_right()函数让电机向右转动并设置转速。
static void pageStatic_btn_right_event_handler(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
switch (code) {
caseLV_EVENT_CLICKED:
{
lv_obj_add_flag(guider_ui.pageStatic_label_speed_left, LV_OBJ_FLAG_HIDDEN);
lv_obj_clear_flag(guider_ui.pageStatic_label_speed_right, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(guider_ui.pageStatic_slider_speed, LV_OBJ_FLAG_CLICKABLE);
direction =DIR_RIGHT;
lv_slider_set_value(guider_ui.pageStatic_slider_speed, speed_value, LV_ANIM_ON);
lv_label_set_text_fmt(guider_ui.pageStatic_label_speed_right, "%d%%", speed_value);
motor_right(speed_value);
break;
}
default:
break;
}
}
2.4 stop按键
让两个速度标签都隐藏,设置速度变量为0,并设置滑条数值为0,且不允许拖动滑条,最后调用motor_stop()让电机停止转动。
static void pageStatic_btn_stop_event_handler(lv_event_t* e)
{
lv_event_code_t code = lv_event_get_code(e);
switch (code) {
caseLV_EVENT_CLICKED:
{
lv_obj_add_flag(guider_ui.pageStatic_label_speed_left, LV_OBJ_FLAG_HIDDEN);
lv_obj_add_flag(guider_ui.pageStatic_label_speed_right, LV_OBJ_FLAG_HIDDEN);
speed_value =0;
lv_slider_set_value(guider_ui.pageStatic_slider_speed, speed_value, LV_ANIM_ON);
lv_obj_clear_flag(guider_ui.pageStatic_slider_speed, LV_OBJ_FLAG_CLICKABLE);
motor_stop();
break;
}
default:
break;
}
}
关于安富利
安富利是全球领先的技术分销商和解决方案提供商,在过去一个多世纪里一直秉持初心,致力于满足客户不断变化的需求。通过遍布全球的专业化和区域化业务覆盖,安富利可在产品生命周期的每个阶段为客户和供应商提供支持。安富利能够帮助各种类型的公司适应不断变化的市场环境,在产品开发过程中加快设计和供应速度。安富利在整个技术价值链中处于中心位置,这种独特的地位和视角让其成为了值得信赖的合作伙伴,能够帮助客户解决复杂的设计和供应链难题,从而更快地实现营收。
全部0条评论
快来发表一下你的评论吧 !