STM32使用HAL库编写SHT2x温湿度传感器驱动
温湿度传感器在嵌入式开发中应用场景非常多。本文主要利用STM32及HAL库完成SHT2x温湿度传感器温湿度值得读取及将值通过串口打印出来。
一、SHT20芯片芯片介绍
1、官方收据手册可以该网站下载:数字温湿度传感器 SHT2X-深圳市森思德克科技有限公司
该网站提供的手册为英文的,该芯片使用较多,通过百度也能找到中文的。
2、SHT20 配有一个全新设计的 CMOSens®芯片、一 个经过改进的电容式湿度传感元件和一个标准的能 隙温度传感元件。(这段摘自数据手册)
二、芯片技术手册读到可能对后续编程有用的信息
1、该芯片采用数字输出,I2C接口,低功耗。
2、SHT20的分辨率可以通过输入命令进行改变(8/12bit乃至12/14bit的RH/T)。RH代表湿度,T代表温度。
3、默认测量分辨率14bit(温度)/12bit(湿度),可通过寄存器发送命令将其减少到12/8bit,11/11bit,13/10bit。
4、温湿度测量频率过高,传感器自身温度会升高而影响精度。
5、接口定义
6、传感器通讯流程如下
(1)启动传感器:将传感器上电后,传感器最多需要15毫秒时间(此时SCL为高电平)以达到空闲状态,即做好准备接收由主机MCU发送的命令。
(2)启动/停止时序:参照标准I2C总线。
(3)在启动传输后,随后传输的I2C首字节应包括7位的I2C设备地址和一个SDA方向位(读:1,写:0)。等待应答后,发送温度或湿度的测量命令。
(4)传感器地址由厂商写死的,I2C 设备地址( 地址‘1000’000’)和一个 SDA
方向位(读 R: ‘1’,写 W: ‘0’)。
7、基本命令集
命令 | 释义 | 代码 | 十六进制 |
触发 T 测量 | 保持主机 | 1110’0011 | 0XE3(主机模式) |
触发 RH 测量 | 保持主机 | 1110’0101 | 0XE5(主机模式) |
触发 T 测量 | 非保持主机 | 1111’0011 | 0XF3(非主机模式) |
触发 RH 测量 | 非保持主机 | 1111’0101 | 0XF5(非主机模式) |
写用户寄存器 | 1110’0110 | 0XE6 | |
读用户寄存器 | 1110’0111 | 0XE7 | |
软复位 | 1111’1110 | 0XFE |
8、主机/非主机模式
(1)MCU与传感器之间的通讯有两种不同的工作方式:主机模式或非主机模式。
(2)在主机模式下,在测量过程中,SCL线被封锁(由传感器进行控制)。在非主机模式下,当传感器执行测量任务时,SCL线仍然保持开放状态,可进行其他通讯。非主机模式允许传感器进行测量时在总线上处理其他I2C总线通讯任务。
(3)在主机模式测量时,SHT2x将SCL拉低强制主机进入等待状态。通过释放SCL线,表示传感器内部处理工作结束,进而可以继续数据传送。
第一步:发送起始信号→
第二步:发送传感器写地址→
第三步骤:等待传感器应答→
第四步:发送测量信号命令→
第五步骤:等待传感器应答→
第六步:发送起始信号→
第七步:发送传感器读地址→
第八步:等待传感器应答→
第九步:测量期间保持(延时一会)→
第十步:接收数据高八位,主机发送应答→
第十一步:接收数据低八位,主机发送应答→
第十二步:接收校验码值→主机发送NACK、P(传输停止时序)。
由于测量的最大分辨率为14位,第二字节SDA上的后两位(bit43和bit44)用来传输相关的状态信息。
后两位即LSB Stat简称 LSBs 。两个LSBs中的bit1表明测量的类型('0':温度, '1':湿度)。bit0位当前没有赋值。(这点非主机模式也是这种)
(4)在非主机模式时,MCU需要对传感器状态进行查询。主机发送一个启动传输时序,之后发送读地址( 1000’0001)。如果内部处理工作完成,单片机查询到传感器发出的确认信号后,相关的数据就可以通过MCU进行读取。如果测量处理工作没有完成,传感器无确认位(ACK)输出,此时必须重新发送启动传输时序。
9、软复位
三、I2C代码
1、头文件
#ifndef __DRV_SHT2x_I2C_H
#define __DRV_SHT2x_I2C_H/*头文件包含*/
#include "drv_gpio.h"
#include "drv_i2c.h" /*包含uS级延时函数*//*宏定义*/
/*置位与清零SCL管脚*/
#define __SHT2X_I2C_SCL_H() HAL_GPIO_WritePin(SHT_SCL_GPIO_Port,SHT_SCL_Pin,GPIO_PIN_SET)
#define __SHT2X_I2C_SCL_L() HAL_GPIO_WritePin(SHT_SCL_GPIO_Port,SHT_SCL_Pin,GPIO_PIN_RESET)
/*置位与清零SDA管脚*/
#define __SHT2X_I2C_SDA_H() HAL_GPIO_WritePin(SHT_SDA_GPIO_Port,SHT_SDA_Pin,GPIO_PIN_SET)
#define __SHT2X_I2C_SDA_L() HAL_GPIO_WritePin(SHT_SDA_GPIO_Port,SHT_SDA_Pin,GPIO_PIN_RESET)
/*读取SDA管脚状态*/
#define __SHT2X_READ_I2C_SDA() HAL_GPIO_ReadPin(SHT_SDA_GPIO_Port,SHT_SDA_Pin)
/*读取SCL管脚状态*/
#define __SHT2X_READ_I2C_SCL() HAL_GPIO_ReadPin(SHT_SCL_GPIO_Port,SHT_SCL_Pin)/*设置SDA管脚为输出模式*/
#define __SHT2X_I2C_SDA_OUT() SHT_SDA_OutputMode()
/*设置SDA管脚为输入模式*/
#define __SHT2X_I2C_SDA_INPUT() SHT_SDA_InputMode()/*函数声明*/
void SHT_SDA_OutputMode(); /*设置SHT_SDA管脚为输出模式*/
void SHT_SDA_InputMode(void); /*设置SHT_SDA管脚为输入模式*/
void SHT2X_I2C_Init(void); /*SHT_SDA和SHT_SCL引脚电平初始化*/
void SHT2X_I2C_Start(void); /*sht2x_I2C总线起始信号时序*/
void SHT2X_I2C_Stop(void); /*sht2x_I2C总线停止信号时序*/
uint8_t SHT2X_I2C_Wait_Ack(void); /*IIC等待应答信号,1接收应答失败,0接收应答成功*/
void SHT2X_I2C_Ack(void); /*IIC产生应答*/
void SHT2X_I2C_NAck(void); /*IIC不产生应答*/
void SHT2X_I2C_Write_Byte(uint8_t Byte); /*SHT2X_I2C总线写字节时序*/
uint8_t SHT2X_I2C_Read_Byte(I2C_ACK_TypeDef AckValue); /*SHT2X_I2C总线读字节时序*/#endif
2、C文件
#include "drv_sht2x_i2c.h"/**功能:设置SHT_SDA管脚为输出模式*参数:无*返回值:无*/
void SHT_SDA_OutputMode()
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = SHT_SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; /*输出模式*/GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}/**功能:设置SHT_SDA管脚为输入模式*参数:无*返回值:无*/
void SHT_SDA_InputMode(void)
{GPIO_InitTypeDef GPIO_InitStruct = {0};GPIO_InitStruct.Pin = SHT_SDA_Pin; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; /*输入模式*/GPIO_InitStruct.Pull = GPIO_NOPULL;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}/**功能:SHT_SDA和SHT_SCL引脚电平初始化*参数:无*返回值:无*测试:OK*/
void SHT2X_I2C_Init(void)
{__SHT2X_I2C_SCL_H();__SHT2X_I2C_SDA_H();HAL_Delay(15); /*延时15mS*/
}/**功能:sht2x_I2C总线起始信号时序*参数:无*返回值:无*注意:开始状态是由主机控制的一种特殊总线状态,指示从机传输开始(Start之后,BUS总线一般被认为处于占线状态)*/
void SHT2X_I2C_Start(void)
{__SHT2X_I2C_SDA_OUT(); /*SDA配置为输出模式*//*SCL为高电平,SDA的下降沿为I2C起始信号*/__SHT2X_I2C_SDA_H();__SHT2X_I2C_SCL_H();I2C_Delay_us(20);__SHT2X_I2C_SDA_L();I2C_Delay_us(20);__SHT2X_I2C_SCL_L();
}/**功能:sht2x_I2C总线停止信号时序*参数:无*返回值:无*注意:停止状态是由主机控制的一种特殊的总线状态,指示从机传输结束(Stop之后,BUS总线一般被认为处于空闲状态)*/
void SHT2X_I2C_Stop(void)
{__SHT2X_I2C_SDA_OUT();/*SCL为高电平,SDA的上升沿为I2C停止信号*/__SHT2X_I2C_SDA_L();__SHT2X_I2C_SCL_H();I2C_Delay_us(1);I2C_Delay_us(10);__SHT2X_I2C_SDA_H();
}/**功能:IIC等待应答信号*参数:无*返回值:1接收应答失败,0接收应答成功*/
uint8_t SHT2X_I2C_Wait_Ack(void)
{uint8_t ucErrTime = 0;SHT_SDA_InputMode(); __SHT2X_I2C_SDA_H();I2C_Delay_us(10);__SHT2X_I2C_SCL_H();I2C_Delay_us(10);while(__SHT2X_READ_I2C_SDA()){ucErrTime++;if(ucErrTime > 250){SHT2X_I2C_Stop();return NACK;}}__SHT2X_I2C_SCL_L(); return ACK;
}/**功能:IIC产生应答*/
void SHT2X_I2C_Ack(void)
{__SHT2X_I2C_SCL_L();__SHT2X_I2C_SDA_OUT();__SHT2X_I2C_SDA_L();I2C_Delay_us(20);__SHT2X_I2C_SCL_H();I2C_Delay_us(20);__SHT2X_I2C_SCL_L();
}/**功能:IIC不产生应答*/
void SHT2X_I2C_NAck(void)
{__SHT2X_I2C_SCL_L();__SHT2X_I2C_SDA_OUT();__SHT2X_I2C_SDA_H();I2C_Delay_us(20);__SHT2X_I2C_SCL_H();I2C_Delay_us(20);__SHT2X_I2C_SCL_L();
}/**功能:SHT2X_I2C总线写字节时序*参数:Byte:写入的内容*测试:OK*/
void SHT2X_I2C_Write_Byte(uint8_t Byte)
{__SHT2X_I2C_SDA_OUT(); /*SDA配置为输出模式*//*SCL为低电平时,SDA准备数据,接着SCL为高电平,读取SDA数据*/for (uint8_t i = 0; i < 8; i++){/*SCL清零,主机SDA准备数据*/__SHT2X_I2C_SCL_L();I2C_Delay_us(1);if((Byte & (1 << 7)) == (1 << 7)){__SHT2X_I2C_SDA_H();}else{__SHT2X_I2C_SDA_L();}I2C_Delay_us(1);/*SCL置高,传输数据*/__SHT2X_I2C_SCL_H();I2C_Delay_us(10);/*准备发送下一比特位*/Byte <<= 1;}__SHT2X_I2C_SCL_L();
}/**功能:SHT2X_I2C总线读字节时序*参数:*返回值:读取到的数据*测试:OK*/
uint8_t SHT2X_I2C_Read_Byte(I2C_ACK_TypeDef AckValue)
{uint8_t byte = 0;__SHT2X_I2C_SDA_INPUT();/*SCL为低电平时,SDA准备数据,接着SCL为高电平,读取SDA数据*/for (uint8_t i = 0; i < 8; i++){/*准备接收下一比特位*/byte <<= 1;/*SCL清零,从机SDA准备数据*/__SHT2X_I2C_SCL_L();I2C_Delay_us(10);/*SCL置高,获取数据*/__SHT2X_I2C_SCL_H();I2C_Delay_us(10); byte |= __SHT2X_READ_I2C_SDA(); }/*SCL清零,主机准备应答信号*/__SHT2X_I2C_SCL_L();I2C_Delay_us(1);__SHT2X_I2C_SDA_OUT();/*主机发送应答信号*/ if(AckValue == ACK){__SHT2X_I2C_SDA_L();}else{__SHT2X_I2C_SDA_H(); }I2C_Delay_us(1);__SHT2X_I2C_SCL_H(); I2C_Delay_us(10);/*SCL先清零,再释放SDA,防止连续传输数据时,从机错将SDA释放信号当成NACk信号*/__SHT2X_I2C_SCL_L();__SHT2X_I2C_SDA_H(); I2C_Delay_us(1);/*返回数据*/return byte;
}
四、SHT2x代码
1、头文件
#ifndef __SHT2_H
#define __SHT2_H/*头文件包含*/
#include "main.h"/*宏定义*/
#define SHT2x_ADDR_READ 0x81 /*传感器i2C读地址*/
#define SHT2x_ADDR_WRITE 0x80 /*传感器I2C写地址*//*测量信号的选择*/
typedef enum{HUMIDITY, /*选择湿度*/TEMP /*选择温度*/
}etSHT2xMeasureType; /* *功能:传感器命令 *TRIG:触发(trigger) *MEASUREMENT:测量*HM:hold master*/
typedef enum{/*主机模式*/TRIG_T_MEASUREMENT_HM = 0xE3, /*触发温度测量,主机模式*/TRIG_RH_MEASUREMENT_HM = 0xE5, /*触发湿度测量,主机模式*//*非主机模式*/TRIG_T_MEASUREMENT_POLL = 0xF3, /*触发温度测量,非保持主机*/TRIG_RH_MEASUREMENT_POLL = 0xF5, /*触发湿度测量,非保持主机*/USER_REG_W = 0xE6, /*command writing user register(写用户寄存器)*/USER_REG_R = 0xE7, /*command reading user register(读用户寄存器)*/SOFT_RESET = 0xFE /*command soft reset(软件复位)*/
}etSHT2xCommand;/*函数声明*/
float SHT2x_MeasurePoll(etSHT2xMeasureType SHT2xMeasureType); /*非主机模式采集温度或湿度*/#endif
2、C文件
/**文件:SHT2x.c *功能:温湿度采集程序*//*头文件包含*/
#include "SHT2x.h"
#include "drv_uart.h"
#include "drv_sht2x_i2c.h"/**功能:非主机模式采集温度或湿度*参数:SHT2xMeasureType:需要采集的项,HUMIDITY湿度 TEMP温度*返回值:读到的温湿度值
*/
float SHT2x_MeasurePoll(etSHT2xMeasureType SHT2xMeasureType)
{float temp; /*临时变量*/unsigned char MSB,LSB; /*存储测量值的高八位和低八位*/float Humidity,Temperature;SHT2X_I2C_Start(); /*sht2x_I2C总线起始信号时序*/SHT2X_I2C_Write_Byte(SHT2x_ADDR_WRITE); /*sht2x_I2C总线写传感器写地址*/if(SHT2X_I2C_Wait_Ack() == ACK) /*写写地址等待应答*/ {switch(SHT2xMeasureType) { case HUMIDITY: /*湿度*/ SHT2X_I2C_Write_Byte(TRIG_RH_MEASUREMENT_POLL); /*非主机模式测湿度命令*/ break; case TEMP: /*温度*/ SHT2X_I2C_Write_Byte(TRIG_T_MEASUREMENT_POLL); /*非主机模式测温度命令*/break; default: printf("Tip: SHT2x_MeasurePoll function error.\r\n");break;}if(SHT2X_I2C_Wait_Ack() == 0) /*非主机模式测温湿度指令应答*/ {HAL_Delay(85); /*延时等待测量完成*/SHT2X_I2C_Start(); SHT2X_I2C_Write_Byte(SHT2x_ADDR_READ); /*sht2x_I2C总线写传感器读地址*/if(SHT2X_I2C_Wait_Ack() == 0) /*写读地址等待应答*/{MSB = SHT2X_I2C_Read_Byte(ACK);LSB = SHT2X_I2C_Read_Byte(ACK);SHT2X_I2C_Read_Byte(NACK); SHT2X_I2C_Stop();LSB &= 0xfc;temp = MSB*256 + LSB;if (SHT2xMeasureType == HUMIDITY){ Humidity =(temp*125)/65536-6;//printf("Humidity = %.2f\r\n",Humidity);return Humidity;} else { Temperature = (temp*175.72)/65536-46.85;//printf("Temperature = %.2f\r\n",Temperature);return Temperature; }}}}printf("Tip: SHT2x_MeasurePoll error\r\n");return 0XFF; /*表示出错了*/}
五、测试
float Humidity,Temperature; //定义温度和湿度变量
while (1){/*Test*/Temperature = SHT2x_MeasurePoll(TEMP); /*非主机模式采集温度*/printf("Temperature%.2f\r\n",Temperature);Humidity = SHT2x_MeasurePoll(HUMIDITY); /*非主机模式采集湿度*/printf("Humidity = %.2f\r\n",Humidity);HAL_Delay(1000);
}
STM32使用HAL库编写SHT2x温湿度传感器驱动相关推荐
- 【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(一)
前言: 本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 本文 1首先讲解什么是FMC及SDRAM,W9825G6KH芯片原理,2基于CubeMx创建工程 ...
- 【STM32】HAL库 STM32CubeMX教程十四---SPI
前言: 本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 在我们的HAL库中,对硬件SPI函数做了很好的集成,使得之前SPI几百行代码,在HAL库中,只需 ...
- stm32 ADC hal库实现
stm32 ADC hal库实现 1.ADC的作用 (1)简介: ADC(Analog-to-Digital Converter),即模拟-数字转换器,可以将连续变化的模拟信号转换为离散的数字信号,进 ...
- STM32的HAL库分析及使用
STM32的三种开发方式 通常新手在入门STM32的时候,首先都要先选择一种要用的开发方式,不同的开发方式会导致你编程的架构是完全不一样的.一般大多数都会选用标准库和HAL库,而极少部分人会通过直接配 ...
- STM32之HAL库详解 及 手动移植
转载出处:http://blog.csdn.net/zcshoucsdn/article/details/55213616 HAL库结构 说到STM32的HAL库,就不得不提STM32CubeMX ...
- 正点原子STM32(基于HAL库)0
目录 开发环境搭建与使用 常用开发工具简介 MDK 安装 仿真器驱动安装 CH340 USB 虚拟串口驱动安装 使用MDK5 编译例程 使用串口下载程序 使用DAP 下载与调试程序 使用DAP 下载程 ...
- STM32CubeMX | 基于STM32使用HAL库实现USB组合设备之多路CDC
STM32CubeMX | 基于STM32使用HAL库实现USB组合设备之多路CDC 本博客完整代码下载地址:https://download.csdn.net/download/qq15347150 ...
- 正点原子STM32(基于HAL库)5
目录 SRAM 实验 存储器简介 SRAM 方案简介 硬件设计 程序设计 程序流程图 程序解析 下载验证 内存管理实验 内存管理简介 硬件设计 程序设计 程序流程图 程序解析 下载验证 SD 卡实验 ...
- 【STM32】HAL库 STM32CubeMX教程十五---FMC-SDRAM(二)
前言: 本系列教程将HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 上一讲我们说了CubeMX配置SDRAM的一些基本配置,还有FMC跟SDRAM的讲解,这一讲我们 ...
最新文章
- oracle 64位客户端_oracle的管理工具toad如何设置命令补全
- 如何从 dump 文件中提取出 C# 源代码?
- java离职交接文档_财务人员工作交接你知道么?没处理好不止将来风险大还可能违法...
- vscode输入vue自动_使用vscode,新建.vue文件,tab自动生成vue代码模板
- 【linux指令】sed指令
- lol游戏挂机软件_直男玩家吐槽LOL手游:挂机,送头,队友菜
- orcale物化视图刷新
- 自己动手写操作系统(高清图书+源代码)分享
- 微信公众开发java教程_[Java教程]微信公众平台开发(一)
- php 扫描条形码,将条形码扫描仪集成到PHP应用程序中?
- 手机微信连不上wifi服务器怎么回事,微信连不上wifi怎么办?
- SQL1005N 数据库别名 ECM 已存在于本地数据库目录或系统数据库目录中。
- 明大推荐系统导论笔记 week 2
- LeetCode算法解析之“箭爆气球问题”
- 平板为何无法用无线网连接媒体服务器,我家装了无线路由器后,台式机老是断网但是平板电脑却能连接无线网络上网...
- Fllutter TabBar中文文字抖动完美解决方案
- ssm毕设项目磐基建筑机械租赁有限公司机械租赁系统41c32(java+VUE+Mybatis+Maven+Mysql+sprnig)
- MySQL审核神器Inception
- 事务(Transaction)的特性
- tensorflow2.0学习经历:建立一个多元函数拟合模型并移植到ESP32(Arduino IDE)