STM32之模拟IIC总线控制SHT20温湿度芯片

2024-01-07 17:44

本文主要是介绍STM32之模拟IIC总线控制SHT20温湿度芯片,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、IIC总线概述

1、IIC总线介绍

I2C (Inter-Integrated Circuit)总线产生于在80年代, 由PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备, 最初为音频和视频设备开发。I2C总线两线制包括:串行数据SDA(Serial Data)、串行时钟SCL(Serial Clock)。时钟线必须由主机(通常为微控制器)控制,主机产生串行时钟(SCL)控制总线的传输方向,并产生起始和停止条件。I2C总线上有主机(MCU)和从机(片外外设,如AT24C02)之分,可以有多个主机和多个从机。从机永远不会主动给主机发送数据。器件发送数据到总线上,则定义为发送器,器件接收数据则定义为接收器。主器件和从器件都可以工作于接收和发送状态。

USART : 异步串行全双工

SPI: 同步串行全双工

IIC:同步串行半双工

挂载在同一根IIC总线上可以有多个设备,有主机和从机之分

2、IIC总线物理拓扑图

3、IIC总线主从设备通信

SPI如何解决从多个从机中选择一个通信:片选线

IIC如何解决从多个从机中选择一个通信: 器件地址

首先向外界发出一个器件地址

所有挂载在这个总线上的设备都可以接收到这个地址

设备获取到这个器件地址后和本身的地址作比较

匹配的设备就会接下来接收主机发出的数据

其他设备重新处于休眠状态

器件地址:一般是7位的硬件地址 + 1位的读写位

IIC通信规定一次发送的数据是8位的

针对主机而言:

写(向外界发送数据):0

读(从外界接收数据):1

4、IIC总线与UART比较

通讯协议UARTIICSPI
特征异步串行全双工同步串行半双工同步串行全双工
接口TX、RXSDA、SCLMOSI、MISO、CS、SCK
速度波特率很多100Khz、400Khz、3.5MhzMhz级以上
数据帧格式起始位+数据位+校验位+停止位起始条件+位传输+应答+停止条件四种MODE0-3
主从设备通讯没有主从之分有主从之分有主从之分
总线结构一对一一对多一对多
发送数据顺序先发低位再发高位先发高位再发低位

先发高位再发低位

SPI控制器可以选择先低后高还是先高后低

二、IIC总线数据

1、IIC数据帧的格式

起始条件(告诉接收方要开始发送数据了):在时钟线高电平期间,数据线产生下降沿

数据的传输:时钟线低电平期间发送数据,高电平期间接收数据,需要给一定的时间让数据可以发送和接收

高位先发,8位数据的发送

应答位:1个位的数据,代表当前有没有受到数据,是接收方回发给发送方的

(0)应答:代表接收到数据并且可以继续发送

(1)非应答:代表当前不能再接受数据了

停止条件(代表一次通信结束):在时钟线高电平期间,数据线产生上升沿

2、标准IIC时序(100khz)

1、起始条件
SDA = 1;
SCL = 1;
Delay_us(4);//起始条件的建立时间
SDA = 0;
Delay_us(4);//起始条件的保持时间
SCL = 0;//一个完整的时钟周期

2、停止条件
SDA = 0;
SCL = 1;
Delay_us(4);//停止条件的建立时间
SDA = 1;
Delay_us(4);//停止和启动条件之间的总线空闲时间

3、位传输
高位先发,高电平期间接收数据,低电平期间发送数据

主机发送数据(发送的是写方向):
for( i = 0 ; i < 8; i++)
{
        SCL = 0;
        SDA = 0/1;
        Delay_us(4);//主机发送数据的时间
        SCL = 1;
        Delay_us(4);//从机接收数据的时间
}

主机接收数据:(发送的是读方向)
for( i = 0 ; i < 8; i++)
{
        SCL = 0;
        Delay_us(4);//从机发送数据的时间
        SCL = 1;
        if(SDA)
        {
                Data |= 1;
        }
        Delay_us(4);//主机接受数据的时间
}

4、应答

主机发送一个应答位:
    SCL = 0;
    SDA = 0/1;
    Delay_us(4);//主机发送数据的时间
    SCL = 1;
    Delay_us(4);//从机接收数据的时间
    SCL = 0;
    Delay_us(4);//保证周期的完整性


主机接收一个应答位:
    SCL = 0;
    Delay_us(4);//从机发送数据的时间
    SCL = 1;
    if(SDA)
    {
        Data = 1;
    }
    Delay_us(4);//主机接受数据的时间
    SCL = 0;
    Delay_us(4);//保证周期的完整性
 

三、SHT20温湿度芯片

1、硬件:

相对湿度的误差在±3

湿度范围:0 - 100%

温度的误差在±0.3摄氏度

温度范围:-40 - 125摄氏度

管脚说明:

SCL: IIC通信的时钟线

SDA: IIC通信的数据线

SHT20采用IIC的400kHZ的通信速率

测量温度的命令:0xf3

测量湿度的命令:0xf5

器件地址 + 写方向:0x80

器件地址 + 写方向:0x81

2、软件:

通信步骤:
1. 传感器上电,最多等待15ms的时间再去发送相应的命令
2. 发送器件地址 + 方向位以及相应的命令去触发测量

3、时序

起始条件--->发送器件地址 + 写方向(0x80) --> 如果通信正常则回应答位 --> 发送测量温湿度数据的命令-->

起始条件--->不断发送发送器件地址 + 读方向(0x81)直到回了一个应答才停止发送器件地址 + 读方向(0x81)-->如果回了应答就可以接收从机发过来的数据(16位构成的),需要接收两次才完整,先发送过来的数据是16位数据中的高八位----->接受完16位的数据主机发送非应答告诉SHT20不用再回发数据---->停止条件

注意:接收回来的16位数据中最低两位要清零

起始条件 ---->发送器件地址 + 写方向(0x80)---->等待sht20应答 ---->发送软复位指令(0xfe)等待sht20应答 ---->停止条件

写用户寄存器:

起始条件 ---->发送器件地址 + 写方向(0x80)---->等待sht20应答 ---->发送0xe6告诉SHT20要往用户寄存器里写值----> 等待sht20应答 ---->发送需要写到里面的值---->等待sht20应答 ----->停止条件

RH  = -6 + 125 * Srh / 65536

T = -46.85 + 175.72 * St / 65536

初始化GPIO口

PB8 -- SCL -- 推挽输出

PB9 -- SDA

输入输出模式切换

SDA线既可以接收数据也可以发送数据

输入模式的时候不能输出数据

输出模式的时候可以读取数据

开漏输出

开漏输出:只能输出低电平

如果输出高电平就是断开输出电路

#include "iic.h"
/****************************
函数功能:初始化IIC总线的IO口
函数形参:void
函数返回值:void
函数说明:
PB8 -- SCL -- 推挽输出
PB9 -- SDA 
1.输入输出模式切换
SDA线既可以接收数据也可以发送数据
输入模式的时候不能输出数据
输出模式的时候可以读取数据
2.开漏输出
开漏输出:只能输出低电平
如果输出高电平就是断开输出电路
****************************/
void Iic_PortInit(void)
{GPIO_InitTypeDef  GPIO_InitStruct;//定义了一个结构体变量//1. 打开GPIOB的时钟RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//2. 配置GPIO口功能GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;//配置输出模式GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;//配置为推挽GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;//选择8号管脚GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;//无上下拉GPIO_InitStruct.GPIO_Speed = GPIO_Low_Speed;//低速GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;//配置为开漏GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;//选择9号管脚GPIO_Init(GPIOB, &GPIO_InitStruct); }/****************************
函数功能:起始条件
函数形参:void
函数返回值:void
函数说明:在时钟线高电平期间,数据线产生下降沿
****************************/
void IIC_Start(void)
{SDA_H;SCL_H;Delay_Us(4);//起始条件的建立时间SDA_L; Delay_Us(4);//起始条件的保持时间SCL_L;//保证周期完整
}/****************************
函数功能:停止条件
函数形参:void
函数返回值:void
函数说明:在时钟线高电平期间,数据线产生上升沿
****************************/
void IIC_Stop(void)
{SDA_L;SCL_H;Delay_Us(4);//停止条件的建立时间SDA_H;Delay_Us(4);//停止和启动条件之间的总线空闲时间
}/****************************
函数功能:发送应答位
函数形参:u8 ack
函数返回值:void
函数说明:0:代表应答1:代表非应答
****************************/
void Send_Ack(u8 ack)
{SCL_L;//发送方准备发送数据if(ack){SDA_H;}else{SDA_L;}Delay_Us(4);//发送数据所需要的时间SCL_H;Delay_Us(4);//接收数据所需要的时间SCL_L;Delay_Us(4);//保证一个完整的周期}/****************************
函数功能:接收应答位
函数形参:void
函数返回值:u8
函数说明:0:代表应答1:代表非应答
****************************/
u8 Receive_Ack(void)
{u8 ack = 0;SDA_H;//断开输出电路SCL_L;//发送方准备发送数据Delay_Us(4);//发送数据所需要的时间SCL_H;if(SDA){ack = 1;}Delay_Us(4);//接收数据所需要的时间SCL_L;Delay_Us(4);//保证一个完整的周期return ack;
}/****************************
函数功能:发送一个字节并接收一个应答位
函数形参:u8 data
函数返回值:u8
函数说明:0:代表应答1:代表非应答
****************************/
u8 Send_Byte_Receive_Ack(u8 data)
{u8 i,ack = 0;for(i = 0; i < 8; i++){SCL_L;//发送方准备发送数据//1100 0011//0100 0000if(data & 0x80 >> i){SDA_H;}elseSDA_L;Delay_Us(4);//发送数据所需要的时间SCL_H;Delay_Us(4);//接收数据所需要的时间}ack = Receive_Ack();return ack;
}/****************************
函数功能:接收一个字节并发送一个应答位
函数形参:u8 data
函数返回值:u8
函数说明:0:代表应答1:代表非应答
****************************/
u8 Receive_Byte_Send_Ack(u8 ack)
{u8 i = 0;u8 data = 0;for(i = 0; i < 8; i++){SCL_L;//发送方准备发送数据Delay_Us(4);//发送数据所需要的时间SDA_H;//断开输出电路SCL_H;data <<= 1;//空出最低位if(SDA){data |= 1;}Delay_Us(4);//接收数据所需要的时间}Send_Ack(ack);return data;
}
#ifndef __IIC_H_
#define __IIC_H_#include "stm32f4xx.h"
#include "delay.h"#define SCL_H  GPIO_SetBits(GPIOB,GPIO_Pin_8)
#define SCL_L  GPIO_ResetBits(GPIOB,GPIO_Pin_8)
#define SDA_H  GPIO_SetBits(GPIOB,GPIO_Pin_9)
#define SDA_L  GPIO_ResetBits(GPIOB,GPIO_Pin_9)
#define SDA    GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)void Iic_PortInit(void);
void IIC_Start(void);
void IIC_Stop(void);
u8 Send_Byte_Receive_Ack(u8 data);
u8 Receive_Byte_Send_Ack(u8 ack);#endif

完整版代码例程在

【免费】STM32控制SHT20温湿度芯片资源-CSDN文库

这篇关于STM32之模拟IIC总线控制SHT20温湿度芯片的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/580742

相关文章

Spring Boot集成/输出/日志级别控制/持久化开发实践

《SpringBoot集成/输出/日志级别控制/持久化开发实践》SpringBoot默认集成Logback,支持灵活日志级别配置(INFO/DEBUG等),输出包含时间戳、级别、类名等信息,并可通过... 目录一、日志概述1.1、Spring Boot日志简介1.2、日志框架与默认配置1.3、日志的核心作用

python运用requests模拟浏览器发送请求过程

《python运用requests模拟浏览器发送请求过程》模拟浏览器请求可选用requests处理静态内容,selenium应对动态页面,playwright支持高级自动化,设置代理和超时参数,根据需... 目录使用requests库模拟浏览器请求使用selenium自动化浏览器操作使用playwright

RabbitMQ消息总线方式刷新配置服务全过程

《RabbitMQ消息总线方式刷新配置服务全过程》SpringCloudBus通过消息总线与MQ实现微服务配置统一刷新,结合GitWebhooks自动触发更新,避免手动重启,提升效率与可靠性,适用于配... 目录前言介绍环境准备代码示例测试验证总结前言介绍在微服务架构中,为了更方便的向微服务实例广播消息,

浅析Spring如何控制Bean的加载顺序

《浅析Spring如何控制Bean的加载顺序》在大多数情况下,我们不需要手动控制Bean的加载顺序,因为Spring的IoC容器足够智能,但在某些特殊场景下,这种隐式的依赖关系可能不存在,下面我们就来... 目录核心原则:依赖驱动加载手动控制 Bean 加载顺序的方法方法 1:使用@DependsOn(最直

Spring如何使用注解@DependsOn控制Bean加载顺序

《Spring如何使用注解@DependsOn控制Bean加载顺序》:本文主要介绍Spring如何使用注解@DependsOn控制Bean加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录1.javascript 前言2. 代码实现总结1. 前言默认情况下,Spring加载Bean的顺

基于Python开发Windows屏幕控制工具

《基于Python开发Windows屏幕控制工具》在数字化办公时代,屏幕管理已成为提升工作效率和保护眼睛健康的重要环节,本文将分享一个基于Python和PySide6开发的Windows屏幕控制工具,... 目录概述功能亮点界面展示实现步骤详解1. 环境准备2. 亮度控制模块3. 息屏功能实现4. 息屏时间

Python远程控制MySQL的完整指南

《Python远程控制MySQL的完整指南》MySQL是最流行的关系型数据库之一,Python通过多种方式可以与MySQL进行交互,下面小编就为大家详细介绍一下Python操作MySQL的常用方法和最... 目录1. 准备工作2. 连接mysql数据库使用mysql-connector使用PyMySQL3.

如何搭建并配置HTTPD文件服务及访问权限控制

《如何搭建并配置HTTPD文件服务及访问权限控制》:本文主要介绍如何搭建并配置HTTPD文件服务及访问权限控制的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、安装HTTPD服务二、HTTPD服务目录结构三、配置修改四、服务启动五、基于用户访问权限控制六、

Python使用pynput模拟实现键盘自动输入工具

《Python使用pynput模拟实现键盘自动输入工具》在日常办公和软件开发中,我们经常需要处理大量重复的文本输入工作,所以本文就来和大家介绍一款使用Python的PyQt5库结合pynput键盘控制... 目录概述:当自动化遇上可视化功能全景图核心功能矩阵技术栈深度效果展示使用教程四步操作指南核心代码解析

Python模拟串口通信的示例详解

《Python模拟串口通信的示例详解》pySerial是Python中用于操作串口的第三方模块,它支持Windows、Linux、OSX、BSD等多个平台,下面我们就来看看Python如何使用pySe... 目录1.win 下载虚www.chinasem.cn拟串口2、确定串口号3、配置串口4、串口通信示例5