【目标实现】
瑞萨RA8D1LVGL/LWIP开发板获取家里的环境信息,实现lvgl展示。
【硬件】
1、CPKCOR-RA8D1B核心板
2、拓展板(CPKEXP-EKRA8X1)
3、STCC4二氧化碳环境监测模组
【硬件连接】
STCC4采用IIC接口。
在开发板上,有I2C的接口,通过原理图查找,以IIC1为接口。

但是这个接口我没有成本的插头,因此改为CEU扩展接口的是第3、4脚来接:

【软件安装思路】
实现两个freertos任务,一个运行lvgl,另一个运行stcc4采集任务。
lvgl的移植,在前面已要实现过来了,这次主要分享如何实现stcc4的采集
【RSCA的配置】
如下图所示,在stack中添加iic:

填入stcc4的地址,以及回调函数。保存后重新生成代码。
【代码实现】
1、移植stcc4的代码,在其官网下载到基于c的代码,将其复制到工程。

2、修改sensiron_i2c_hal.c
#include "sensirion_i2c_hal.h"
#include "sensirion_common.h"
#include "sensirion_config.h"
#include "FreeRTOS.h"
#include "task.h"
#include "hal_data.h"
#include "common_utils.h"
/*
* INSTRUCTIONS
* ============
*
* Implement all functions where they are marked as IMPLEMENT.
* Follow the function specification in the comments.
*/
extern iic_master_instance_ctrl_t g_i2c_master0_ctrl;
/* global variable */
volatile i2c_master_event_t i2c_master_event;
/* User defined functions */
static fsp_err_t wait_for_i2c_event (i2c_master_event_t event);
/**
* Select the current i2c bus by index.
* All following i2c operations will be directed at that bus.
*
* THE IMPLEMENTATION IS OPTIONAL ON SINGLE-BUS SETUPS (all sensors on the same
* bus)
*
* @param bus_idx Bus index to select
* @returns 0 on success, an error code otherwise
*/
int16_t sensirion_i2c_hal_select_bus(uint8_t bus_idx) {
/* TODO:IMPLEMENT or leave empty if all sensors are located on one single
* bus
*/
FSP_PARAMETER_NOT_USED(bus_idx);
return 0;
}
/**
* Initialize all hard- and software components that are needed for the I2C
* communication.
*/
void sensirion_i2c_hal_init(void) {
R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
}
/**
* Release all resources initialized by sensirion_i2c_hal_init().
*/
void sensirion_i2c_hal_free(void) {
/* TODO:IMPLEMENT or leave empty if no resources need to be freed */
R_IIC_MASTER_Close(&g_i2c_master0_ctrl);
}
/**
* Execute one read transaction on the I2C bus, reading a given number of bytes.
* If the device does not acknowledge the read command, an error shall be
* returned.
*
* @param address 7-bit I2C address to read from
* @param data pointer to the buffer where the data is to be stored
* @param count number of bytes to read from I2C and store in the buffer
* @returns 0 on success, error code otherwise
*/
int8_t sensirion_i2c_hal_read(uint8_t address, uint8_t* data, uint8_t count) {
FSP_PARAMETER_NOT_USED(address);
int8_t err = FSP_SUCCESS;
/* Read data back from the I2C slave */
i2c_master_event = I2C_MASTER_EVENT_ABORTED;
R_IIC_MASTER_Read(&g_i2c_master0_ctrl, data, count, false);
/* Wait until write receive complete */
err = wait_for_i2c_event (I2C_MASTER_EVENT_RX_COMPLETE);
return err;
}
/**
* Execute one write transaction on the I2C bus, sending a given number of
* bytes. The bytes in the supplied buffer must be sent to the given address. If
* the slave device does not acknowledge any of the bytes, an error shall be
* returned.
*
* @param address 7-bit I2C address to write to
* @param data pointer to the buffer containing the data to write
* @param count number of bytes to read from the buffer and send over I2C
* @returns 0 on success, error code otherwise
*/
int8_t sensirion_i2c_hal_write(uint8_t address, const uint8_t* data,
uint8_t count) {
FSP_PARAMETER_NOT_USED(address);
int8_t err = FSP_SUCCESS;
/* write data to the i2c slave device */
i2c_master_event = I2C_MASTER_EVENT_ABORTED;
err = R_IIC_MASTER_Write (&g_i2c_master0_ctrl, data, count, false);
// APP_ERR_RETURN(err, " ** IIC MASTER_Write API FAILED ** \r\n");
/* Wait until write transmission complete */
err = wait_for_i2c_event (I2C_MASTER_EVENT_TX_COMPLETE);
// APP_ERR_RETURN(err, " ** I2C master event timeout ** \r\n");
return err;
}
/**
* Sleep for a given number of microseconds. The function should delay the
* execution for at least the given time, but may also sleep longer.
*
* Despite the unit, a <10 millisecond precision is sufficient.
*
* @param useconds the sleep time in microseconds
*/
void sensirion_i2c_hal_sleep_usec(uint32_t useconds) {
/* TODO:IMPLEMENT */
if (useconds < 1000) {
vTaskDelay(1);
} else {
vTaskDelay(useconds/1000);
}
}
/*******************************************************************************************************************//**
* @brief Callback functions for i2c master interrupts
*
* @param[in] p_args Callback arguments
* @retval none
**********************************************************************************************************************/
void i2c_master_callback(i2c_master_callback_args_t *p_args)
{
if (NULL != p_args)
{
i2c_master_event = p_args->event;
}
}
/*******************************************************************************************************************//**
* @brief This function is used to Wait for i2c event.
*
* @param[in] event : Expected events
* @retval FSP_SUCCESS : Upon successful operation, otherwise: failed
**********************************************************************************************************************/
static fsp_err_t wait_for_i2c_event (i2c_master_event_t event)
{
uint32_t timeout = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_ICLK) / 10;
while (timeout-- && (i2c_master_event != event))
{
;
}
return timeout ? FSP_SUCCESS : FSP_ERR_TIMEOUT;
}修改代码主的思路是添加iic的回调函数,实时提取iic的回调事件。
在检测static fsp_err_t wait_for_i2c_event (i2c_master_event_t event)
在这个函数中,加入超过检测。
按照RA的读写代码添加读取与写入的函数即可。
2、设计简单的展示界面,使用guiguider设计222*480的界面添加co2、temp、humi用来显示二氧化碳浓度,温度,湿度值:

生成工程代码后,将其添加到src/ui下面。
3、修改lvgl_thread_entry.c内容如下:
#include "lvgl_thread.h"
#include <stdlib.h>
#include "board_init.h"
#include "ui/events_init.h"
#include "ui/gui_guider.h"
#include "ui/custom.h"
void vApplicationTickHook(void)
{
lv_tick_inc(1);
}
lv_ui guider_ui;
/* LVGLThread entry function */
/* pvParameters contains TaskHandle_t */
void lvgl_thread_entry(void *pvParameters)
{
FSP_PARAMETER_NOT_USED (pvParameters);
lv_init();
board_init();
setup_ui(&guider_ui);
events_init(&guider_ui);
custom_init(&guider_ui);
lv_timer_handler();
/* TODO: add your own code here */
while (1)
{
lv_timer_handler();
vTaskDelay (5);
}
}4、在blink_entry.c中添加初始化stcc4,并定时显示环境参数:
/*
* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "blinky_thread.h"
#include "common_utils.h"
#include "ui/stcc4_i2c.h"
#include "ui/sensirion_i2c_hal.h"
#include "lvgl.h"
#include "ui/gui_guider.h"
extern lv_ui guider_ui;
/* Blinky Thread entry function */
void blinky_thread_entry (void * pvParameters)
{
FSP_PARAMETER_NOT_USED(pvParameters);
uint32_t product_id;
uint64_t serial_number;
fsp_err_t err = FSP_SUCCESS;
uint8_t sttc4_sta = 0;
int erro;
uint16_t co2_concentration_raw;
uint16_t temperature_raw;
uint16_t relative_humidity_raw;
uint8_t sensor_status_raw;
float hum, temp;
char buf[32];
sensirion_i2c_hal_init();
erro = stcc4_get_product_id(&product_id, &serial_number);
if(erro != 0)
{
APP_PRINT("stcc4 read Id erro\n");
}
else
{
APP_PRINT("stcc4 id:%d\n",product_id);
sttc4_sta = 1;
}
vTaskDelay(2000);
if(sttc4_sta ==1)
{
erro = stcc4_start_continuous_measurement();
if(erro != 0)
{
sttc4_sta = 0;
}
vTaskDelay(1000);
}
while (1)
{
erro = stcc4_read_measurement_raw(&co2_concentration_raw,
&temperature_raw,
&relative_humidity_raw,
&sensor_status_raw);
if (erro == 0) {
// 计算实际值
hum = (25.0f * relative_humidity_raw) / 13107.0f - 6.0f;
temp = (175.0f * temperature_raw) / 65535.0f - 45.0f;
// 更新 CO2 Label
lv_label_set_text_fmt(guider_ui.screen_label_co2, "%d ppm", co2_concentration_raw);
// 更新 温度 Label
lv_label_set_text_fmt(guider_ui.screen_label_temp, "%d C", (int)temp);
// 更新 湿度 Label
lv_label_set_text_fmt(guider_ui.screen_label_humi, "%d%%", (int)hum);
} else {
// 可选:显示错误信息
lv_label_set_text(guider_ui.screen_label_co2, "-- ppm");
lv_label_set_text(guider_ui.screen_label_temp, "-- °C");
lv_label_set_text(guider_ui.screen_label_humi, "-- %");
}
vTaskDelay(2000);
}
}【测试】
编译下载后,连接STCC4模组,获取环境信息如下:

【总结】
瑞萨的RASC图形化的配置工具非常方面工程的配置。
【感谢】
非常感谢@枫雪天 大佬的指导,此次工程是学习他的freertos+lvgl工程的基础上创建出来的。
我要赚赏金
