下面是参加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的温湿度数据。
通过对比了RA4M2开发板的PMOD接口以及HS300X的接口,HS300X是IIC接口,但是单片机的PMOD接口没有一个对应的IIC接口可以匹配,所以我们将HS300X直接和单片机的IIC引脚连接,不通过PMOD连接。
由于OLED也是IIC接口的,OLED操作可以参考我之前的帖子:【瑞萨RA4系列开发板体验】5. 硬件IIC驱动OLED显示汉字。
OLED使用的是sci3的硬件i2c接口
所以我打算将HS300X也接到sci3 i2x接口上,即:
SCL3 - P408
SDA3 - P409
虽然知道了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
/*
@hehung
2023-2-8
转载请注明出处,版权由@hehung所有
email: 1398660197qq.com
wechat: hehung95
*/
/*******************************************************************************
* Header Include
******************************************************************************/
#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
/*******************************************************************************
* Macro Definitions
******************************************************************************/
#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)
/* calculation formula, 2^14 - 1 */
#define HS300X_DATA_FACTOR (16383U)
/*******************************************************************************
* Static Variables Definitions
******************************************************************************/
/*******************************************************************************
* Static Function Declarations
******************************************************************************/
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);
/*******************************************************************************
* Function Definitions
******************************************************************************/
/*********************Hs300x读数据函数************************************/
static void Hs300x_ReadFromI2C(uint8_t *data_buffer, uint8_t data_len)
{
fsp_err_t err;
uint32_t timeout_ms = 100;
// setting mutex for lock sci3_i2c bus
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);
/* Since there is nothing else to do, block until Callback triggers*/
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);
}
/* Read data back from the I2C slave */
sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;
// release the mutex, unlock
(void)xSemaphoreGive(mutex_sci3_i2c);
}
}
/*********************Hs300x写数据函数************************************/
static void Hs300x_WriteToI2C(uint8_t *data_buffer, uint8_t data_len)
{
fsp_err_t err;
uint32_t timeout_ms = 100;
// setting mutex for lock sci3_i2c bus
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);
/* Since there is nothing else to do, block until Callback triggers*/
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);
}
/* Read data back from the I2C slave */
sci3_i2c_event = I2C_MASTER_EVENT_ABORTED;
// release the mutex, unlock
(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)
{
// Data is 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;
// Calculate the humidity: humi_data/(2^14-1) * 100
cal_result->humi = (double)humi_data/(double)(HS300X_DATA_FACTOR) * 100.0;
// Calculate the temperature: temp_data/(2^14-1) * 165 - 40
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)
{
// Do not settings, keep default settings in sensor device
}
s_Hs300xDataType Hs300x_ReadData(void)
{
uint8_t data[4];
uint32_t data_u32;
s_Hs300xDataType humi_temp;
// Write address start measurement
Hs300x_WriteToI2C(NULL, 0);
// Delay 50ms for waiting for convert finished
vTaskDelay(pdMS_TO_TICKS(50));
// Read measurement from sensor HS300X
Hs300x_ReadFromI2C(data, 4);
// Convert the data to 32bit
data_u32 = (uint32_t)((data[0] << 24U) |
(data[1] << 16U) |
(data[2] << 8U) |
(data[3]));
// Read the temperature and hunidity
(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]);
// printf("HS300X origin data2:%x\n", data_u32);
#endif
return humi_temp;
}
app_Hs300x.h
/*
@hehung
2023-2-8
转载请注明出处,版权由@hehung所有
email: 1398660197qq.com
wechat: hehung95
*/
#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 /* APP_HS300X_H_ */
新建一个任务,然后写入如下代码开始测试验证。
#define DISP_DEBUG
// Display sensor information: humidity/temperature/light strength
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
}
更多回帖