背景
9月份逛某论坛时,发现一个有意思的传感器RRH62000,此传感器号称可以监控室内大部分空气质量,瞬间就想到了多年前新家入住时特意买的甲醛监测仪,如果自己能做一个这样的设备,也是挺有意思的一件事。当时头脑一热,就申请了。到11月时,突然收到邮件说选中了,就赶紧拿回来把玩起来。
RRH62000目前释放出来的资料不多,但是搜索github上发现,其实瑞萨的fsp5.6已经有上传RRH62000的代码了(具体可以在链接中搜索RRH62000:Releases · renesas/fsp),也就是说,如果要适配RRH62000,如果使用瑞萨主控,基于目前rtthread上瑞萨的代码逻辑,我们需要把板卡fsp升级到5.6,之后开启rrh62000,再将rrh62000对接到rtthread的传感器框架中,便能够实现适配。
但是呢,通过查阅传感器部分的代码,我决定暂时放弃这一操作,原因是我并不认为目前fsp上的外围器件框架逻辑符合产品设计的需求。因为目前fsp上的rrh62000框架,I2C是独占式的,而实际项目设计中,I2C很少独占一路,而是多种器件共用一路I2C。
硬件配置
由于RRH62000独特的架构设计(供电需要5V,但通信却使用3.3V),我手头上能直接供5V并操作3.3V的板子并不多,只有野火的启明6M5,因此就用启明6M5来做RRH6200的适配。
I2C通信接口
启明6M5的typec端口上的串口可以配置成I2C1,如下图:
在调试时,仅仅需要将J35的跳冒拿开,并将RRH62000的I2C口接到此处即可。
供电部分
启明6M5的J29座子上有引出VCC_5V和GND,因此可以将供电引至该口。
软件设置
选定了硬件接口,那剩下的就是FSP的设置了,由于之前我已经把启明6M5大部分功能配好并合并到github主线仓库了,因此这里的配置,仅仅是通过FSP配置对应的硬件接口即可。
串口部分
FSP修改
rtt主线上目前配置的串口和I2C1所使用的接口冲突,因此我将此路串口切换至JTAG上的串口,以便调试。具体配置如下:
删除stacks中的uart4配置后,依次进行以下配置:
这部分配置完毕后,点击Generate Project Content生成配置。
menuconfig配置
fsp已经把uart4关闭,并打开了UART2,但是目前rtt默认的配置还是在uart4上,此时只需要进入menuconfig中,打开uart2,关闭uart4,并将调试口更换至uart2即可。具体修改如下:
在emu中输入menuconfig并回车,进行以下配置:
选择完毕后保存,并输入 scons --target=mdk5 生成新工程。此时编译运行,可发现finsh串口变成了uart2。
I2C1部分
FSP修改
I2C1部分和配置类似,具体配置方法如下:
之后点击Generate Project Content便可生成I2C1相关的配置。
menuconfig配置
同样的,虽然FSP已经启用了I2C1,但是rtt目前并由没启用I2C1,此时需要在menuconfig中启用I2C1,启用方法同uart,但操作位置有细微差异,具体差异如下:
选择完毕后保存,并输入 scons --target=mdk5 生成新工程。
至此,I2C1也被添加至工程中。
传感器代码添加
文件添加
所有驱动文件都按惯例,全部添加至bsp\renesas\libraries\HAL_Drivers\中,因为瑞萨所有的驱动看起来都是加在此处。
rrh62000.c
#include "rrh62000.h" #define RRH62000_ADDR 0x69 /* Definitions of Timeout */ #define RM_RRH62000_TIMEOUT (100) /* Definitions of Wait Time */ #define RM_RRH62000_WAIT_TIME_1000 (1000) /* Definitions of Retry max counts */ #define RM_RRH62000_RETRY_MAX_COUNTS (5) #define RM_RRH62000_RETRY_ZMOD_CLEANING_COUNTS (60 + 10) // ZMOD cleaning time (60s) + buffer (10s) /* Definitions of Command */ #define RM_RRH62000_COMMAND_READ (0x00) #define RM_RRH62000_COMMAND_DATA (0x40) #define RM_RRH62000_COMMAND_RESET (0x52) #define RM_RRH62000_COMMAND_MAVE (0x53) #define RM_RRH62000_COMMAND_SPEEDFAN (0x63) #define RM_RRH62000_COMMAND_ARGVER (0x73) #define RM_RRH62000_COMMAND_CSTATUS (0x74) #define RM_RRH62000_COMMAND_FWVAR (0x75) /* Definitions of Reset */ #define RM_RRH62000_RESET_VALUE (0x81) /* Definitions of Cleaning Status */ #define RM_RRH62000_ZMOD_CLEAN_NOT_COMPLETE (0x00) #define RM_RRH62000_ZMOD_CLEAN_COMPLETE (0x01) /* Definitions of data size */ #define RM_RRH62000_LEN_MEASUREMENT_DATA (37) /* Definitions of Mask */ #define RM_RRH62000_STATUS_MASK (0x01) #define RM_RRH62000_HIGH_CONCENTRATION_MASK (0x01) #define RM_RRH62000_DUST_ACCUMULATION_MASK (0x02) #define RM_RRH62000_FAN_SPEED_MASK (0x04) #define RM_RRH62000_FAN_MASK (0x08) /* Definitions of Position */ #define RM_RRH62000_POSITION_STATUS (0) #define RM_RRH62000_POSITION_NC_0P3 (2) #define RM_RRH62000_POSITION_TEMPERATURE (24) #define RM_RRH62000_POSITION_ECO2 (30) #define RM_RRH62000_POSITION_IAQ (32) /* Definitions of Calculation */ #define RM_RRH62000_CALC_CRC_INITIAL_VALUE (0xFF) #define RM_RRH62000_CALC_CRC_DATA_LENGTH (36) #define RM_RRH62000_CALC_DATA_STEP (2) #define RM_RRH62000_CALC_CRC_8BITS_LENGTH (8) #define RM_RRH62000_CACL_CRC_0X80 (0x80) #define RM_RRH62000_CACL_CRC_MASK_MSB (0x80) #define RM_RRH62000_CALC_CRC_POLYNOMIAL (0x31) #define RM_RRH62000_CALC_CRC_FINAL_XOR (0x00) #define RM_RRH62000_CALC_DECIMAL_VALUE_100 (100) #define RM_RRH62000_CALC_DECIMAL_VALUE_10 (10) /* Definitions of Shift */ #define RM_RRH62000_SHIFT_24 (24) #define RM_RRH62000_SHIFT_16 (16) #define RM_RRH62000_SHIFT_8 (8) static rt_err_t rrh62000_read(struct rt_i2c_bus_device *bus, uint8_t reg, uint8_t *data, uint16_t len) { rt_uint8_t tmp = reg; struct rt_i2c_msg msgs[2]; msgs[0].addr = RRH62000_ADDR; /* Slave address */ msgs[0].flags = RT_I2C_WR; /* Write flag */ msgs[0].buf = &tmp; /* Slave register address */ msgs[0].len = 1; /* Number of bytes sent */ msgs[1].addr = RRH62000_ADDR; /* Slave address */ msgs[1].flags = RT_I2C_RD; /* Read flag */ msgs[1].buf = data; /* Read data pointer */ msgs[1].len = len; /* Number of bytes read */ if (rt_i2c_transfer(bus, msgs, 2) != 2) { return -RT_ERROR; } return RT_EOK; } static rt_err_t rrh62000_write(struct rt_i2c_bus_device *bus, uint8_t reg, uint8_t *data, uint16_t len) { struct rt_i2c_msg msgs[2]; uint8_t data1[5]; uint16_t i; data1[0] = reg; for (i = 0; i < len; i++) { data1[i + 1] = data[i]; } msgs[0].addr = RRH62000_ADDR; /* Slave address */ msgs[0].flags = RT_I2C_WR; /* Write flag */ msgs[0].buf = data1; /* Slave register address */ msgs[0].len = len + 1; /* Number of bytes sent */ if (rt_i2c_transfer(bus, msgs, 1) != 1) { return -RT_ERROR; } return RT_EOK; } static rt_err_t rm_rrh62000_crc_execute (const uint8_t * const p_raw_data) { uint8_t crc; const uint8_t * p_input_data; uint8_t i; uint8_t j; /* Set pointer to input data */ p_input_data = &p_raw_data[0]; /* Set initial value */ crc = RM_RRH62000_CALC_CRC_INITIAL_VALUE; /* Execute CRC */ for (i = 0; i < RM_RRH62000_CALC_CRC_DATA_LENGTH; i++) { /* Calculate XOR with input value */ crc ^= *p_input_data; for (j = 0; j < RM_RRH62000_CALC_CRC_8BITS_LENGTH; j++) { if (RM_RRH62000_CACL_CRC_0X80 == (crc & RM_RRH62000_CACL_CRC_MASK_MSB)) { /* If MSB is 1, calculate XOR with the polynomial. */ crc = (uint8_t) (crc << 1) ^ RM_RRH62000_CALC_CRC_POLYNOMIAL; } else { crc <<= 1; } } p_input_data++; } /* Final XOR */ crc ^= RM_RRH62000_CALC_CRC_FINAL_XOR; if(p_raw_data[RM_RRH62000_CALC_CRC_DATA_LENGTH] == crc) { return RT_EOK; } else { return -RT_ERROR; } } static rt_err_t RM_RRH62000_DataCalculate (uint8_t * p_raw_data, struct rrh62000_data *p_rrh62000_data) { rt_err_t err = RT_EOK; rt_uint32_t tmp_u32; rm_air_sensor_single_data_t * p_sensor_data; rt_uint32_t position; /* Execute CRC */ err = rm_rrh62000_crc_execute(p_raw_data); if(err != RT_EOK) { return err; } /* Set status data */ p_rrh62000_data->status = (uint32_t) (((uint32_t) p_raw_data[1] << RM_RRH62000_SHIFT_8) | (uint32_t) p_raw_data[0]); /* Set measurement results */ p_sensor_data = &p_rrh62000_data->nc_0p3; for (position = RM_RRH62000_POSITION_NC_0P3; position < RM_RRH62000_LEN_MEASUREMENT_DATA; position += RM_RRH62000_CALC_DATA_STEP) { /* Calculate sensor data from measurement results (big-endian). */ tmp_u32 = (uint32_t) (((uint32_t) p_raw_data[position] << RM_RRH62000_SHIFT_8) | (uint32_t) p_raw_data[position + 1]); if (RM_RRH62000_POSITION_TEMPERATURE > position) { /* NC_x and PMx_x data. One decimal place. */ p_sensor_data->integer_part = tmp_u32 / RM_RRH62000_CALC_DECIMAL_VALUE_10; p_sensor_data->decimal_part = tmp_u32 % RM_RRH62000_CALC_DECIMAL_VALUE_10; } else if ((RM_RRH62000_POSITION_ECO2 > position) || (RM_RRH62000_POSITION_IAQ == position)) { /* Temperature, humidity, TVOC and IAQ data. Two decimal places. */ p_sensor_data->integer_part = tmp_u32 / RM_RRH62000_CALC_DECIMAL_VALUE_100; p_sensor_data->decimal_part = tmp_u32 % RM_RRH62000_CALC_DECIMAL_VALUE_100; } else { /* eCO2 and Relative IAQ data. These data does not have a decimal part. */ p_sensor_data->integer_part = tmp_u32; p_sensor_data->decimal_part = 0; } p_sensor_data++; } return RT_EOK; } rt_err_t rrh62000_read_measured_value(struct rt_i2c_bus_device *bus, struct rrh62000_data *data) { rt_uint8_t buf[37]; rt_uint32_t len = 37; if(rrh62000_read(bus, RM_RRH62000_COMMAND_READ, buf, len) != RT_EOK) { return -RT_ERROR; } return RM_RRH62000_DataCalculate(buf, data); } rt_err_t rrh62000_read_data_status(struct rt_i2c_bus_device *bus, rt_bool_t *isDataReady) { rt_uint8_t buf[1]; if(rrh62000_read(bus, RM_RRH62000_COMMAND_DATA, buf, 1) != RT_EOK) { return -RT_ERROR; } *isDataReady = buf[0]; return RT_EOK; } rt_err_t rrh62000_sleep_set(struct rt_i2c_bus_device *bus, rt_bool_t isSleep) { rt_uint8_t buf[1]; if(isSleep) { buf[0] = 0x00; } else { buf[0] = 0x80; } if(rrh62000_write(bus, 0x50, buf, 1) != RT_EOK) { return -RT_ERROR; } return RT_EOK; } rt_err_t rrh62000_sleep_get(struct rt_i2c_bus_device *bus, rt_bool_t *isSleep) { rt_uint8_t buf[1]; if(rrh62000_read(bus, 0x50, buf, 1) != RT_EOK) { return -RT_ERROR; } if(buf[0]) { *isSleep = 0; } else { *isSleep = 1; } return RT_EOK; } rt_err_t rrh62000_start_dust_cleaning(struct rt_i2c_bus_device *bus) { rt_uint8_t buf[1] = {0x01}; if(rrh62000_write(bus, 0x51, buf, 1) != RT_EOK) { return -RT_ERROR; } return RT_EOK; } rt_err_t rrh62000_reset(struct rt_i2c_bus_device *bus) { rt_uint8_t buf[1] = {0x81}; if(rrh62000_write(bus, RM_RRH62000_COMMAND_RESET, buf, 1) != RT_EOK) { return -RT_ERROR; } return RT_EOK; } rt_err_t rrh62000_moving_average_set(struct rt_i2c_bus_device *bus, uint8_t time) { rt_uint8_t buf[1]; if(time > 60) { time = 60; } else if(time < 1) { time = 1; } buf[0] = time; if(rrh62000_write(bus, RM_RRH62000_COMMAND_MAVE, buf, 1) != RT_EOK) { return -RT_ERROR; } return RT_EOK; } rt_err_t rrh62000_moving_average_get(struct rt_i2c_bus_device *bus, uint8_t *time) { rt_uint8_t buf[1]; if(rrh62000_read(bus, RM_RRH62000_COMMAND_MAVE, buf, 1) != RT_EOK) { return -RT_ERROR; } *time = buf[0]; return RT_EOK; } rt_err_t rrh62000_clean_interval_time_set(struct rt_i2c_bus_device *bus, uint16_t time) { rt_uint8_t buf[1]; if(time > 60480) { time = 60480; } buf[0] = (time >> 8); if(rrh62000_write(bus, 0x5A, buf, 1) != RT_EOK) { return -RT_ERROR; } buf[0] = (time & 0x00FF); if(rrh62000_write(bus, 0x5B, buf, 1) != RT_EOK) { return -RT_ERROR; } return RT_EOK; } rt_err_t rrh62000_clean_interval_time_get(struct rt_i2c_bus_device *bus, uint16_t *time) { rt_uint8_t buf[2]; if(rrh62000_read(bus, 0x5A, buf, 1) != RT_EOK) { return -RT_ERROR; } if(rrh62000_read(bus, 0x5B, buf + 1, 1) != RT_EOK) { return -RT_ERROR; } *time = ((uint16_t)buf[0] << 8) + buf[1]; return RT_EOK; } rt_err_t rrh62000_auto_clean_time_set(struct rt_i2c_bus_device *bus, uint8_t time) { rt_uint8_t buf[1]; if(time > 60) { time = 60; } buf[0] = time; if(rrh62000_write(bus, 0x5C, buf, 1) != RT_EOK) { return -RT_ERROR; } return RT_EOK; } rt_err_t rrh62000_auto_clean_time_get(struct rt_i2c_bus_device *bus, uint8_t *time) { rt_uint8_t buf[1]; if(rrh62000_read(bus, 0x5C, buf, 1) != RT_EOK) { return -RT_ERROR; } *time = buf[0]; return RT_EOK; } rt_err_t rrh62000_fan_speed_set(struct rt_i2c_bus_device *bus, uint8_t speed) { rt_uint8_t buf[1]; if(speed > 100) { speed = 100; } else if(speed < 60) { speed = 60; } buf[0] = speed; if(rrh62000_write(bus, RM_RRH62000_COMMAND_SPEEDFAN, buf, 1) != RT_EOK) { return -RT_ERROR; } return RT_EOK; } rt_err_t rrh62000_fan_speed_get(struct rt_i2c_bus_device *bus, uint8_t *speed) { rt_uint8_t buf[1]; if(rrh62000_read(bus, RM_RRH62000_COMMAND_SPEEDFAN, buf, 1) != RT_EOK) { return -RT_ERROR; } *speed = buf[0]; return RT_EOK; } rt_err_t rrh62000_read_mox_resistance(struct rt_i2c_bus_device *bus, uint32_t *data) { rt_uint8_t buf[4]; if(rrh62000_read(bus, 0x71, buf, 4) != RT_EOK) { return -RT_ERROR; } *data = (uint32_t)buf[0] << 24; *data += (uint32_t)buf[1] << 16; *data += (uint32_t)buf[2] << 8; *data += (uint32_t)buf[3] << 0; return RT_EOK; } rt_err_t rrh62000_read_uid(struct rt_i2c_bus_device *bus, struct rrh62000_uid *data) { rt_uint8_t buf[6]; if(rrh62000_read(bus, 0x72, buf, 6) != RT_EOK) { return -RT_ERROR; } rt_memcpy(&data->uid, buf, 6); return RT_EOK; } rt_err_t rrh62000_read_algoritm_verison(struct rt_i2c_bus_device *bus, struct rrh62000_algoversion *data) { rt_uint8_t buf[3]; if(rrh62000_read(bus, RM_RRH62000_COMMAND_ARGVER, buf, 3) != RT_EOK) { return -RT_ERROR; } data->major = buf[0]; data->minor = buf[1]; data->patch = buf[2]; return RT_EOK; } rt_err_t rrh62000_read_TVOC_sensor_clean_status(struct rt_i2c_bus_device *bus, rt_bool_t *isComplete) { rt_uint8_t buf[1]; if(rrh62000_read(bus, RM_RRH62000_COMMAND_CSTATUS, buf, 1) != RT_EOK) { return -RT_ERROR; } *isComplete = buf[0]; return RT_EOK; } rt_err_t rrh62000_read_firmware_verison(struct rt_i2c_bus_device *bus, struct rrh62000_firmwareversion *data) { rt_uint8_t buf[2]; if(rrh62000_read(bus, RM_RRH62000_COMMAND_FWVAR, buf, 2) != RT_EOK) { return -RT_ERROR; } data->major = buf[0]; data->minor = buf[1]; return RT_EOK; }
rrh_62000.h
#include <rtdevice.h> #include <rtthread.h> typedef struct st_rm_air_sensor_single_data { uint32_t integer_part; ///< Integer part of sensor data. uint32_t decimal_part; ///< Decimal part of sensor data. } rm_air_sensor_single_data_t; /** AIR SENSOR data block */ struct rrh62000_data { uint32_t status; rm_air_sensor_single_data_t nc_0p3; ///< Number concentration of particle size 0.3 um - 10 um [1/cm3] rm_air_sensor_single_data_t nc_0p5; ///< Number concentration of particle size 0.5 um - 10 um [1/cm3] rm_air_sensor_single_data_t nc_1; ///< Number concentration of particle size 1 um - 10 um [1/cm3] rm_air_sensor_single_data_t nc_2p5; ///< Number concentration of particle size 2.5 um - 10 um [1/cm3] rm_air_sensor_single_data_t nc_4; ///< Number concentration of particle size 4 um - 10 um [1/cm3] rm_air_sensor_single_data_t pm1_1; ///< Mass concentration of particle size 0.3 um - 1 um with reference to KCl particle [um/cm3] rm_air_sensor_single_data_t pm2p5_1; ///< Mass concentration of particle size 0.3 um - 2.5 um with reference to KCl particle [um/cm3] rm_air_sensor_single_data_t pm10_1; ///< Mass concentration of particle size 0.3 um - 10 um with reference to KCl particle [um/cm3] rm_air_sensor_single_data_t pm1_2; ///< Mass concentration of particle size 0.3 um - 1 um with reference to cigarette smoke [um/cm3] rm_air_sensor_single_data_t pm2p5_2; ///< Mass concentration of particle size 0.3 um - 2.5 um with reference to cigarette smoke [um/cm3] rm_air_sensor_single_data_t pm10_2; ///< Mass concentration of particle size 0.3 um - 10 um with reference to cigarette smoke [um/cm3] rm_air_sensor_single_data_t temperature; ///< Temperature [Celsius] rm_air_sensor_single_data_t humidity; ///< Humidity [%RH] rm_air_sensor_single_data_t tvoc; ///< Total volatile organic compounds (TVOC) concentrations [mg/m3] rm_air_sensor_single_data_t eco2; ///< Estimated carbon dioxide (eCO2) level [ppm] rm_air_sensor_single_data_t iaq; ///< Indoor Air Quality level according to UBA rm_air_sensor_single_data_t rel_iaq; ///< Relative IAQ }; rt_err_t rrh62000_read_measured_value(struct rt_i2c_bus_device *bus, struct rrh62000_data *data); rt_err_t rrh62000_read_data_status(struct rt_i2c_bus_device *bus, rt_bool_t *isDataReady); rt_err_t rrh62000_sleep_set(struct rt_i2c_bus_device *bus, rt_bool_t isSleep); rt_err_t rrh62000_sleep_get(struct rt_i2c_bus_device *bus, rt_bool_t *isSleep); rt_err_t rrh62000_start_dust_cleaning(struct rt_i2c_bus_device *bus); rt_err_t rrh62000_reset(struct rt_i2c_bus_device *bus); rt_err_t rrh62000_moving_average_set(struct rt_i2c_bus_device *bus, uint8_t time); rt_err_t rrh62000_moving_average_get(struct rt_i2c_bus_device *bus, uint8_t *time); rt_err_t rrh62000_clean_interval_time_set(struct rt_i2c_bus_device *bus, uint16_t time); rt_err_t rrh62000_clean_interval_time_get(struct rt_i2c_bus_device *bus, uint16_t *time); rt_err_t rrh62000_auto_clean_time_set(struct rt_i2c_bus_device *bus, uint8_t time); rt_err_t rrh62000_auto_clean_time_get(struct rt_i2c_bus_device *bus, uint8_t *time); rt_err_t rrh62000_fan_speed_set(struct rt_i2c_bus_device *bus, uint8_t speed); rt_err_t rrh62000_fan_speed_get(struct rt_i2c_bus_device *bus, uint8_t *speed); rt_err_t rrh62000_read_mox_resistance(struct rt_i2c_bus_device *bus, uint32_t *data); struct rrh62000_uid{ char uid[6]; }; rt_err_t rrh62000_read_uid(struct rt_i2c_bus_device *bus, struct rrh62000_uid *data); struct rrh62000_algoversion{ char major; char minor; char patch; }; rt_err_t rrh62000_read_algoritm_verison(struct rt_i2c_bus_device *bus, struct rrh62000_algoversion *data); rt_err_t rrh62000_read_TVOC_sensor_clean_status(struct rt_i2c_bus_device *bus, rt_bool_t *isComplete); struct rrh62000_firmwareversion{ char major; char minor; }; rt_err_t rrh62000_read_firmware_verison(struct rt_i2c_bus_device *bus, struct rrh62000_firmwareversion *data);
drv_rrh62000.c
#include <drivers/sensor.h> #include "hal_data.h" #include "rrh62000.h" struct sensor_device { rt_bool_t openCount; struct rt_i2c_bus_device * dev; struct rrh62000_data data; }; static rt_ssize_t _get_data(rt_sensor_t sensor, struct rt_sensor_data *data) { struct sensor_device *dev = sensor->parent.user_data; rt_bool_t isDataReady = RT_FALSE; if (sensor->info.type == RT_SENSOR_CLASS_TEMP) { if((rrh62000_read_data_status(dev->dev, &isDataReady) == RT_EOK) && (isDataReady)) { rrh62000_read_measured_value(dev->dev, &dev->data); } } if (sensor->info.type == RT_SENSOR_CLASS_TEMP) { data->data.temp = (dev->data.temperature.integer_part << 16) + dev->data.temperature.decimal_part; data->timestamp = rt_sensor_get_ts(); return 1; } return 0; } static rt_ssize_t fetch_data(struct rt_sensor_device *sensor, void *buf, rt_size_t len) { RT_ASSERT(buf); if (sensor->config.mode == RT_SENSOR_MODE_POLLING) return _get_data(sensor, buf); else return 0; } static rt_err_t _set_power(struct rt_sensor_device *sensor, void *args) { struct sensor_device *dev = sensor->parent.user_data; rt_uint8_t power = *(uint8_t *)args; //fsp_err_t ret; rt_err_t ret; rt_bool_t isTVOCCLean = RT_FALSE; int count = 70; // 70s if(power == RT_SENSOR_POWER_DOWN) { if(dev->openCount != 0) { dev->openCount--; } } else { if(dev->openCount == 0) { do { if(rrh62000_read_TVOC_sensor_clean_status(dev->dev, &isTVOCCLean) == RT_EOK) { if(isTVOCCLean == RT_FALSE) { rt_thread_mdelay(1000); count--; } } }while((isTVOCCLean == RT_FALSE) && (count--)); if(count == 0) { goto RET; } ret = rrh62000_reset(dev->dev); if(ret != RT_EOK) { rt_kprintf("open failed %d\n\r",ret); goto RET; } rt_thread_mdelay(1000); ret = rrh62000_moving_average_set(dev->dev, 1); ret = rrh62000_fan_speed_set(dev->dev, 60); } dev->openCount++; } return RT_EOK; RET: return -RT_ERROR; } static rt_err_t control(struct rt_sensor_device *sensor, int cmd, void *args) { rt_err_t result = RT_EOK; switch (cmd) { case RT_SENSOR_CTRL_GET_ID: // TODO: get device id // result = xxxx(sensor, args); break; case RT_SENSOR_CTRL_GET_INFO: // TODO: get info // result = xxxx(sensor, args); break; case RT_SENSOR_CTRL_SET_RANGE: // TODO: set test range // result = xxxx(sensor, args); break; case RT_SENSOR_CTRL_SET_ODR: // TODO: set frequency // result = xxxx(sensor, args); break; case RT_SENSOR_CTRL_SET_MODE: // TODO: set work mode // result = xxxx(sensor, args); break; case RT_SENSOR_CTRL_SET_POWER: // TODO: set power mode result = _set_power(sensor, args); break; case RT_SENSOR_CTRL_SELF_TEST: // TODO: process self test // result = xxxx(sensor); break; default: return -RT_ERROR; } return result; } static struct rt_sensor_ops sensor_ops = { fetch_data, control }; struct sensor_device * rrh62000_param_init(void) { struct sensor_device *dev; struct rrh62000_firmwareversion fwVersion; struct rrh62000_algoversion algoVersion; dev = rt_calloc(1, sizeof(struct sensor_device)); if(!dev) { goto exit; } rt_memset(dev, 0x00, sizeof(struct sensor_device)); dev->dev = (struct rt_i2c_bus_device *)rt_device_find("i2c1"); if(dev->dev == RT_NULL) { goto exit; } if(rrh62000_read_firmware_verison(dev->dev, &fwVersion) != RT_EOK) { goto exit; } if(rrh62000_read_algoritm_verison(dev->dev, &algoVersion) != RT_EOK) { goto exit; } rt_kprintf("rrh62000 firmware version %d.%d\n\r", fwVersion.major, fwVersion.minor); rt_kprintf("rrh62000 algoritm version %d.%d.%d\n\r", algoVersion.major, algoVersion.minor, algoVersion.patch); return dev; exit: if(dev) rt_free(dev); return RT_NULL; } int rt_hw_init(const char *name, struct rt_sensor_config *cfg) { rt_int8_t result; rt_sensor_t sensor = RT_NULL; struct sensor_device *dev; dev = rrh62000_param_init(); if(dev == RT_NULL) { goto __exit; } /* sensor register */ sensor = rt_calloc(1, sizeof(struct rt_sensor_device)); if (sensor == RT_NULL) goto __exit; sensor->info.type = RT_SENSOR_CLASS_TEMP; // Set real type sensor->info.vendor = RT_SENSOR_VENDOR_UNKNOWN; // Set real vendor sensor->info.model = name; // set real model name sensor->info.unit = RT_SENSOR_UNIT_DCELSIUS; // set to real unit flag sensor->info.intf_type = RT_SENSOR_INTF_I2C; // Set interface type sensor->info.range_max = 0xFFFF; // Set to range max sensor->info.range_min = 0x0000; // Set to range min sensor->info.period_min = 50; // Set frequency rt_memcpy(&sensor->config, cfg, sizeof(struct rt_sensor_config)); sensor->ops = &sensor_ops; result = rt_hw_sensor_register(sensor, name, RT_DEVICE_FLAG_RDONLY, dev); if (result != RT_EOK) { goto __exit; } return RT_EOK; __exit: if (sensor) rt_free(sensor); if(dev) rt_free(dev); return -RT_ERROR; } static int rrh62000_device_register(void) { struct rt_sensor_config cfg = { .mode = RT_SENSOR_MODE_POLLING, .power = RT_SENSOR_POWER_DOWN, }; rt_hw_init("rrh62000", &cfg); return RT_EOK; } INIT_DEVICE_EXPORT(rrh62000_device_register); #if 1 #define RRH_TEMP_DEVICE_NAME "temp_rrh" void rrh6200_temp_read(void) { rt_device_t dev = rt_device_find(RRH_TEMP_DEVICE_NAME); rt_err_t result; rt_uint32_t len; struct rt_sensor_data data; if(!dev) { rt_kprintf("No device name %s\n\r", RRH_TEMP_DEVICE_NAME); return; } result = rt_device_open(dev,RT_DEVICE_FLAG_RDONLY); if(result != RT_EOK) { rt_kprintf("Open %s Fail\n\r", RRH_TEMP_DEVICE_NAME); return; } len = rt_device_read(dev, 0 ,&data,1); if(len) { rt_kprintf("Temp %d.%d \n\r", data.data.temp >> 16, data.data.temp & 0x0000FFFF); } result = rt_device_close(dev); if(result != RT_EOK) { rt_kprintf("Close %s Fail\n\r", RRH_TEMP_DEVICE_NAME); return; } } MSH_CMD_EXPORT(rrh6200_temp_read, rrh62000 temprate sample); #endif
编译选项修改
虽然代码已经添加到目录里了,但是工程并不会编译,此时需要我们手动修改脚本,让工程自动将这些文件导入工程,具体修改如下:
bsp\renesas\ebf_qi_min_6m5\board\Kconfig
bsp\renesas\libraries\HAL_Drivers\SConscript
menuconfig配置
上面添加完毕后,我们还需要去menuconfig中将此传感器启用,具体修改方法如下:
配置完毕后保存,并输入 scons --target=mdk5生成新工程并编译
运行结果
\ | / - RT - Thread Operating System / | \ 5.2.0 build Nov 28 2024 22:19:37 2006 - 2024 Copyright by RT-Thread team [I/I2C] I2C bus [i2c1] registered rrh62000 firmware version 1.0 rrh62000 algoritm version 3.2.0 [I/sensor] rt_sensor[temp_rrh62000] init success Hello RT-Thread! msh >r reboot rrh6200_temp_read msh >rr rrh6200_temp_read msh >rrh6200_temp_read Temp 0.0 msh >rrh6200_temp_read Temp 0.0 msh >rrh6200_temp_read Temp 0.0 msh >rrh6200_temp_read Temp 22.17 msh >rrh6200_temp_read Temp 22.17 msh >rrh6200_temp_read Temp 22.17 msh >rrh6200_temp_read Temp 22.12 msh >rrh6200_temp_read Temp 22.12 msh >rrh6200_temp_read Temp 22.12 msh >rrh6200_temp_read Temp 22.12 msh >rrh6200_temp_read Temp 22.7 msh >rrh6200_temp_read Temp 22.7 msh >rrh6200_temp_read Temp 22.7 msh >rrh6200_temp_read Temp 22.7 msh >rrh6200_temp_read Temp 22.3 msh >rrh6200_temp_read Temp 22.3
后续计划
目前仅仅是初步把温度传感器部分打通了,后续将陆续把剩余的RTT支持的传感器类型全打通。另外,由于搞得比较匆忙,其实代码封装很多地方都不太合适,还需要进一步完善,完善后看怎么推到rtt的软件包里面去。