你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【福利三:逢7发帖赢大礼】lv_timer和BME680实现温度、湿度、气压数据读取

[复制链接]
donatello1996 发布时间:2026-7-22 18:00
       LVGL默认是使用回调函数进行事件触发的,比如按下屏幕中的按键,或者是某个控件的值发生变化之类的,而如果想要使用LVGL去连续不断地显示某样东西,那就需要用到lv_timer即定时器控件,这帖我将用lv_timer来实现对BME680模块的温度、湿度、气压数据读取。
       首先需要在LVGL程序开始的时候注册定时器回调函数:
37.JPG
void lv_example_tileview(void)
{
        lv_obj_t *tileview = lv_tileview_create(lv_scr_act());
        lv_timer_t * timer1;
        timer1 = lv_timer_create(my_timer1 , 100000 , NULL);
。。。
}


第二个参数为定时器溢出时间间隔,数字越大间隔越大。然后需要在定时器回调函数里面写上具体的实现:
static void my_timer1(lv_timer_t * timer)
{
。。。
}


BME680是一个使用I2C通信总线的模块,非常典型也非常常用,采集的大气压数据非常准确,跟气象台数据基本一致,算是BMP280的上位替代,BME680的初始化代码比较特别,是使用回调函数注册相关参数的,比如I2C读,I2C写,Delay函数,器件地址等,我手上这个模块的器件地址是0x77:
39.JPG 38.JPG
#define BME680_I2C_ADDR_SECONDARY        UINT8_C(0x77)


        gas_sensor.dev_id = BME680_I2C_ADDR_SECONDARY;
        gas_sensor.intf = BME680_I2C_INTF;
        gas_sensor.read = user_i2c_read;
        gas_sensor.write = user_i2c_write;
        gas_sensor.delay_ms = Delay_ms;
        
        if(bme680_init(&gas_sensor) != BME680_OK)
        {
                printf("Error al inicializar el sensor.\n");
        }
        printf("bme680_init.\n");


I2C就用现成的模拟I2C代码即可:
40.JPG
uint8_t Fake_I2C_Read_Reg_Addr(uint8_t dev_addr , uint8_t reg)
{
        uint8_t res;
        Fake_I2C_Start();
        Fake_I2C_Send_Byte((dev_addr << 1) | 0);
        Fake_I2C_Wait_Ack();
        Fake_I2C_Send_Byte(reg);
        Fake_I2C_Wait_Ack();
        Fake_I2C_Start();
        Fake_I2C_Send_Byte((dev_addr << 1) | 1);
        Fake_I2C_Wait_Ack();
        res = Fake_I2C_Read_Byte(0);
        Fake_I2C_Stop();
        return res;               
}


void Fake_I2C_Read_Reg_Datas(uint8_t dev_addr , uint8_t reg , uint8_t data_len , uint8_t data[])
{
        while(data_len)
        {
                *data = Fake_I2C_Read_Reg_Addr(dev_addr , reg++);
                data ++;
                data_len --;
        }        
        Delay_ms(1);
}


void Fake_I2C_Write_Reg_Addr_Data(uint8_t dev_addr , uint8_t reg , uint8_t data)
{
        Fake_I2C_Start();
        Fake_I2C_Send_Byte((dev_addr << 1) | 0);
        Fake_I2C_Wait_Ack();
        Fake_I2C_Send_Byte(reg);
        Fake_I2C_Wait_Ack();
        Fake_I2C_Send_Byte(data);
        Fake_I2C_Wait_Ack();
        Fake_I2C_Stop();
}


void Fake_I2C_Write_Reg_Addr_Datas(uint8_t dev_addr , uint8_t reg , uint8_t data_len , uint8_t data[])
{
        int i;
        Fake_I2C_Start();
        Fake_I2C_Send_Byte((dev_addr << 1) | 0);
        Fake_I2C_Wait_Ack();
        Fake_I2C_Send_Byte(reg);
        Fake_I2C_Wait_Ack();
        for(i = 0 ; i < data_len ; i++)
        {
                Fake_I2C_Send_Byte(data);
                Fake_I2C_Wait_Ack();
        }
  Fake_I2C_Stop();
        Delay_ms(1);
}


int8_t user_i2c_write(uint8_t dev_id , uint8_t reg_addr , uint8_t *reg_data , uint16_t len)
{
        Fake_I2C_Write_Reg_Addr_Datas(0x77 , reg_addr , len , reg_data);
        return 0;
}


int8_t user_i2c_read(uint8_t dev_id , uint8_t reg_addr , uint8_t *reg_data , uint16_t len)
{
        Fake_I2C_Read_Reg_Datas(0x77 , reg_addr , len , reg_data);
        return 0;
}


在主界面中添加tileview,可以实现类似智能手机的滑屏效果:


        lv_obj_t *tileview = lv_tileview_create(lv_scr_act());


        lv_obj_t *tile_1 = lv_tileview_add_tile( tileview, 0 , 0, LV_DIR_LEFT | LV_DIR_RIGHT );
        lv_obj_t *tile_2 = lv_tileview_add_tile( tileview, 1 , 0, LV_DIR_LEFT | LV_DIR_RIGHT );


这样,就可以单独用一个页面去显示BME680的传感器读数,而其它页面实现别的功能了,非常方便。用Bar(进度条)和Label去动态显示读数:


        font = &lv_font_montserrat_24;
        lv_obj_t* label = lv_label_create(btn_speed_up);
        lv_obj_set_style_text_font(label , font , LV_PART_MAIN);
        
        label_bme680_temp = lv_label_create(tile_1);
        lv_obj_set_style_text_font(label_bme680_temp , font , LV_STATE_DEFAULT);
        lv_obj_align(label_bme680_temp , LV_ALIGN_CENTER, 0 , -220);
        
        bar_bme680_temp = lv_bar_create(tile_1);
  lv_obj_align(bar_bme680_temp , LV_ALIGN_CENTER, 0 , -180);
        lv_obj_set_size(bar_bme680_temp , 260 , 20);
        
        label_bme680_pres = lv_label_create(tile_1);
        lv_obj_set_style_text_font(label_bme680_pres , font , LV_STATE_DEFAULT);
        lv_obj_align(label_bme680_pres , LV_ALIGN_CENTER, 0 , -120);
        
        bar_bme680_pres = lv_bar_create(tile_1);
  lv_obj_align(bar_bme680_pres , LV_ALIGN_CENTER, 0 , -80);
        lv_obj_set_size(bar_bme680_pres , 260 , 20);
        
        label_bme680_humi = lv_label_create(tile_1);
        lv_obj_set_style_text_font(label_bme680_humi , font , LV_STATE_DEFAULT);
        lv_obj_align(label_bme680_humi , LV_ALIGN_CENTER, 0 , -20);
        
        bar_bme680_humi = lv_bar_create(tile_1);
  lv_obj_align(bar_bme680_humi , LV_ALIGN_CENTER, 0 , 20);
        lv_obj_set_size(bar_bme680_humi , 260 , 20);


看看演示效果:

用手捂着BME680,会看到温度读数升高,松开温度则降下来。

收藏 评论0 发布时间:2026-7-22 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版