使用STM32F103采集Si7021温湿度传感器数据

发布者:BlissfulWhisper最新更新时间:2019-07-11 来源: eefocus关键字:STM32F103  Si7021  温湿度传感器 手机看文章 扫描二维码
随时随地手机看文章

一、传感器电路连接


Si7021的外围电路非常简单,如图1所示:

图1    Si7021传感器外围电路


Si7021采用的是IIC接口,最高支持400KHz的通信速率,0~100%RH的湿度量程和最大-40℃~+125℃的温度量程,150μA低功耗,超小体积。可提供精确,低功耗,工厂校准的数字解决方案,适用于测量湿度,露点和温度,适用于从HVAC / R和资产跟踪到工业和消费者平台的各种应用。


二、时序和协议分析


首先看看Si7021的IIC通信时序,图2展示了Si7021的IIC时序图和各个时序时间的参数表。



图2    传感器IIC通信时序


其实这个IIC时序我个人认为没啥特别的,感觉就是一个比较常见的通信时序。


不过,这个传感器在读写协议上有个比较特殊的也是我有点搞不懂的地方。它的IIC读写其实是有两个模式的,一个叫保持主模式(Hold Master Mode),另一个叫无保持主模式(No Hold Master Mode),这两种模式又分别有两种测量指令相对应。


按照数据手册的说法,无保持主模式下在从机应答了测量指令后,主机要重新发送一次起始信号Sr,然后连续发送三次从机地址之后开才始读取数据;而在保持主模式下,传感器应答主机的读指令之后从机会把时钟线SCL强制拉高,直到温湿度转换完成。图3和图4分别为Si7021无保持主模式和保持主模式下的IIC读写协议。



图3    无保持主模式读写协议



图4    保持主模式读写协议


这个读写协议我就有点看不懂了,而且最尴尬的是,按照手册上的无保持主模式读写根本读不出数据,全是0xFF,而且不知道是不是我的驱动有问题,用保持主模式的时候拿逻辑分析仪测信号,发现SCL也并没有强制拉高。最后实在没办法,就用了无保持的测量指令,然后在STM32等到ACK之后延时20ms再读数据,才正常的。但是这样又跟数据手册说的完全不一样了。


反正当时真是把我给搞懵逼了,还请各位大佬能点拨指导一下。


三、测量程序编写


既然已经能读到数据了,那就直接开始编写测量程序好了。我的测量代码的底层IIC驱动代码是借鉴的正点原子的例程,温湿度计算部分参考了这篇博客:家庭IOT监测之温湿度SI7021及上传ONENET


首先是IO口的初始化,我使用了PB8(SCL)和PB9(SDA)。


void IIC_Init(void)//IIC初始化

{      

GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); //使能GPIOB时钟

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_9;//PB8->SCL, PB9->SDA

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOB, &GPIO_InitStructure);

 

IIC_SCL=1;//初始电平设为高

IIC_SDA=1;

}

 


然后是多字节读取传感器函数:


 


//函数名称:Multiple_read_Si7021

//函数功能:多字节读取传感器

//参数描述:

//返 回 值:

void Multiple_read_Si7021(u8 REG_address, u16 *value)

{

u8 Si7021_BUF[2]={0};//缓存数组定义

IIC_Start();//IIC起始信号

IIC_Send_Byte((SLAVE_ADDR<<1)|0);//将7位器件地址左移一位再加上一位写操作

IIC_Wait_Ack();//等待应答

IIC_Send_Byte(REG_address);

IIC_Wait_Ack();//等待应答

delay_ms(19);//等待温湿度转换完成,至少应该大于18ms

IIC_Start();

IIC_Send_Byte((SLAVE_ADDR<<1)|1);//将7位器件地址左移一位再加上一位读操作

IIC_Wait_Ack();

Si7021_BUF[0] = IIC_Read_Byte(1);//读传感器高8位数据并发送应答信号

Si7021_BUF[1] = IIC_Read_Byte(0);//读传感器低8位数据并发送非应答信号

IIC_Stop();//停止信号

*value=((Si7021_BUF[0]<<8)+Si7021_BUF[1]);//将高低8位数据合成为16位数据

}

接着是温湿度测量函数:


//函数名称:measure_si7021

//函数功能:NO HOLD MASTER模式下读取温湿度 

//参数描述:无

//返 回 值:无

void measure_Si7021(void)

{

//缓存变量定义

u16 TEMP,HUMI;

u8 curI;

//读取温度

Multiple_read_Si7021(TEMP_NOHOLD_MASTER,&TEMP);//NOHOLD_MASTER模式下读取温度

si7021.temp=(((((float)TEMP)*175.72f)/65536.0f) - 46.85f);//将原始温度数据计算为实际温度数据并传递给缓存区,单位 ℃

// TEMP_buf=(((((float)TEMP)*175.72f)/65536.0f) - 46.85f);

Multiple_read_Si7021(HUMI_NOHOLD_MASTER,&HUMI);//NOHOLD_MASTER模式下读取湿度

si7021.humi=(((((float)HUMI)*125.0f)/65535.0f) - 6.0f);//将原始湿度数据计算为实际湿度数据并传递给缓存区,单位 %RH

// Humi_buf=(((((float)HUMI)*125.0f)/65535.0f) - 6.0f);

//下面其实是我抄的机智云智能宠物屋温湿度测量的一个平均值滤波算法,循环储存10次的数据,调用一次measure_Si7021()就存一次

if(MEAN_NUM > si7021_filter.curI)//当MEAN_NUM==10时,完成10次读取

{

si7021_filter.tBufs[si7021_filter.curI] = si7021.temp;

si7021_filter.hBufs[si7021_filter.curI] = si7021.humi;

 

si7021_filter.curI++;

}

else

{

si7021_filter.curI = 0;

 

si7021_filter.tBufs[si7021_filter.curI] = si7021.temp;

si7021_filter.hBufs[si7021_filter.curI] = si7021.humi;

 

si7021_filter.curI++;

}

if(MEAN_NUM <= si7021_filter.curI) 

    {

        si7021_filter.thAmount = MEAN_NUM;

    }

 

//判断是否初次循环

    if(0 == si7021_filter.thAmount) 

    {

        //计算采集第10次数据之前的平均值

        for(curI = 0; curI < si7021_filter.curI; curI++)

        {

            si7021.temp += si7021_filter.tBufs[curI];

            si7021.humi += si7021_filter.hBufs[curI];

        }

 

        si7021.temp = si7021.temp / si7021_filter.curI;

        si7021.humi = si7021.humi / si7021_filter.curI; 

        

        TEMP_buf = si7021.temp;

        Humi_buf = si7021.humi;

    }

    else if(MEAN_NUM == si7021_filter.thAmount) 

    {

        //计算采集第10次数据之后的平均值

        for(curI = 0; curI < si7021_filter.thAmount; curI++) 

        {

            si7021.temp += si7021_filter.tBufs[curI];

            si7021.humi += si7021_filter.hBufs[curI];

        }

 

        si7021.temp = si7021.temp / si7021_filter.thAmount; 

        si7021.humi = si7021.humi / si7021_filter.thAmount; 

        

        TEMP_buf = si7021.temp; 

        Humi_buf = si7021.humi; 

    }

}

最后,主函数每50ms调用一次测量函数,但每隔1s才发送一次数据给串口:


#include "delay.h"

#include "sys.h"

#include "usart.h"

#include "Si7021.h"

 

int main(void)

{

    u8 i=0;

 

delay_init(); //延时函数初始化

uart_init(115200); //串口1初始化波特率为115200

IIC_Init(); //IIC初始化 

 

 

while(1)

{ //每50ms读取一次数据

measure_Si7021();

 

 

i++;

delay_ms(50);

if(i==20)

{ //串口每1s打印一次数据

printf("rnTemp:%.2frn",TEMP_buf);//打印温度数据,保留两位小数

printf("Humi:%.2frn",Humi_buf);//打印湿度数据,保留两位小数

i=0;

}

}

}

delay_init(); //延时函数初始化

uart_init(115200); //串口1初始化波特率为115200

IIC_Init(); //IIC初始化 



while(1)

{ //每50ms读取一次数据

measure_Si7021();



i++;

delay_ms(50);

if(i==20)

{ //串口每1s打印一次数据

printf("rnTemp:%.2frn",TEMP_buf);//打印温度数据,保留两位小数

printf("Humi:%.2frn",Humi_buf);//打印湿度数据,保留两位小数

i=0;

}

}

}


关键字:STM32F103  Si7021  温湿度传感器 引用地址:使用STM32F103采集Si7021温湿度传感器数据

上一篇:零知开源分享- 温湿度模块DHT11的使用
下一篇:STM32驱动DHT22温湿度传感器程序

推荐阅读最新更新时间:2024-11-09 16:52

stm32f103——时钟树的分析与配置
时钟树是用来对单片机系统和各个外设进行时钟配置的,因为不同的外设,其电路不同,对时钟频率的要求也就不同。所以需要我们对时钟源的频率进行改变,变成外设需要的时钟频率。 首先时钟树分为俩部分: 左边部分是时钟的来源,右边部分是时钟的去向: 各类时钟简括: 1.HSE时钟(高速外部时钟):来源为外部晶振,通常速度8Mhz。由RCC_CR时钟控制寄存器中的16:HSEON控制。 2.HSI时钟(高速内部时钟):来源为芯片内部,大小为8Mhz,当HSE故障时,系统时钟会自动切换到HSI,知道HSE启动成功,相当于HSE的替补。由RCC_CR时钟控制寄存器的位0:HSION控制。 3.PLLCLK(锁相环时钟):来源
[单片机]
<font color='red'>stm32f103</font>——时钟树的分析与配置
STM32F103之USB(一)
初识USB 由于项目需求,需要USB这块,花了几天时间了解了下USB方面的知识,的确挺难的!USB是个挺难啃的家伙,当时看了一遍看的一头雾水,不过几天下来还是有所收获的。顺便记录下自己学习的过程,一遍以后查看。 一、USB介绍 USB(Univetsal Serial Bus)的缩写,即通用串行总线。是现在通讯设备中不可或缺的一部分,可以这么说,电子工程师不懂USB那就太OUT了。 二、USB的发展史 Ø1994年 Philips公司 Access.Bus规范(USB的前身) Ø1996年 Compaq、Intel、Microsoft、NEC USB1.0规范 Ø1997年 US
[单片机]
<font color='red'>STM32F103</font>之USB(一)
NS32F103VBT6软硬件替代STM32F103VBT6
NS32F103X8和NS32F103XB标准型MCU系列使用高性能的ARM Cortex-M3 32 位的RISC内核,工作频率为72MHz,内置高速存储器(高达128K字节的闪存和20K字节的SRAM),丰富的增强I/O端口和联接到两条APB总线的外设。其中包含2个12位ASDC、3个通用16位定时器和1个PWM定时器,此外,还包含标准和先进的通信接口:多达2个I2C接口和SPI接口、3个USART接口、1个USB接口和1个CAN接口。 NS32F103X8和NS32F103XB标准型MCU系列产品供电电压为2.0V至3.6V,-40℃至+85℃的工作温度范围以及-40℃至+105℃的扩展温度范围,一系列的省电模式保证低功
[单片机]
基于STM32F103——SIM900A发送短信+串口打印
最近用STM32F103做一个智能门锁小玩意,密码输入错误次数多进行验证码解锁,这里我采用SIM900A来通过发送短信输入验证码进行解锁。就是简单的了解了一下在这里也单独的写写这个SIM900A的一写笔记。 基本介绍 。。。。。。还是直接进入主题吧 一:单独测试 SIM900A是可以AT指令操作的,所以一般我拿到这种模块就是先单独的测试一下这个模块是否正常。通过一个USB-TTL 和 SIM900A连接 进行调试。用我们的电脑串口助手测试即可。没必要上来就用单片机,现单独测试了先。没问题再转成代码也不迟。 1.准备工作 USB-TTL一个 还有杜邦线就不用说啦 2.接线 3.指令操作 打开你的串口助手 注意
[单片机]
基于<font color='red'>STM32F103</font>——SIM900A发送短信+串口打印
STM32F103标准库开发---Uart串口通信实验---I/O口模拟串口通信----延时法
UART是一种通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输和接收。 一、串口传输协议 1. 传输方式 串口通信的数据由发送设备通过自身的TXD接口传输到接收设备得RXD接口, 一个字符一个字符地传输,每个字符一位一位地传输,并且传输一个字符时,总是以“起始位”开始,以“停止位”结束,字符之间没有固定的时间间隔要求。 每一个字符的前面都有一位起始位(低电平),字符本身由8位数据位组成,接着字符后面是一位校验位(检验位可以是奇校验、偶校验或无校验位),最后是一位或一位半或二位停止位,停止位后面是不定长的空闲位,停止位和空闲位都规定为高电平。具体如下图所示。 实际传输时每一位的信号宽度与波特率有关,波特
[单片机]
<font color='red'>STM32F103</font>标准库开发---Uart串口通信实验---I/O口模拟串口通信----延时法
STM32F103R6之系统架构
主系统由四个驱动单元和四个被动单元构成。 四个驱动单元: M3内核的Dcode总线(D-bus) 系统总线 通用DMA1 通用DMA2 四个被动单元: 内部SRAM 内部闪存存储器(flash) FSMC AHB到APB的桥 图 1系统结构 ICode总线将Cortex™-M3内核的指令总线与闪存指令接口相连接。指令预取在此总线上完成。 DCode总线将Cortex™-M3内核的DCode总线与闪存存储器的数据接口相连接(常量加载和调试访问)。 系统总线连接Cortex™-M3内核的系统总线(外设总线)到总线矩阵,总线矩阵协调着内核和DMA间的访问。 总线矩阵协调内核系统总线和DMA主控总线之间的访问仲
[单片机]
<font color='red'>STM32F103</font>R6之系统架构
SHT11数字温湿度传感器
单片机源程序如下: #include reg52.h #include intrins.h #include LCD1602.h /******************************************************** 宏定义 ********************************************************/ #define uint unsigned int #define uchar unsigned char #define noACK 0 #define ACK 1 #define STATUS_REG_W 0x06 #define STATU
[单片机]
SHT11数字<font color='red'>温湿度</font><font color='red'>传感器</font>
STM32F103 UART 串口
USART 通用同步收发器,UART 通用异步收发器 支持LIN(局部互联网)、智能卡协议、IrDA(红外)、以及调制解调器(CTS/RTS)等。 全双工交换数据、即收发同时进行。 接口 三个引脚:接收数据输入(RX)、发送数据输出(TX)、地(GND)。 RX:接收数据串行输入。通过采样技术来区别数据和噪音,从而恢复数据。 TX:发送数据输出。当发送器禁止时,输出引脚恢复到它的IO端口配置。当发送器激活时,不发送数据,TX引脚处于高电平。 传送速率 1波特 = 1bps(位/秒) 常用有:4800、9600、19200、115200波特等。 协议 总线在发送或接收前应该处于空闲状态;一个起
[单片机]
<font color='red'>STM32F103</font> UART 串口
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved