[DAY 16] _Si7020温湿度读写

今天来说说温湿度读取的部分吧,首先来看看这颗的Datasheet:
https://www.silabs.com/documents/public/data-sheets/Si7020-A20.pdf
https://ithelp.ithome.com.tw/upload/images/20210929/20141979KQG9TNipnx.png
这是第一页,他的接脚不复杂四条线就可以使用了:SCL、SDA、VDD、GND,DNC脚空接就好

在手册的第1页有说明了,他不需要校准出工厂前都有效准过了,我觉得温度这真的很难有个绝对,没必要讨论温湿度到底准不准,每的地点温度又不同也会受风的影响,要真的说温度测的准不准我觉得要用1个恒温箱来观看吧,那又有个问题恒温箱是真的准确的?之前有被问到这问题,个人觉得讨论这个没甚麽意义。

来看看 bsp_I2C_si7020.h

#ifndef __BSP_I2C_si7020_H
#define __BSP_I2C_si7020_H
#include "stm32f0xx.h"
#include "bsp_I2C_gpio.h"

#define SI7020_ADDRESS 0x40			//SI7020器件地址
#define SI7020_WEITE   0X80     //7位地址+1bit写地址
#define SI7020_READ    0X81     //7位地址+1bit读地址

//---- Measure---
#define SI7020_Humidity_Hold_Master_Mode			0xE5
#define SI7020_Humidity_No_Hold_Master_Mode         0xF5
#define SI7020_Temperature_Hold_Master_Mode         0xE3
#define SI7020_Temperature_No_Hold_Master_Mode      0xF3
//****************
#define SI7020_SOFT_RESET  						    0xFE

void SI7020_Init(void); //初始化IIC
uint16_t SI7020_ReadOneByte(uint8_t ReadAddr);	//读取暂存器的数值
int16_t SI7020_Read_Humidity(void);				//取出湿度值
int16_t SI7020_Read_Temperture(void);			//取出温度值
uint8_t SI7020_WaitStandby(void);			    //等待I2C总线空闲
#endif /*__BSP_I2C_si7020_H*/

以上是一些定义下面是函示的宣告SI7020_ReadOneByte这个示读暂存器里的数值,下面那两个个别的取出湿度和温度的函示里面来使用 SI7020_ReadOneByte

bsp_I2C_si7020.c

接下来我会分段讲

#include "bsp_I2C_si7020.h"
#include "bsp_SysTick.h"
void SI7020_Init(void)   //初始化si7020******
{ 
	//初始化GPIO_IIC ******
    GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHBPeriphClockCmd(i2c_GPIO_CLK, ENABLE);	/* 打开GPIO时钟 */
	GPIO_InitStructure.GPIO_Pin = i2c_SCL_PIN | i2c_SDA_PIN;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;  	
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;      /* 开漏输出 */
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(i2c_GPIO_PORT, &GPIO_InitStructure);
	/* 给一个停止信号, 重定I2C汇流排上的所有设备到待机模式 */
	i2c_Stop();     
} 

因为我是GPIO口的方式来完成读写,所以会初始化这些两个IO口 i2c_SCL_PIN | i2c_SDA_PIN

//在SI7020指定地址读出一个数据
//ReadAddr:读取温度或湿度_暂存器位置 
//return value:读到的数据

uint16_t SI7020_ReadOneByte(uint8_t ReadAddr)
{                                  
    uint8_t temp[2];
    uint16_t value=0;
    i2c_Start();
    i2c_SendByte(SI7020_WEITE);
    i2c_WaitAck();
    i2c_SendByte(ReadAddr);
    i2c_WaitAck();
    delay_ms(20); 
    i2c_Start();
    i2c_SendByte(SI7020_READ);
    i2c_WaitAck();
    delay_ms(20);                                      
//  i2c_Start();               //********************************************
//  i2c_SendByte(SI7020_READ); //使用No Hold Master Mode多使用此3行程序
//  i2c_WaitAck();			  //********************************************
    temp[1]=i2c_ReadByte();
    i2c_Ack();
    temp[0]=i2c_ReadByte();
    i2c_NAck();
    i2c_Stop();
    value=temp[0]|(temp[1]<<8);
    return value;
}

这是读取数值的部分,再来看手册说明的部分
https://ithelp.ithome.com.tw/upload/images/20210929/20141979nBTHpzwopn.png

不管读温度还是湿度的有两种模式,保持跟部保持数据,程序码没甚麽大差别,我程序码有注解上去
白色为主机端,灰色为从机端

//Humidity 读取湿度
//return   返回湿度
int16_t SI7020_Read_Humidity(void)
{
   uint16_t value=0;
   double temp;
   value=SI7020_ReadOneByte(SI7020_Humidity_Hold_Master_Mode);
   temp=(double)value;
   temp=(temp/65536.0f)*125.0f-6.0f;
   printf("%.1lf %%RH\r\n",(temp-5));  //
   return (int16_t)(temp*10);          //返回Humidity,此处放大了10倍
}
//Temperture_读取温度
//return    _返回温度
int16_t SI7020_Read_Temperture(void) 
{
    uint16_t value=0;
    double temp;
    value=SI7020_ReadOneByte(SI7020_Temperature_Hold_Master_Mode);
    temp=(double)value;
    temp=(temp/65536.0f) * 175.72f - 46.85f;
	  printf("%.1lf C\r\n",(temp-2));	//-2 校正误差
    return (int16_t)(temp*10);      //返回温度值,此处放大了10倍    
}
uint8_t SI7020_WaitStandby(void)
{
	uint32_t wait_count = 0;
	while(i2c_CheckDevice(SI7020_WEITE))
	{
		//若检测超过次数,退出循环
		if(wait_count++>0x0FFFF)
		{
			return 1;//等待超时
		}
	}
	return 0;//等待完成
}

我读取温度和湿度分开写了,可以看到中间有个计算,是根据手册上的说明去计算

https://ithelp.ithome.com.tw/upload/images/20210929/20141979QR3K7pLfXF.png

再来是main.c的部份

#include "bsp_I2C_si7020.h"
#include "bsp_SysTick.h"

int main(void)
{
    SysTick_Init(48);     //初始化M0内核计时器
    SI7020_Init();        //SI7020_GPIO初始化
	DEBUG_USART_Config(); //UARTt初始化
    
    while(1)
	{
		SI7020_WaitSdby();            //确定I2C BUS可否使用
		delay_ms(10);
		SI7020_Read_Humidity();		 //抓取湿度後,列印湿度
		SI7020_Read_Temperture();    //抓取温度後,列印温度
		delay_ms(500);
    }
}

这些都是要花时间看的,我当初学这些也花了不少时间,了解这I2C时序运作方式後让我会看任何手册的数位讯号的时序会更快进入状况,遇到其他协定也大概都知道如何看。


<<:  Day 14 - Asynchronous 非同步核心

>>:  DAY29 - [React] useContext 实作篇

No Time To Die在线看

No Time To Die在线看 《007:无暇赴死》是007系列电影的第25部,由凯瑞·福永执导...

流程控制

选择语句 最简单的版本 if 表达式: 接下来需要做的...... 当然,前一章也看过了,也有els...

Day 12 - Confusion Matrix 混淆矩阵-模型的好坏 (2)

精确率(precision) 召回率(recall) Precision和Recall同时关注的都是...

Day 8 中断服务处理机制与分配器

上篇说到排程器的部分,有个地方需要注意的是,如果因为硬体要求中断排程的优先权,此时就会有个中断服务的...