概述
HS3003是一种数字式温湿度传感器,可以测量环境中的温度和湿度。读取HS3003的数据需要连接传感器到一个数据采集系统,一般是微处理器或者单片机。以下是一个简单的读取HS3003数据的概述:
- 连接电路:将HS3003传感器连接到微处理器或单片机的GPIO引脚。需要注意HS3003的电气特性,比如供电电压和信号电平等。
- 发送命令:发送读取温湿度数据的命令到HS3003传感器。具体的命令格式和通信协议需要参考HS3003的数据手册。
- 接收数据:等待HS3003传感器回应,并接收传感器发送的数据。HS3003传感器的数据一般是经过数字转换后的二进制数据,需要解析成温湿度值。
- 解析数据:将接收到的二进制数据解析成温湿度值。具体的解析算法需要参考HS3003的数据手册,一般涉及到位移、位运算、符号扩展等操作。
- 处理数据:对得到的温湿度值进行处理,比如校准、滤波、显示等。
- 循环读取:根据需要循环执行步骤2到5,以实现连续读取HS3003传感器的温湿度数据。
需要注意的是,HS3003传感器的使用和读取数据需要按照数据手册的规范和建议操作,否则可能会导致数据精度降低、传感器损坏等问题。
硬件准备
首先需要准备一个开发板,这里我准备的是芯片型号R7FAM2AD3CFP的开发板:
IIC配置
配置RA4M2的I2C接口,使其作为I2C master进行通信。
对于OLED的IIC配置,可以查看往期的博客。
查看HS3003说明书,最小电路图如下所示。
由于需要读取HS3003数据,需要使用IIC接口,这里使用PMOD2上的接口(P410和P411)。
点击Stacks->New Stack->Connectivity -> I2C Master(r_sci_i2c)。
查看说明书可以得知,ISL29035的地址为0x44(1000100)。
设置IIC的配置。
R_SCI_I2C_Open()函数原型
R_SCI_I2C_Open()函数为执行IIC初始化,开启配置如下所示。
err = R_SCI_I2C_Open(&g_i2c0_ctrl, &g_i2c0_cfg);
assert(FSP_SUCCESS == err);
R_SCI_I2C_Write()函数原型
R_SCI_I2C_Write()函数是向IIC设备中写入数据,写入格式如下所示。
err = R_SCI_I2C_Write(&g_i2c0_ctrl, &g_i2c_tx_buffer[0], I2C_BUFFER_SIZE_BYTES, false);
assert(FSP_SUCCESS == err);
R_SCI_I2C_Read**()函数原型**
R_SCI_I2C_Read()函数是向IIC设备中读取数据,读取格式如下所示。
err = R_SCI_I2C_Write(&g_i2c0_ctrl, &g_i2c_tx_buffer[0], I2C_BUFFER_SIZE_BYTES, false);
assert(FSP_SUCCESS == err);
sci_i2c_master_callback()回调函数
对于数据是否发送完毕,可以查看是否获取到I2C_MASTER_EVENT_TX_COMPLETE字段。
i2c_master_event_t i2c_event1 = I2C_MASTER_EVENT_ABORTED;
void sci_i2c_master_callback0(i2c_master_callback_args_t *p_args)
{
i2c_event1 = I2C_MASTER_EVENT_ABORTED;
if (NULL != p_args)
{
i2c_event1 = p_args->event;
}
}
HS3003写数据
对于HS3003写数据,手册上的操作方式如下所示。
设备地址+操作地址+数据
初始化程序如下所示。
void Humiture_HS3003_writeRegister( uint8_t reg_address, uint8_t *buffer, uint8_t len)
{
err = R_SCI_I2C_Write(&g_i2c0_ctrl, buffer, len, false);
assert(FSP_SUCCESS == err);
while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event1) && timeout_ms1>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms1--;
}
if (I2C_MASTER_EVENT_ABORTED == i2c_event1)
{
__BKPT(0);
}
i2c_event1 = I2C_MASTER_EVENT_ABORTED;
timeout_ms1 = 100000;
}
HS3003读数据
对于读取数据,可以直接在发送地址后,进行读取,当时需要注意再发送完地址后,要有等待时间。
读取操作函数如下所示,先发送操作地址,在进行读取,这里是一次读取32位。
uint32_t Humiture_HS3003_readRegister32(uint8_t reg_address) {
uint32_t value;
uint8_t data[4];
timeout_ms1 = 100000;
/* Read data from I2C slave */
err = R_SCI_I2C_Read(&g_i2c0_ctrl, &data, 0x04, false);
assert(FSP_SUCCESS == err);
while ((I2C_MASTER_EVENT_RX_COMPLETE != i2c_event1) && timeout_ms1)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
timeout_ms1
}
if (I2C_MASTER_EVENT_ABORTED == i2c_event1)
{
__BKPT(0);
}
i2c_event1 = I2C_MASTER_EVENT_ABORTED;
timeout_ms1 = 100000;
value=data[0];
value<<=8;
value|=data[1];
value<<=8;
value|=data[2];
value<<=8;
value|=data[3];
return value;
}
HS3003初始化
首先需要将HS3003进行唤醒,默认情况下是睡眠模式。
唤醒需要对Measurement Requests (MR)进行操作,MR命令用于将HS300x从休眠模式唤醒。通过发送7位从地址和第8位=0 (WRITE)来发起测量请求。
对于不同精度的数据读取,等待时间是不同的。
对于等待的时间,可以参考下图红框的数据。
HS3003读取温湿度
对于读取数据,可以直接在发送地址后,进行读取,当时需要注意再发送完地址后,要有等待时间。
读取操作函数如下所示,先发送操作地址,在进行读取。
void Humiture_HS3003_init(void)
{
Humiture_HS3003_writeRegister(HS300X_ADR,NULL,0);
}
uint32_t Humiture_HS3003_ReadData_Raw(uint8_t resolution )
{
uint8_t rx_buf[ 4 ];
uint32_t data=0;
Humiture_HS3003_init();
if(resolution==8)
R_BSP_SoftwareDelay(1200U, BSP_DELAY_UNITS_MICROSECONDS);
else if(resolution==10)
R_BSP_SoftwareDelay(2720U, BSP_DELAY_UNITS_MICROSECONDS);
else if(resolution==12)
R_BSP_SoftwareDelay(9100U, BSP_DELAY_UNITS_MICROSECONDS);
else
R_BSP_SoftwareDelay(34U, BSP_DELAY_UNITS_MILLISECONDS);
data=Humiture_HS3003_readRegister32(HS300X_ADR);
return data;
}
对于读取的数据,需要进行处理。
湿度在后两个字节的15-2位,温度在前2个字节的13-0位。
对于原始的数据,要对他进行处理。
Data=Humiture_HS3003_ReadData_Raw(14);
Temp = (float)( (Data & 0xFFFF) >> 2);//只要低十六位
Temp = Temp*HS300X_TEMP_MULTY*165-40;//HS300X_TEMP_MULTY->0.00006163516(1/(2^14-1) )
Humidity = (float)( (Data >> 16) &0x3FFF );//只要高十六位,且最高2位不要
Humidity = Humidity*HS300X_HUMD_MULTY*100;//HS300X_HUMD_MULTY->0.00006163516(1/(2^14-1) )
实现效果
正常显示数据。
同时串口也可以打印数据。
主程序
#include "hal_data.h"
#include <stdio.h>
#include "Humiture_HS3003.h"
#include "oled.h"
#include "bmp.h"
FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER
fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback(uart_callback_args_t *p_args)
{
if(p_args->event == UART_EVENT_TX_COMPLETE)
{
uart_send_complete_flag = true;
}
}
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
if(FSP_SUCCESS != err) __BKPT();
while(uart_send_complete_flag == false){}
uart_send_complete_flag = false;
return ch;
}
int _write(int fd,char *pBuffer,int size)
{
for(int i=0;i<size;i++)
{
__io_putchar(*pBuffer++);
}
return size;
}
i2c_master_event_t i2c_event1 = I2C_MASTER_EVENT_ABORTED;
void sci_i2c_master_callback0(i2c_master_callback_args_t *p_args)
{
i2c_event1 = I2C_MASTER_EVENT_ABORTED;
if (NULL != p_args)
{
i2c_event1 = p_args->event;
}
}
i2c_master_event_t i2c_event = I2C_MASTER_EVENT_ABORTED;
void sci_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
i2c_event = I2C_MASTER_EVENT_ABORTED;
if (NULL != p_args)
{
i2c_event = p_args->event;
}
}
uint32_t timeout_ms1 = 100000;
uint32_t timeout_ms = 100000;
float Temp=0.0f;
float Humidity=0.0f;
uint32_t Data=0;
void hal_entry(void)
{
err = R_SCI_I2C_Open(&g_i2c3_ctrl, &g_i2c3_cfg);
assert(FSP_SUCCESS == err);
OLED_Init();
OLED_Clear() ;
OLED_ShowCHinese(0,0,0);
OLED_ShowCHinese(16,0,1);
OLED_ShowString(0,2,"Temp:",16);
OLED_ShowString(0,4,"Humidity:",16);
err = R_SCI_I2C_Open(&g_i2c0_ctrl, &g_i2c0_cfg);
assert(FSP_SUCCESS == err);
Humiture_HS3003_init();
fsp_err_t err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
assert(FSP_SUCCESS == err);
printf("hello world!\n");
while(1)
{
Data=Humiture_HS3003_ReadData_Raw(14);
Temp = (float)( (Data & 0xFFFF) >> 2);
Temp = Temp*HS300X_TEMP_MULTY*165-40;
Humidity = (float)( (Data >> 16) &0x3FFF );
Humidity = Humidity*HS300X_HUMD_MULTY*100;
OLED_Clear() ;
OLED_ShowCHinese(0,0,0);
OLED_ShowCHinese(16,0,1);
OLED_ShowString(0,2,"Temp:",16);
OLED_ShowString(0,4,"Humidity:",16);
if(Temp<10 && Temp>=0)
{
OLED_ShowNum(48,2,(int)(Temp),1,16);
OLED_ShowString(56,2,".",16);
OLED_ShowNum(64,2,(int)(Temp*100) - ( ((int)Temp) *100),1,16);
if(( (int)(Temp*100) - ( ((int)Temp) *100) ) <10 )
OLED_ShowString(64,2,"0",16);
}
else if (Temp>=10 && Temp<100)
{
OLED_ShowNum(48,2,(int)(Temp),2,16);
OLED_ShowString(64,2,".",16);
OLED_ShowNum(72,2,(int)(Temp*100) - ( ((int)Temp) *100),2,16);
if(( (int)(Temp*100) - ( ((int)Temp) *100) ) <10 )
OLED_ShowString(72,2,"0",16);
}
else if (Temp>=100 && Temp<1000)
{
OLED_ShowNum(48,2,(int)(Temp),3,16);
OLED_ShowString(72,2,".",16);
OLED_ShowNum(80,2,(int)(Temp*100) - ( ((int)Temp) *100),2,16);
if(( (int)(Temp*100) - ( ((int)Temp) *100) ) <10 )
OLED_ShowString(80,2,"0",16);
}
if(Humidity<10)
{
OLED_ShowNum(72,4,(int)(Humidity),1,16);
OLED_ShowString(80,4,".",16);
OLED_ShowNum(88,4,(int)(Humidity*100) - ( ((int)Humidity) *100),2,16);
if(( (int)(Humidity*100) - ( ((int)Humidity) *100) ) <10 )
OLED_ShowString(88,4,"0",16);
}
else if(Humidity>10 && Humidity<100)
{
OLED_ShowNum(72,4,(int)(Humidity),2,16);
OLED_ShowString(88,4,".",16);
OLED_ShowNum(96,4,(int)(Humidity*100) - ( ((int)Humidity) *100),2,16);
if(( (int)(Humidity*100) - ( ((int)Humidity) *100) ) <10 )
OLED_ShowString(96,4,"0",16);
}
printf("Temp=%.2f,Humidity=%.2f\n",Temp,Humidity);
R_BSP_SoftwareDelay(1000U, BSP_DELAY_UNITS_MILLISECONDS);
}
#if BSP_TZ_SECURE_BUILD
R_BSP_NonSecureEnter();
#endif
}
Humiture_HS3003.c
#include "hal_data.h"
#include "Humiture_HS3003.h"
extern fsp_err_t err;
extern int timeout_ms1;
extern i2c_master_event_t i2c_event1 ;
uint32_t Humiture_HS3003_readRegister32(uint8_t reg_address) {
uint32_t value;
uint8_t data[4];
timeout_ms1 = 100000;
err = R_SCI_I2C_Read(&g_i2c0_ctrl, &data, 0x04, false);
assert(FSP_SUCCESS == err);
while ((I2C_MASTER_EVENT_RX_COMPLETE != i2c_event1) && timeout_ms1)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MILLISECONDS);
timeout_ms1--;
}
if (I2C_MASTER_EVENT_ABORTED == i2c_event1)
{
__BKPT(0);
}
i2c_event1 = I2C_MASTER_EVENT_ABORTED;
timeout_ms1 = 100000;
value=data[0];
value<<=8;
value|=data[1];
value<<=8;
value|=data[2];
value<<=8;
value|=data[3];
return value;
}
void Humiture_HS3003_writeRegister( uint8_t reg_address, uint8_t *buffer, uint8_t len)
{
err = R_SCI_I2C_Write(&g_i2c0_ctrl, buffer, len, false);
assert(FSP_SUCCESS == err);
while ((I2C_MASTER_EVENT_TX_COMPLETE != i2c_event1) && timeout_ms1>0)
{
R_BSP_SoftwareDelay(1U, BSP_DELAY_UNITS_MICROSECONDS);
timeout_ms1--;
}
if (I2C_MASTER_EVENT_ABORTED == i2c_event1)
{
__BKPT(0);
}
i2c_event1 = I2C_MASTER_EVENT_ABORTED;
timeout_ms1 = 100000;
}
void Humiture_HS3003_init(void)
{
Humiture_HS3003_writeRegister(HS300X_ADR,NULL,0);
}
uint32_t Humiture_HS3003_ReadData_Raw(uint8_t resolution )
{
uint8_t rx_buf[ 4 ];
uint32_t data=0;
Humiture_HS3003_init();
if(resolution==8)
R_BSP_SoftwareDelay(1200U, BSP_DELAY_UNITS_MICROSECONDS);
else if(resolution==10)
R_BSP_SoftwareDelay(2720U, BSP_DELAY_UNITS_MICROSECONDS);
else if(resolution==12)
R_BSP_SoftwareDelay(9100U, BSP_DELAY_UNITS_MICROSECONDS);
else
R_BSP_SoftwareDelay(34U, BSP_DELAY_UNITS_MILLISECONDS);
data=Humiture_HS3003_readRegister32(HS300X_ADR);
return data;
}
Humiture_HS3003.h
#ifndef HUMITURE_HS3003_H_
#define HUMITURE_HS3003_H_
#define HS300X_ADR 0x44
#define HS300X_HUMD_MULTY 0.00006163516
#define HS300X_TEMP_MULTY 0.00006163516
uint32_t Humiture_HS3003_readRegister32(uint8_t reg_address);
void Humiture_HS3003_writeRegister( uint8_t reg_address, uint8_t *buffer, uint8_t len);
void Humiture_HS3003_init(void);
uint32_t Humiture_HS3003_ReadData_Raw(uint8_t resolution);
#endif
*附件:RA4M2_IIC_OLED_ISL29035_1.zip
*附件:REN_HS300x-Datasheet_DST_20210809.pdf
*附件:ISL29035光照传感器_Schematic1_2022-12-10.pdf