在网上没有找到有耐心去看的适合的教程和视频,主要是我写的代码实在是太多,虽然只是几页非常简洁的页面,但是改动起来还是嫌麻烦,所以完全没有耐心。在寻找的路上挣扎了很长一段时间,2024年9月27日晚偶然在网上看到一个比较简单而且看得懂的例子,于是复制了下来做实验,没想到成功了,但是没能匹配到我原来的代码上就被叫去打台球了,于是今天2024年9月28日早上上完课,在机房大约实验了快2个小时,还是被一堆问题所难倒,于是就去吃了饭交网费了,大约15:00:36来到教室到19:19:24,终于得到解决,可能是一种最低级的解决办法。
问题所在:关于LVGL中实时更新数据而且在换页后停止更新的问题。解决的办法:找到一个比较简洁的计时器代码,一点一点试,差点放弃,同时想过很多种可能。解决的问题:在需要更新的页面air_display()函数中后面加了while(1),
while (1)
{
if(display_btn_left && display_btn_right)
{
lv_task_handler(); //回调函数(需要更新的内容)
}else{
break; //如果触发了显示界面其中一个将会跳出该循环
}
}
并且在air_display()函数的回调函数display_even_cb()里面,触发temp按钮代码的下面加了生成一个定时器的代码:
timer = lv_timer_create(timer_callback, 1000, NULL);
实现在点temp时生成计时器,并且有效的执行计时器回调函数更新数据。开启定时器后,在切换页面后还是需要关闭一下,因为不关闭,会占用LVGL很多资源,导致无法运行新的页面;为了解决这个问题,于是在home_page()和pre_waring()两个函数里面加了判定标准display_btn_left 和 display_btn_right,以此来准确的删除定时器。这个问题应该肯定有比较好的就解决方法的,我这种方法应该是最烂的一种。还有一个不得不说的问题,也就是存在的bug,想要点击home和waring按钮必须先生成一个计时器,也就是先点击temp按钮,不然将会卡死,出现这一问题的原因是:home_page()和pre_waring()要删除计时器而又灭有计时器可删的,本来计时器timer是一个指针,容易出现问题。
#include "aqi_lvgl.h"
#include "lvgl.h"
static lv_obj_t *btn[8]; //
static lv_obj_t *aqi[8];
static lv_obj_t *obj_waring[8]; //
static lv_obj_t *waring_up[8]; //用于设置预警值的加操作
static lv_obj_t *waring_down[8];//用于设置预警值的减操作
static lv_obj_t *waring_up_key[8];
static lv_obj_t *waring_down_key[8];
static lv_obj_t *air_waring[8];
static int waring_value[8]={0};
static lv_obj_t *switch_waring[8];
static int switch_state[8]={0};
static int air_value[8]={0};
static char air[8][6]={"PM2.5","PM10","SO2","NO2","CO","O3","AQI","TEMP"};
static lv_obj_t *redirct[6]; //跳转
static lv_obj_t *redirct_value[6]; //跳转的方向
static bool display_btn_left=true; //显示页面的左右按键转态值
static bool display_btn_right=true; //true表示在现实界面,false表示离开现实界面
void pre_warning(void);
void air_dispaly(void);
void home_page(void);
static lv_timer_t * timer; 创建一个定时器,调用 timer_callback 每 1000 毫秒 (1 秒)
// 定时器回调
static void timer_callback(lv_timer_t * timer)
{
for(int i=0;i<8;i++) //显示空气值
{
if(i!=7)
{
air_value[i]++;
lv_label_set_text_fmt(aqi[i],"%s \n\n %d ug/m^3",air[i],air_value[i]);
//printf("%s \n\n %d ug/m^3",air[i],air_value[i]);
当设的阈值小于空气因子值时,显示页面变为红色
if(waring_value[i] < air_value[i]&&switch_state[i]) //当设的阈值小于空气因子值时,显示页面变为红色
{
lv_obj_set_style_bg_color(btn[i],lv_color_hex(0xE70000),LV_STATE_DEFAULT);
}
}else{
lv_label_set_text_fmt(aqi[i],"%s",air[i]);
}
}
// 这里可以执行其他任务,例如更新 UI
}
//显示回调
static void display_even_cb(lv_event_t *e)
{
lv_obj_t *target = lv_event_get_target(e);
// 当设的阈值小于空气因子值时,显示页面变为红色
// for(int i=0;i<7;i++)
// {
// if(waring_value[i] < air_value[i]&&switch_state[i]) //当设的阈值小于空气因子值时,显示页面变为红色
// {
// lv_obj_set_style_bg_color(btn[i],lv_color_hex(0xE70000),LV_STATE_DEFAULT);
// }
// }
//按下显示页面的TEMP按键时,清空显示页面的所有值,并且开启定时器,更新数据;
if(target == btn[7]) //按下显示页面的TEMP按键时,清空显示页面的所有值
{
for(int i=0;i<7;i++)
{
air_value[i]=0;
lv_label_set_text_fmt(aqi[i],"%s \n\n %d ug/m^3",air[i],air_value[i]);
lv_obj_set_style_bg_color(btn[i],lv_color_hex(0x2094F0),LV_STATE_DEFAULT);
}
timer = lv_timer_create(timer_callback, 1000, NULL); //当按下temp按钮时,将开启一个计时器
}
}
//警告显示回调
static void waring_event_cb(lv_event_t *e)
{
lv_obj_t *target = lv_event_get_target(e);
for(int i=0;i<7;i++)
{
if(target == waring_up[i])
{
waring_value[i]++;
lv_label_set_text_fmt(air_waring[i],"%s : %d",air[i],waring_value[i]);
}else if(target == waring_down[i])
{
waring_value[i]--;
lv_label_set_text_fmt(air_waring[i],"%s : %d",air[i],waring_value[i]);
}else if(target == switch_waring[i])
{
switch_state[i]++;
if(switch_state[i] > 1) //大于1表示第二次按下,也就是关闭状态,因为默认开机为关闭状态
{
switch_state[i]=0;
}
}
}
if(target == waring_up[7])
{
for(int i=0;i<7;i++)
{
waring_value[i]++;
lv_label_set_text_fmt(air_waring[i],"%s : %d",air[i],waring_value[i]);
}
}else if(target == waring_down[7])
{
for(int i=0;i<7;i++)
{
waring_value[i]--;
lv_label_set_text_fmt(air_waring[i],"%s : %d",air[i],waring_value[i]);
}
}else if(target == switch_waring[7]) //关闭所有开关和开启所有开光
{
switch_state[7]++;
if(switch_state[7] > 1) //大于1表示第二次按下,也就是关闭状态,因为默认开机为关闭状态
{
switch_state[7]=0;
for(int i=0;i<8;i++)
{
switch_state[i]=0;
lv_obj_clear_state(switch_waring[i],LV_STATE_CHECKED); //关闭开关
}
}else
{
for(int i=0;i<8;i++)
{
switch_state[i]=1;
lv_obj_add_state(switch_waring[i],LV_STATE_CHECKED); //开启开关
}
}
}
}
//换页选择回调
static void redirct_event_cb(lv_event_t *e)
{
lv_obj_t *target = lv_event_get_target(e);
if(target == redirct[0] || target == redirct[3])
{
lv_obj_clean(lv_scr_act()); //清除当前活动屏幕上面的所有对象
if(target == redirct[3])
{
display_btn_right = false;
}
pre_warning();
}else if(target == redirct[1] || target == redirct[4])
{
lv_obj_clean(lv_scr_act()); //清除当前活动屏幕上面的所有对象
air_dispaly(); //显示显示页
display_btn_left = true; //
display_btn_right = true; //
}else if(target == redirct[2] || target == redirct[5])
{
lv_obj_clean(lv_scr_act());
if(target == redirct[2])
{
display_btn_left = false;
}
home_page();
}
}
//换页设置函数
void redirct_set(int i)
{
redirct[i] = lv_btn_create(lv_scr_act());
lv_obj_set_size(redirct[i],80,45);
lv_obj_set_style_bg_color(redirct[i],lv_color_hex(0xF0F0F0),LV_STATE_DEFAULT);
lv_obj_set_style_opa(redirct[i],200,LV_STATE_DEFAULT);
if(i%2==0)
{
lv_obj_align(redirct[i],LV_ALIGN_TOP_LEFT,30,20);
}else{
lv_obj_align(redirct[i],LV_ALIGN_TOP_RIGHT,-30,20);
}
lv_obj_add_event_cb(redirct[i],redirct_event_cb,LV_EVENT_CLICKED,NULL); //触发回调
redirct_value[i]=lv_label_create(redirct[i]);
lv_obj_set_style_text_color(redirct_value[i],lv_color_hex(0xE70000),LV_STATE_DEFAULT);
lv_obj_set_align(redirct_value[i],LV_ALIGN_CENTER);
lv_obj_set_style_text_font(redirct_value[i],&lv_font_montserrat_16,LV_STATE_DEFAULT);
}
//警告函数
void pre_warning(void)
{
//判断是否需要清理显示界面的定时器
if((display_btn_left && !display_btn_right) || (display_btn_left && display_btn_right))
{
lv_timer_del(timer);
}
lv_obj_t *title = lv_label_create(lv_scr_act());
lv_label_set_text(title,"WARING PAGE");
lv_obj_set_style_text_font(title,&lv_font_montserrat_24,LV_STATE_DEFAULT);
lv_obj_align(title,LV_ALIGN_TOP_MID,0,35);
for(int i=0;i<8;i++)
{
obj_waring[i] = lv_obj_create(lv_scr_act());
lv_obj_set_size(obj_waring[i],150,150);
waring_up[i] = lv_btn_create(obj_waring[i]);
lv_obj_align(waring_up[i],LV_ALIGN_TOP_MID,-30,0);
lv_obj_set_style_bg_color(waring_up[i],lv_color_hex(0xE0E0E0),LV_STATE_DEFAULT);
lv_obj_add_event_cb(waring_up[i],waring_event_cb,LV_EVENT_CLICKED,NULL);
waring_down[i] = lv_btn_create(obj_waring[i]);
lv_obj_align(waring_down[i],LV_ALIGN_TOP_MID,30,0);
lv_obj_set_style_bg_color(waring_down[i],lv_color_hex(0xE0E0E0),LV_STATE_DEFAULT);
lv_obj_add_event_cb(waring_down[i],waring_event_cb,LV_EVENT_CLICKED,NULL); //触发回调函数
waring_up_key[i] = lv_label_create(waring_up[i]);
lv_label_set_text(waring_up_key[i],"+");
lv_obj_set_align(waring_up_key[i],LV_ALIGN_CENTER);
lv_obj_set_style_text_color(waring_up_key[i],lv_color_hex(0x2094F0),LV_STATE_DEFAULT);
waring_down_key[i] = lv_label_create(waring_down[i]);
lv_label_set_text(waring_down_key[i],"-");
lv_obj_set_align(waring_down_key[i],LV_ALIGN_CENTER);
lv_obj_set_style_text_color(waring_down_key[i],lv_color_hex(0x2094F0),LV_STATE_DEFAULT);
air_waring[i] = lv_label_create(obj_waring[i]);
lv_obj_align(air_waring[i],LV_ALIGN_CENTER,0,0);
if(i == 7)
{
lv_label_set_text_fmt(air_waring[i],"%s",air[i]);
}else
{
lv_label_set_text_fmt(air_waring[i],"%s : %d",air[i],waring_value[i]);
}
switch_waring[i] = lv_switch_create(obj_waring[i]);
lv_obj_align_to(switch_waring[i],air_waring[i],LV_ALIGN_OUT_BOTTOM_MID,0,15);
lv_obj_add_event_cb(switch_waring[i],waring_event_cb,LV_EVENT_CLICKED,NULL); //触发回调函数
if(i==0)
{
lv_obj_align(obj_waring[i],LV_ALIGN_TOP_LEFT,55,85);
}else if(i<4)
{
lv_obj_align_to(obj_waring[i],obj_waring[i-1],LV_ALIGN_OUT_RIGHT_MID,30,0);
}
else{
lv_obj_align_to(obj_waring[i],obj_waring[i-4],LV_ALIGN_OUT_BOTTOM_MID,0,20);
}
}
for(int i=0;i<8;i++)
{
if(switch_state[i]==0) //跳转后,如果状态为0表示之前为关闭状态,反之为开启状态
{
lv_obj_clear_state(switch_waring[i],LV_STATE_CHECKED);
}else {
lv_obj_add_state(switch_waring[i],LV_STATE_CHECKED);
}
}
redirct_set(4);
redirct_set(5);
lv_label_set_text(redirct_value[4],"display");
lv_label_set_text(redirct_value[5],"home");
}
//空气质量值显示函数
void air_dispaly(void)
{
lv_obj_t *title = lv_label_create(lv_scr_act());
lv_label_set_text(title,"DISPLAY PAGE");
lv_obj_set_style_text_font(title,&lv_font_montserrat_24,LV_STATE_DEFAULT);
lv_obj_align(title,LV_ALIGN_TOP_MID,0,50);
//Model_AirValue();//模拟空气值
//显示基本的图形框架
for(int i=0;i<8;i++)
{
btn[i] = lv_btn_create(lv_scr_act());
lv_obj_set_size(btn[i],130,110);
if(i == 0)
{
lv_obj_align(btn[i],LV_ALIGN_DEFAULT,50,125);
}else if(i<4)
{
lv_obj_align_to(btn[i],btn[i-1],LV_ALIGN_OUT_RIGHT_MID,60,0);
}else{
lv_obj_align_to(btn[i],btn[i-4],LV_ALIGN_OUT_BOTTOM_MID,0,60);
}
if(i==7)
{
lv_obj_set_style_bg_color(btn[i],lv_color_hex(0xCA3316),LV_STATE_DEFAULT);
}
lv_obj_add_event_cb(btn[i],display_even_cb,LV_EVENT_CLICKED,NULL);
aqi[i] = lv_label_create(btn[i]);
lv_obj_set_align(aqi[i],LV_ALIGN_CENTER);
}
//跳转显示按钮
redirct_set(2);
redirct_set(3);
lv_label_set_text(redirct_value[2],"home");
lv_label_set_text(redirct_value[3],"waring");
//初始化空气值
for(int i=0;i<7;i++)
{
lv_label_set_text_fmt(aqi[i],"%s \n\n %d ug/m^3",air[i],0);
}
// 创建一个定时器,调用 timer_callback 每 1000 毫秒 (1 秒)
//timer = lv_timer_create(timer_callback, 1000, NULL);
while (1)
{
if(display_btn_left && display_btn_right)
{
//lv_timer_resume(timer);
//lv_tick_inc(5); // LVGL tick
lv_task_handler(); //回调函数(需要更新的内容)
}else{
//lv_timer_pause(timer); //暂停定时器
break; //如果触发了显示界面其中一个将会跳出该循环
}
}
}
//主页显示函数
void home_page(void)
{
//判断是否需要清理显示界面的定时器
if((!display_btn_left && display_btn_right) || (display_btn_left && display_btn_right))
{
lv_timer_del(timer);
}
lv_obj_t *homepage = lv_label_create(lv_scr_act());
lv_label_set_text(homepage,"#E70000 AIR QUALITY MONITORING SYSTEM\n #"
"Real-ti me air quality monitoring, safeguarding your breathing health.\n"
"Clearly displaying data such as PM2.5 and PM10, keeping fresh air within your grasp.\n");
lv_label_set_recolor(homepage,true);
lv_obj_align(homepage,LV_ALIGN_CENTER,0,-40);
lv_obj_set_style_text_font(homepage,&lv_font_montserrat_18,LV_STATE_DEFAULT);
lv_obj_set_style_text_align(homepage,LV_TEXT_ALIGN_CENTER,LV_STATE_DEFAULT);
redirct_set(0);
redirct_set(1);
lv_label_set_text(redirct_value[0],"waring");
lv_label_set_text(redirct_value[1],"display");
}
//调用主函数
void aqi_lvgl(void)
{
air_dispaly(); //第一页
}