当前位置:网站首页>传感器:SHT30温湿度传感器检测环境温湿度实验(底部附代码)
传感器:SHT30温湿度传感器检测环境温湿度实验(底部附代码)
2022-06-13 01:56:00 【Cheems_Pak Choi】
一、导言
SHT30温湿度传感器模块是通过IIC驱动,所以大家使用该模块时,需要具备IIC的基本知识,这篇文章带领大家一起使用SHT30模块进行温湿度的测量,当然DHT10/DHT10原理都一样,好了,一起来学习学习吧!
二、IIC知识
1、IIC总线介绍
I2C(Inter-Integrated Circuit)总线是由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。是微电子通信控制领域广泛采用的一种总线标准。它是同步通信的一种特殊形式,具有接口线少,控制方式简单,器件封装形式小,通信速率较高等优点。I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。由于其管脚少,硬件实现简单,可扩展性强等特点,因此被广泛的使用在各大集成芯片内。下面我们就从IIC的物理层和协议层来了解IIC
1.1、IIC物理层
物理层:
(1)它是一个支持多设备的总线
(2)I2C 总线只使用两条总线线路,SDA、SCL。
(3)每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。
(4)总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平。
(5)多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
(6)具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式下可达 3.4Mbit/s,但目前大多 I2C 设备尚
不支持高速模式。
(7)连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制。
1.2、IIC协议层
(1)数据有效性规定
如上图可以看到,当时钟线SCL为高电平时,并且SDA为高电平时,数据要求稳定,即不允许变化,SCL为高电平就是SDA的载体,当时钟线SCL为低电平时,这时候允许SDA的数据发生变化,即可以允许数据传送,所以通过时序图我们就能很好的进行编程,很容易上手IIC。(注意:每次传输都以字节为单位)
(2)开始信号和停止信号
如上图可以看到,当时钟线SCL为高电平时,并且SDA由高电平变为低电平,这时候表明已经启动了IIC,后面我们在程序中也是这样去进行设计,非常方便,灵位当时钟线SCL为高电平,并且SDA由低电平变为高电平,这时候表明已经停止了IIC。从这里大家可以看到,不管是开始IIC还是停止IIC,时钟线都是保持高电平才行,只有SDA的电平有变化。
(3)应答(ACK)与非应答信号(NACK)
如上图可以看到,当IIC启动之后,就开始传输数据,前面说过IIC传输是以字节为单位进行传输,例如一个字节8位,那么首先IIC先将8位进行传输,传输完成之后,后面紧跟着第9位,表示应答位,什么意思呢?也就是说只要一个字节8位必须正确按位传输,当传输完成之后,从机就会响应数据是否传输正确,如果正确,则从机响应应答信号,将SDA置为低电平表示应答,如果传输错误从机响应非应答信号,将SDA置为高电平,主机产生一个终止信号,终止本次数据的传输,然后主机再开启下一次传输。所以通过这个时序图可以看出,每一个字节传输完成之后,后面都需要紧跟着一个应答位/非应答位。
(4)总线的寻址方式
总线的寻址方式一般有两种,一种是7位寻址,另一种是10位寻址,通常采用7位进行寻址,也就是传输设备的地址是7位,7位寻址时序图如下:
如上图可以看到,总线传输是以字节传输,当以7位寻址的时候,前7位表示从机地址,第8位表示主机是写还是读;首先要清楚为什么要寻址(7位)?前面讲过,挂接在IIC总线上的设备有很多,这时候总线就会为挂接在总线上的设备分配唯一的地址,类似于路由器给连接在路由器上的WIFI设备分配不同且唯一的IP地址,所以主机就可以根据地址跟不同的设备进行通信,讲清楚了前7位,然后讲第8位;第8位表示从机是从主机接收数据,还是向主机写数据。
(5)总线的数据传输方式
I2C总线上传送的数据信号是广义的,既包括地址信号,又包括真正的数据信号。在起始信号后必须传送一个从机的地址(7位),第8位是数据的传送方向位(R/W),用“0”表示主机发送(写)数据(W),“1”表示主机接收数据(R)。每次数据传送总是由主机产生的终止信号结束。但是,若主机希望继续占用总线进行新的数据传送,则可以不产生终止信号,马上再次发出起始信号对另一从机进行寻址。如下所示:S表示IIC开始信号,0表示主机写入从机,1表示主机从从机读取,A表示应答信号,非A表示非应答信号,P表示停止信号
第一种传输方式:主机向从机发送数据,数据传输方向在整个传输过程不变
第二种传输方式:主机在传输第一个字节后,立即从从机读取数据
第三种传输方式:在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重
复产生一次,但两次读/写方向位正好反相
三、SHT30源代码
1、sht30.c源文件
/* 设定温度阈值范围:-20℃——125℃ 设定相对湿度范围:0%——100% */
#include"stm32f10x.h"
#include"sht30.h"
#include"stdio.h"
#define write 0 //IIC设备地址一般是7位,也有10位,本程序使用7位IIC设备地址,第8位是写命令
#define read 1 //IIC设备地址一般是7位,也有10位,本程序使用7位IIC设备地址,第8位是读命令
//IIC总线接口定义
#define SCL PBout(6)//设置时钟端口
//SHT30数据SDA传输口,有输出也有输入,所以需配置它的输入和输出
#define SDA_OUT PBout(7)//设置输出数据端口
#define SDA_IN PBin(7)//设置输入数据端口
//设置端口高8位的工作模式(具体可以参照端口位配置表),即I/O输入输出方向设置,先用与(&)对PB7引脚的四个位清0,再用或(|)置1
#define IIC_INPUT_MODE_SET() {
GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=8<<28;}//改变PB7对应位为1000(CNF[1:0]MODE[1:0]),设置成上拉或者下拉输入
#define IIC_OUTPUT_MODE_SET() {
GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=3<<28;}//改变PB7对应位为0011,设置成通用推挽输出
//#define IIC_INPUT_MODE_SET() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}//改变PB7对应位为1000(CNF[1:0]MODE[1:0]),设置成上拉或者下拉输入
//#define IIC_OUTPUT_MODE_SET() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}//改变PB7对应位为0011,设置成通用推挽输出
//定义温湿度存储变量
u8 humiture_buff1[20];
void SHT30_Init(void)//初始化SHT30的SCL与SDA接口
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE );
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;//定于SCL连接到STM32的PB6引脚上,定于SDA_OUT/SDA_IN连接到STM32的PB7引脚上
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
SCL=1;//根据SHT30时序要求,默认时序是高电平(SDA拉低时,SCL跟着拉低,开始数据的传输)
SDA_OUT=1;//高电平还未开始数据的传输,拉低时开始数据的传输
}
//主机发送确认字符ACK
void IIC_ACK(void)//IIC协议,需要主机发送确认字符ACK来判断数据是否接收无误
{
IIC_OUTPUT_MODE_SET();//配置PB7的SDA输出为推挽输出模式
SCL=0;
delay_us(2);
SDA_OUT=0;
delay_us(2);
SCL=1;//数据接收完成之后,将SCL拉高,以便与后面主机发送ACK给从机
delay_us(2);
SCL=0;//数据接收完成,主机发送ACK
delay_us(1);
}
//主机不发送确认字符ACK
void IIC_NACK(void)//IIC协议,数据传输未完成或者数据传输有误,主机不发送确认字符ACK
{
IIC_OUTPUT_MODE_SET();//配置PB7的SDA输出为推挽输出模式
SCL=0;
delay_us(2);
SDA_OUT=1;
delay_us(2);
SCL=1;
delay_us(2);
SCL=0;
delay_us(1);
}
//主机等待从机的确认字符ACK
u8 IIC_wait_ACK(void)//主机等待从机发送ACK,从而判断数据是否接收完成
{
u8 t = 200;
IIC_OUTPUT_MODE_SET();
SDA_OUT=1;//8位发送完后释放数据线,准备接收应答位
delay_us(1);
SCL=0;
delay_us(1);
IIC_INPUT_MODE_SET();
delay_us(1);
while(SDA_IN)//等待SHT30应答
{
t--;
delay_us(1);
if(t==0)
{
SCL=0;
return 1;
}
delay_us(1);
}
delay_us(1);
SCL=1;
delay_us(1);
SCL=0;
delay_us(1);
return 0;
}
//启动IIC总线进行通讯,发送IIC通讯的起始条件
void IIC_Start(void)//启动IIC通讯
{
IIC_OUTPUT_MODE_SET();//设置PB7的SDA为推挽输出
SDA_OUT=1;//根据SHT30时序,启动之前,SDA配置为高电平
SCL=1;根据SHT30时序,启动之前,SCL配置为高电平
delay_us(4);//延时4us,给硬件一个反应时间
SDA_OUT=0;//SDA引脚拉低,开始数据的传输
delay_us(4);
SCL=0;//SCL拉低,与SDA对应,响应SDA数据的拉低,表示正式开始数据的传输
}
//结束IIC总线通讯,发送IIC通讯的结束条件
void IIC_Stop(void)
{
IIC_OUTPUT_MODE_SET();
SCL=0;//结束IIC通讯之前,查看SCL是否是拉低状态
SDA_OUT=0;//结束IIC通讯之前,查看SDA是否是拉低状态
delay_us(4);
SCL=1;//将时钟拉高,表示已经结束IIC通讯
delay_us(4);
SDA_OUT=1;//将数据传输引脚拉高,表示正式结束数据的传输
delay_us(4);
}
//将byte数据发送出去
void IIC_SendByte(u8 byte)
{
u8 Count;
IIC_OUTPUT_MODE_SET();
SCL=0;//将时钟拉低,开始数据的传输
for(Count=0;Count<8;Count++)//要传送的数据长度为8位
{
if(byte&0x80) SDA_OUT=1;//判断发送位,发送位为1,则还未发送数据
else SDA_OUT=0; //判断发送位为0,则开始数据的发送
byte<<=1;
delay_us(2);
SCL=1;
delay_us(2);
SCL=0;
delay_us(2);
}
}
// 用来接收从器件传来的数据
u8 IIC_RcvByte(void)
{
u8 retc;
u8 Count;
retc=0;
IIC_INPUT_MODE_SET();//配置数据线为输入方式
delay_us(1);
for(Count=0;Count<8;Count++)
{
SCL=0;//配置时钟线为低,准备接收数据位
delay_us(2);
SCL=1;//配置时钟线为高使数据线上数据有效
retc=retc<<1;
if(SDA_IN) retc |=1;//读数据位,接收的数据位放入retc中
delay_us(1);
}
SCL=0;
return(retc);
}
//用来接收从器件采集并合成温湿度
void SHT30_read_result(u8 addr)
{
//SHT30有两种读取数值的方法,分别是状态查询和数值查询,这里我使用的是数值查询,发送指令为0x2C06
u16 tem,hum;//定义存放温湿度计算公式的变量
u16 buff[6];//定义6个字节的数组,存放温度高、低八位,湿度高、低八位,两个字节的CRC校验位
float Temperature=0;//定义存放温度拼接的变量Temperature,初始化温度为0
float Humidity=0;//定义存放湿度拼接的变量Humidity,初始化湿度为0
//发送指令为0x2C06(默认)
IIC_Start();
IIC_SendByte(addr<<1 | write);//写7位I2C设备地址加0作为写取位,1为写取位
IIC_wait_ACK();
// delay_us(1);
IIC_SendByte(0x2C);//前半段发送指令为0x2C
IIC_wait_ACK();
// delay_us(1);
IIC_SendByte(0x06);//后半段发送指令为0x06
IIC_wait_ACK();
// delay_us(1);
IIC_Stop();
delay_ms(50);
IIC_Start();
IIC_SendByte(addr<<1 | read);//写7位I2C设备地址加1作为读取位,1为读取位
//SHT30返回的数值是6个元素的数组
if(IIC_wait_ACK()==0)
{
// delay_us(1);
buff[0]=IIC_RcvByte();//返回温度高8位
IIC_ACK();
buff[1]=IIC_RcvByte();//返回温度低8位
IIC_ACK();
buff[2]=IIC_RcvByte();//温度crc校验位
IIC_ACK();
buff[3]=IIC_RcvByte();//返回湿度高8位
IIC_ACK();
buff[4]=IIC_RcvByte();//返回湿度低8位
IIC_ACK();
buff[5]=IIC_RcvByte();//湿度crc校验位
IIC_NACK();
IIC_Stop();
}
// tem = (buff[0]<<8) + buff[1];
// hum = (buff[3]<<8) + buff[4];
tem = ((buff[0]<<8) | buff[1]);//将buff[0]采集到的温度8位数据与buff[1]采集到的低8位数据相或,实现温度拼接
hum = ((buff[3]<<8) | buff[4]);//将buff[3]采集到的湿度8位数据与buff[4]采集到的低8位数据相或,实现湿度拼接
//查询SHT30数据手册可知,温湿度的计算方法如下
Temperature= 175.0*(float)tem/65535.0-45.0 ;// T = -45 + 175 * tem / (2^16-1)
Humidity= 100.0*(float)hum/65535.0;// RH = hum*100 / (2^16-1)
if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//设定温度和湿度的阈值,超过这个阈值则返回错误提示
{
printf("温度:%6.2f℃\r\n",Temperature);
printf("湿度:%6.2f%%\r\n",Humidity);
}
else
{
printf("温湿度超过给定阈值!\r\n");
}
hum=0;
tem=0;
}
2、sht30.h头文件
#ifndef _SHT30_H
#define _SHT30_H
#include "delay.h"
#include "sys.h"
#include "stdio.h"
#include "usart.h"
#include "string.h"
extern u8 humiture_buff1[20];
void SHT30_Init(void);
void IIC_ACK(void);//确认字符,表示发来的数据已经确认接收无误
void IIC_NACK(void);//无确认字符,表示数据接收有误或者还未接收完成
u8 IIC_wait_ACK(void);//等待接收确认字符
void IIC_Start(void);//等待IIC传输数据开始
void IIC_Stop(void);//IIC传输数据停止
void IIC_SendByte(u8 byte);//IIC发送数据
u8 IIC_RcvByte(void);//IIC接收数据
void SHT30_read_result(u8 addr);//SHT30温湿度传感器开始读取数据
#endif
3、main.c主函数
/* 本程序只供学习使用,未经作者许可,不得用于其他用途! 开 发 板:普中STM32-F1开发板 实验项目:基于STM32F103ZET6的SHT30温湿度检测实验 作 者:xxx//姓名暂时隐藏,有问题可以联系我下面邮箱 邮 箱:[email protected] 日 期:2022年06月08日 版权所有,盗版必究。 */
#include"stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "SHT30.h"
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
delay_init(); //延时函数初始化
uart_init(9600); //串口初始化为9600
SHT30_Init();//初始化SHT30
printf("SHT30初始化正常,已准备就绪!\r\n");
while(1)
{
SHT30_read_result(0x44);//ADDR寄存器,地址选择引脚,接GND地址为0x44,接VDD地址为0x45
delay_ms(1000);
}
}
四、总结
1、时序图一定要去认真看懂,对应的源代码程序都是按照时序图一步一步去搭建的,如果自己私下里搭建的时候遇到错误,再返回来看看我的程序怎么去搭建的。
2、源代码中以下三个头文件的源代码我没有给大家贴出来:
#include “delay.h”
#include “sys.h”
#include “usart.h”
首先delay只是为了延时,然后sys只是系统配置,最后usart只是为了打印,所以这三个文件大家可以参考其他机构写的代码,例如正点原子
3、大家只有从底层去了解IIC,才能很好的掌握IIC,目前很多图形化界面,例如:STM32CubeMX就不需要手动去写IIC,直接在软件上配置即可。
4、温度和湿度转换公式已经贴在sht30.c文件里,大家也可以查看sht30官方推出的数据手册查看
5、文章开头IIC原理大家一定要认真看,每个字每个字认真看,我相信你看了会对IIC的认识更深一点
边栏推荐
- Devaxpress Chinese description --tcxpropertiesstore (property store recovery control)
- Pyflink implements custom sourcefunction
- rsync 传输排除目录
- 移动IPv6光猫登录的一般ip地址账号与密码,移动光猫变桥接模式
- Magics 23.0如何激活和使用视图工具页的切片预览功能
- 6、 Implementation of warehouse out management function
- Plumber game
- 4、 Improvement of warehousing management function
- Detailed explanation of audience characteristics
- 微服务开发环境搭建
猜你喜欢
Numpy multidimensional array transpose transpose
Introduction to ROS runtime
微服务开发环境搭建
10 days based on stm32f401ret6 smart lock project practice day 1 (environment construction and new construction)
Calculation of accuracy, recall rate, F1 value and accuracy rate of pytorch prediction results (simple implementation)
Devexpress implementation flow chart
General IP address, account and password of mobile IPv6 optical cat login, and mobile optical cat is in bridging mode
Learning notes 51 single chip microcomputer keyboard (non coding keyboard and coding keyboard, scanning mode of non coding keyboard, independent keyboard, matrix keyboard)
白噪声的详细理解
Ruixing coffee moves towards "national consumption"
随机推荐
TensorFlow 2.x 多显卡分布式训练
Ten thousand words make it clear that synchronized and reentrantlock implement locks in concurrency
What is Google plus large text ads? How to use it?
路径字段是什么? ——竞价广告
leetcode743. Network latency (medium, Dijkstra)
[wsl2] restrict wsl2 accessible hardware resources (cpu/ memory)
Alertwindowmanager pop up prompt window help (Part 1)
Decoding iFLYTEK open platform 2.0 is a fertile land for developers and a source of industrial innovation
Simple ranging using Arduino and ultrasonic sensors
General IP address, account and password of mobile IPv6 optical cat login, and mobile optical cat is in bridging mode
Devaxpress Chinese description --tcxpropertiesstore (property store recovery control)
Magics 23.0如何激活和使用视图工具页的切片预览功能
Installing pytorch geometric
Using OpenCV in go
谷歌加大型文字广告是什么?怎么用?
Stone from another mountain: Web3 investment territory of a16z
rsync 传输排除目录
[pytorch FAQ] numpy:dll load failed while importing_ multiarray_ Umath: the specified module could not be found.
Vscode configuration header file -- Take opencv and its own header file as an example
三、上传织物图片至SQL Server并提供name进行展示织物照片