过往分享
下面是参加RA4M2使用活动的分享:
【瑞萨RA4系列开发板体验】1. 新建工程+按键控制LED
【瑞萨RA4系列开发板体验】2. KEIL环境搭建+STLINK调试+FreeRTOS使用
【瑞萨RA4系列开发板体验】3. KEIL下UART实现printf与scanf重定向
【瑞萨RA4系列开发板体验】4. PWM驱动LED
【瑞萨RA4系列开发板体验】5. 硬件IIC驱动OLED显示汉字
【瑞萨RA4系列开发板体验】6. ADC测量摇杆模块偏移量
【瑞萨RA4系列开发板体验】7. 用DAC输出正弦波以及余弦波
【瑞萨RA4系列开发板体验】8. 超声波测距模块在RA4M2上的应用
【瑞萨RA4系列开发板体验】9. 用两路DAC在示波器上显示一个爱心
RA4M2挑战赛分享:
【RA4M2设计挑战赛】1. RASC配置FreeRTOS
前言
本文将操作官方模块HS300X(温湿度传感器),基于FreeRTOS作为OS,实现硬件IIC采集HS3003的温湿度数据。
HS300X原理图
通过对比了RA4M2开发板的PMOD接口以及HS300X的接口,HS300X是IIC接口,但是单片机的PMOD接口没有一个对应的IIC接口可以匹配,所以我们将HS300X直接和单片机的IIC引脚连接,不通过PMOD连接。
IIC接口
由于OLED也是IIC接口的,OLED操作可以参考我之前的帖子:【瑞萨RA4系列开发板体验】5. 硬件IIC驱动OLED显示汉字。
OLED使用的是sci3的硬件i2c接口
所以我打算将HS300X也接到sci3 i2x接口上,即:
SCL3 - P408
SDA3 - P409
HS300X操作方式
虽然知道了HS300X是IIC接口,但是我们还不知道该如何操作,需要了解HS300X的操作方式,寄存器,IIC地址等,查看官方提供的手册《REN_HS300x-Datasheet_DST_20210809.pdf》
测量请求
通过直接写HS300X地址就可以唤醒传感器,然后自动采集数据,说明见下:
从下图中可以看到IIC地址为0x44,然后加一个低位1表示写,就可以触发转换。
数据获取
从下图可以看出,发送HS300X地址+低位读就可以获取采集的数据。
注:重点说明,默认采样精度为14bit,可以通过配置修改,精度越高,采样时间越长,下图中有说明,默认精度下的采样时间为33ms左右,所以在测量请求发出之后,需要等待33毫秒之后在读取
采集数据分析,从图中可以清楚看出,默认温度和湿度数据都为14bit数据,都占用了两个字节,其中湿度的高两位为状态为,表示采集数据状态,见下图,为0表示数据采集完成,1表示没有完成有效采集。
温度的低两位没有任何用处。
采样精度修改
采样精度可以修改,精度月底,采样时间越快。可以通过下属寄存器进行修改,该部分本文不会实现,只作为功能想描述。
修改方式也很简单,IIC地址+低位写0+修改精度寄存器地址+精度即可完成修改,详情参考数据手册。
采样数据处理
采集到的数据为原始数据,需要进行计算得出真实的温湿度数据,计算公式如下:
即:
湿度值(%):采样值/(16383) * 100
温度值(摄氏度):采样值/(16383) * 165 - 40
软件编写
知道了硬件设置以及原理,现在可以看是编写软件了,如下:
app_Hs300x.c
#include "hal_data.h"
#include "app_hw_i2c.h"
#include "app_hs300x.h"
#define HS300X_DEBUG
#undef HS300X_DEBUG
#ifdef HS300X_DEBUG
#include <stdio.h>
#endif
#define HS300x_I2C_SLAVE_ADDR_7BIT (0x44U)
#define HS300X_DATA_VALID (0x00U)
#define HS300X_DATA_STALE (0x01U)
#define HS300X_STATUS_MASK (0xC0000000U)
#define HS300X_STATUS_POS (30U)
#define HS300X_DATA_MASK (0x3FFFFFFCU)
#define HS300X_HUMI_DATA_MASK (0x3FFF0000U)
#define HS300X_HUMI_DATA_POS (16U)
#define HS300X_TEMP_DATA_MASK (0x0000FFFCU)
#define HS300X_TEMP_DATA_POS (2U)
#define HS300X_DATA_FACTOR (16383U)
static void Hs300x_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len);
static void Hs300x_WriteToI2C(uint8_t *data_buffer, uint8_t data_len);
static bool Hs300x_DataConvert(uint32_t read_data, s_Hs300xDataType *cal_result);
static void Hs300x_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len)
{
fsp_err_t err;
uint32_t timeout_ms = 100;
if (pdTRUE == xSemaphoreTake(mutex_sci3_i2c, portMAX_DELAY))
{
R_SCI_I2C_SlaveAddressSet(&g_sci3_i2c_ctrl,
HS300x_I2C_SLAVE_ADDR_7BIT,
I2C_MASTER_ADDR_MODE_7BIT);
err = R_SCI_I2C_Read(&g_sci3_i2c_ctrl, data_buffer, data_len, true);
assert(FSP_SUCCESS == err);
while ((I2C_MASTER_EVENT_TX_COMPLETE != sci3_i2c_event) && timeout_ms>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
if (I2C_MASTER_EVENT_ABORTED == sci3_i2c_event)
{
__BKPT(0);
}
sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;
(void)xSemaphoreGive(mutex_sci3_i2c);
}
}
static void Hs300x_WriteToI2C(uint8_t *data_buffer, uint8_t data_len)
{
fsp_err_t err;
uint32_t timeout_ms = 100;
if (pdTRUE == xSemaphoreTake(mutex_sci3_i2c, portMAX_DELAY))
{
R_SCI_I2C_SlaveAddressSet(&g_sci3_i2c_ctrl,
HS300x_I2C_SLAVE_ADDR_7BIT,
I2C_MASTER_ADDR_MODE_7BIT);
err = R_SCI_I2C_Write(&g_sci3_i2c_ctrl, data_buffer, data_len, true);
assert(FSP_SUCCESS == err);
while ((I2C_MASTER_EVENT_TX_COMPLETE != sci3_i2c_event) && timeout_ms>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms--;
}
if (I2C_MASTER_EVENT_ABORTED == sci3_i2c_event)
{
__BKPT(0);
}
sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;
(void)xSemaphoreGive(mutex_sci3_i2c);
}
}
static bool Hs300x_DataConvert(uint32_t read_data, s_Hs300xDataType *cal_result)
{
uint32_t humi_data;
uint32_t temp_data;
if (((read_data & HS300X_STATUS_MASK) >> HS300X_STATUS_POS) == HS300X_DATA_VALID)
{
humi_data = (read_data & HS300X_HUMI_DATA_MASK) >> HS300X_HUMI_DATA_POS;
temp_data = (read_data & HS300X_TEMP_DATA_MASK) >> HS300X_TEMP_DATA_POS;
cal_result->humi = (double)humi_data/(double)(HS300X_DATA_FACTOR) * 100.0;
cal_result->temp = (double)temp_data/(double)(HS300X_DATA_FACTOR) * 165.0 - 40;
#ifdef HS300X_DEBUG
printf("humidity:%f, temperature:%f\n", cal_result->humi, cal_result->temp);
#endif
return true;
}
else
{
return false;
}
}
void Hs300x_Init(void)
{
}
s_Hs300xDataType Hs300x_ReadData(void)
{
uint8_t data[4];
uint32_t data_u32;
s_Hs300xDataType humi_temp;
Hs300x_WriteToI2C(NULL, 0);
vTaskDelay(pdMS_TO_TICKS(50));
Hs300x_ReadFromI2C(data, 4);
data_u32 = (uint32_t)((data[0] << 24U) |
(data[1] << 16U) |
(data[2] << 8U) |
(data[3]));
(void)Hs300x_DataConvert(data_u32, &humi_temp);
#ifdef HS300X_DEBUG
printf("HS300X origin data1:%x%x%x%x\n", data[0],data[1],data[2],data[3]);
#endif
return humi_temp;
}
app_Hs300x.h
#ifndef APP_HS300X_H_
#define APP_HS300X_H_
#include "app_common.h"
typedef struct
{
double humi;
double temp;
} s_Hs300xDataType;
extern void Hs300x_Init(void);
extern s_Hs300xDataType Hs300x_ReadData(void);
#endif
新建一个任务,然后写入如下代码开始测试验证。
#define DISP_DEBUG
static void Disp_SensorMonitor(void)
{
s_Hs300xDataType humi_temp;
humi_temp = Hs300x_ReadData();
#ifdef DISP_DEBUG
printf("humidity: %.2f%%, temperature: %.2fC\n", humi_temp.humi, humi_temp.temp);
#endif
}
试验结果