STM32应用开发进阶--IIC总线(SHT20温湿度+HAL库_硬件I2C)

实现目标

1、掌握IIC总线基础知识;

2、会使用软件模拟IIC总线和使用STM32硬件IIC总线;

3、 学会STM32CubeMX软件关于IIC的配置;

4、掌握SHT20温湿度传感器的驱动;

5、具体目标:(1)用STM32硬件IIC驱动SHT20,上位机串口助手打印温湿度;(2)用软件模拟IIC驱动SHT20,上位机串口助手打印温湿度(只提供代码)。


一、IIC概述

1.1 IIC定义

IIC , 即  I²C,全称 Inter-Integrated Circuit,是I²C Bus简称,中文叫集成电路总线 ,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。

1.2 IIC通信连接

IIC总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。IIC总线通过上拉电阻接正电源(上拉电阻常用是4.7K,一般在4.7k-10k之间),要求两根线都使用 开漏输出接上拉电阻 的配置。当总线空闲时,两根线均为高电平。连到总线上的任一器件输出的低电平,都将使总线的信号变低,即各器件的SDA及SCL都是线“与”关系。

1.3 IIC特点

  • 简单和灵活的连接:占用空间小,芯片管脚的数量少,无需片选信号,价格低。。
  • 总线的长度可达7.6m,传送速度:快速 400kbps ,标准 100kbps,高速3.4Mbps。
  • 最大主设备数:无限制;最大从机数:理论上是127。
  • 信方式为同步半双工,同一时间只可以单向通信。
  • 双线制:I2C使用两根信号线进行通信,包括时钟线(SCL)和数据线(SDA)。
  • 多从机:多个从机设备可以连接到同一条I2C总线上,每个从机都有唯一的地址。
  • 多主机:多个主机设备可以通过I2C总线进行并行通信,通过仲裁机制实现多主机冲突的解决。

1.4 硬件IIC和软件IIC的区别

硬件IIC和软件IIC都是I2C总线通信的方式,但它们实现的方式有所不同:

硬件IIC:硬件IIC是通过专门的硬件模块实现的,通常是通过IIC控制器或者外部IIC芯片来实现的,具有高可靠性、传输速度快、占用CPU资源少等优点。硬件IIC协议实现比较简单,只需要在芯片上添加I2C控制器就可以实现IIC通信,适用于传输数据量较大、传输速度要求较高的场景。

软件IIC:软件IIC是通过软件模拟实现的,通常是在单片机的GPIO上实现的,具有低成本、可扩展性强等优点。软件IIC的实现需要占用CPU资源,因此传输速度相对较慢,可靠性也不如硬件IIC。软件IIC适用于传输数据量较小、传输速度要求不高的场景。

二、IIC协议层

        在IIC总线上每一位数据都由一个同步时钟所对应,也就是在SCL串行时钟的配合下,数据在SDA上从高位向低位一次串行传送每一位数据。IIC通信时序图如下:

2.1 数据有效性

  IIC 的数据读取动作都在 SCL为高 时产生,SCL为低时是数据改变的时期,无论SDA如何变化都不影响读取。所以,传输数据的过程中,当SCL为高时,数据应当保持稳定,避免数据的采集出错。

2.2 开始信号、结束信号

开始信号:SCL 为高电平时,SDA 由高电平向低电平跳变,开始传送数据。
结束信号:SCL 为高电平时,SDA 由低电平向高电平跳变,结束传送数据。

2.3 字节格式

SDA数据线上的每个字节必须是8位,对于每次传输的字节数没有限制。每个字节(8位)数据传送完后紧跟着应答信号(ACK,第9位)。数据的先后顺序为:高位在前 。

2.4 应答信号

应答信号:主/从机在之后的数据通信中,数据接收方(可能是主机也可能是从机)收到传输的一个字节数据后,需要给出响应,此时处在第九个时钟,发送端释放 SDA 线控制权,将 SDA 电平拉高,由接收方控制。应答信号分为两种:
1)当第9位(应答位)为 低电平 时,为 ACK  (Acknowledge)   信号
2)当第9位(应答位)为 高电平 时,为 NACK(Not Acknowledge)信号

2.5 数据传输(以地址7bit为例)

一个完整的7-bit通信过程如图所示:

在START信号后的首字节由7位从机地址和1位读写位组成,结构如下图:

发送完这个字节之后,主机释放SDA总线等待从机给出ACK应答。如果从机给出了ACK应答,表示从机地址正确(有从机响应)并且已知晓是读还是写,便可以开始读写数据。如果从机没有给出ACK应答,则说明接收设备可能没有收到数据(如寻址的设备不存在或是设备正在忙碌)或无法解析收到的数据,如果是这样,则由master来决定如何处理(STOP或ReSTART)。

2.5.1. 主机写-从机收,传输方向不变

  主机对从机发送数据时,主机对从机发送一个开始字节,然后即可一直发送数据。以示例来讲解,其第一帧数据为要操作的寄存器地址,所以为:“[1-Byte]开始字节(写) + [1-Byte]寄存器地址 + [1-Byte]寄存器数据”。

2.5.2. 主机读-从机发,传输方向改变

  主机对向从机读取数据时,方式同发送数据有所不同,要多一次通信过程。
  主机需要先向从机发送一次信号,告诉从机”我要读取数据“,然后重开一次通信,等待从机主动返回数据。以示例来讲解,发送 “[1-Byte]开始字节(写) + [1-Byte]要读取的寄存器的地址”,之后结束通信,或者重开始,来进入到第二次通信中,先发送 [1-Byte]开始字节(读),然后等待读取从机发送过来的 [1-Byte]数据 即可。

三、SHT20概述

3.1 SHT20简介

SHT20, 新一代 Sensirion 湿度和温度传感器。标准 I 2 C 格式。SHT20 配有一个全新设计的 CMOSens®芯片、一个经过改进的电容式湿度传感元件和一个标准的能隙温度传感元件。SHT20的分辨率可以通过输入命令进行改变(8/12bit乃至12/14bit的 RH/T),传感器可以检测到电池低电量状态,并且输出校验和,有助于提高通信的可靠性。

3.2  SHT20 引脚

3.3 SHT20采用的I2C通信,基本命令

开始传输后,随后先传输首字节包括I2C设备地址(7bit)和一个SDA方向位(R:1, W:0)。一个时钟发送一个位,在第8个下降沿之后,通过拉低SDA引脚(ACK位 为0),只是传感器数据接收正常。在发出测量命令之后(‘1110’‘0011’代表温度测量,‘1110’‘0101’代表相对湿度测量 ,这种为主机模式),MCU必须等待测量完成。

3.4 保持主模式测量时序图

 测量过程中,SCL线被封锁(由传感器控制),在测量时,SHT2x将SCL拉低强制主机进入等待状态。当释放SCL线,表示传感器内部工作接收,可以继续进行数据传送。

首先发送写地址,再发送命令,然后是读地址,随后等待测量即可,测量时间如下图,传感器内部设置的默认分辨率为相对湿度 12位和温度 14位。45发送NACK时可取消校验。

3.5 无保持主模式测量时序图

量过程中,SCL线是开发状态,可进行其它通信,可以在总线上处理其它I2C总线通信任务。 

3.6 软复位

软复位命令是用于无需关闭和再次打开电源的情况下,重新启动传感器系统,重新初始化并恢复默认设置状态。所需要的时间不超过15ms。由MCU发起软复位命令为1111 1110

3.7  温湿度计算

传感器内部设置的默认分辨率为相对湿度12位和温度14位。SDA的输出数据被转换成两个字节的数据包,高字节MSB在前(左对齐)。每个字节后面都跟随一个应答位。两个状态位,即 LSB的后两位在进行物理计算前须置0。

(1)湿度

(2)温度

四、原理图设计

五、STM32CubeMX 配置

5.1 串口USART1配置

USART1:异步模式,波特率115200,功能:用于打印调试信息

5.2 IIC1配置

配置1:主模式特性  和  从模式特性 配置

Master features  主模式特性
I2C Speed Mode: IIC模式设置 快速模式和标准模式。
I2C Clock Speed: I2C传输速率,默认为100KHz

Slave features  从模式特性
Clock No Stretch Mode: 时钟没有扩展模式

IIC时钟拉伸(Clock stretching)
clock stretching通过将SCL线拉低来暂停一个传输.直到释放SCL线为高电平,传输才继续进行.
clock stretching是可选的,实际上大多数从设备不包括SCL驱动,所以它们不能stretch时钟.

Primary Address Length selection: 从设备地址长度 设置从设备的地址是7bit还是10bit 大部分为7bit
Dual Address Acknowledged: 双地址确认
Primary slave address:  从设备初始地址 

配置2:开启IIC中断

六、程序设计

6.1 串口重定向

#include "stdio.h"

int fputc(int ch, FILE *f) 
{
	HAL_UART_Transmit(&huart1, (uint8_t *) &ch, 1, 0xFFFF);
	return ch;
}

6.2 移植sht20.h文件至工程

#ifndef _SHT20_H_
#define _SHT20_H_

/*SHT20 设备操作相关宏定义,详见手册*/
#define SHT20_ADDRESS  0X40
#define SHT20_Write_Add 0x80
#define SHT20_Read_Add	0x81
#define SHT20_Measurement_RH_HM  0XE5
#define SHT20_Measurement_T_HM  0XE3
#define SHT20_Measurement_RH_NHM  0XF5  //非主机模式地址
#define SHT20_Measurement_T_NHM  0XF3   //非主机模式地址
#define SHT20_READ_REG  0XE7
#define SHT20_WRITE_REG  0XE6
#define SHT20_SOFT_RESET  0XFE

typedef struct
{
	float tempreture;
	float humidity;
} SHT20_INFO;

extern SHT20_INFO sht20_info;
void SHT20_GetValue(void);

#endif

6.3 移植sht20.c文件至工程

//头文件
#include "stm32f1xx_hal.h"
#include "sht20.h"
#include "i2c.h"

const int16_t POLYNOMIAL = 0x131;
SHT20_INFO sht20_info;


//	函数功能:	SHT20复位
void SHT20_reset(void)
{	
    HAL_I2C_Mem_Write(&hi2c1, SHT20_Write_Add, SHT20_SOFT_RESET, I2C_MEMADD_SIZE_8BIT,(void*)0, 1, 1000);
    HAL_Delay(15);	
}

//函数功能:	SHT20读取用户寄存器
unsigned char  SHT20_read_user_reg(void)
{	
    unsigned char val = 0;	
    HAL_I2C_Mem_Read(&hi2c1, SHT20_Read_Add, SHT20_READ_REG, I2C_MEMADD_SIZE_8BIT,&val, 1, 1000);	
    return val;	
}

//函数功能:	检查数据正确性
char SHT2x_CheckCrc(char data[], char nbrOfBytes, char checksum)
{	
    char crc = 0;
    char bit = 0;
    char byteCtr = 0;	
    //calculates 8-Bit checksum with given polynomial
    for(byteCtr = 0; byteCtr < nbrOfBytes; ++byteCtr)
    {
        crc ^= (data[byteCtr]);
        for ( bit = 8; bit > 0; --bit)
        {
            if (crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
            else crc = (crc << 1);
        }
    }	
    if(crc != checksum)
		return 1;
    else
		return 0;	
}

//*	函数功能:	温度计算
float SHT2x_CalcTemperatureC(unsigned short u16sT)
{
	
    float temperatureC = 0;            // variable for result
    u16sT &= ~0x0003;           // clear bits [1..0] (status bits)
    //-- calculate temperature [℃] --
    temperatureC = -46.85 + 175.72 / 65536 * (float)u16sT; //T= -46.85 + 175.72 * ST/2^16	
    return temperatureC;	
}

//	函数功能:	湿度计算
float SHT2x_CalcRH(unsigned short u16sRH)
{
    float humidityRH = 0;              // variable for result
    u16sRH &= ~0x0003;          // clear bits [1..0] (status bits)
    //-- calculate relative humidity [%RH] --
    //humidityRH = -6.0 + 125.0/65536 * (float)u16sRH; // RH= -6 + 125 * SRH/2^16
    humidityRH = ((float)u16sRH * 0.00190735) - 6;	
    return humidityRH;
}

//函数功能:	测量温湿度
float SHT2x_MeasureHM(unsigned char cmd, unsigned short *pMeasurand)
{
    char  checksum = 0;  //checksum
    char  data[2];    //data array for checksum verification
	unsigned char addr = 0;
    unsigned short tmp = 0;
    float t = 0;
	HAL_I2C_Mem_Read(&hi2c1, SHT20_Read_Add, cmd, I2C_MEMADD_SIZE_8BIT,data,2, 0xFFFF);
	SHT2x_CheckCrc(data, 2, checksum);
    tmp = (data[0] << 8) + data[1];
    if(cmd == SHT20_Measurement_T_HM)
    {
        t = SHT2x_CalcTemperatureC(tmp);
    }
    else
    {
        t = SHT2x_CalcRH(tmp);
    }	
    if(pMeasurand)
    {
        *pMeasurand = (unsigned short)t;
    }	
    return t;	
}
//函数功能:	获取温湿度数据
void SHT20_GetValue(void)
{
	sht20_info.tempreture = SHT2x_MeasureHM(SHT20_Measurement_T_HM, (void *)0);
	HAL_Delay(70);	
	sht20_info.humidity = SHT2x_MeasureHM(SHT20_Measurement_RH_HM, (void *)0);
	HAL_Delay(25);
	SHT20_reset();
}

6.4 在main.c中打印温湿度值

  while (1)
  {
		SHT20_GetValue();
		printf( "Temperature:%0.1fC,  Humidity:%0.1f%%\r\n", sht20_info.tempreture,                 
        sht20_info.humidity);
		HAL_Delay(1000);	  
	  
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

七、实验效果

八、仿真实现


总结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/646756.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

专业的力量:在自己的领域成为专家

专业的力量:在自己的领域成为专家 我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 现在稀缺的已不再是信息资源&#xff0c;而是运用信息的能力。过去的海…

DBAPI怎么进行数据格式转换

DBAPI如何进行数据格式的转换 假设现在有个API&#xff0c;根据学生id查询学生信息&#xff0c;访问API查看数据格式如下 {"data":[{"name":"Michale","phone_number":null,"id":77,"age":55}],"msg"…

VLC播放器(全称VideoLAN Client)

一、简介 VLC播放器&#xff08;全称VideoLAN Client&#xff09;是一款开源的多媒体播放器&#xff0c;由VideoLAN项目团队开发。它支持多种音视频格式&#xff0c;并能够在多种操作系统上运行&#xff0c;如Windows、Mac OS X、Linux、Android和iOS等。VLC播放器具备播放文件…

深入探索C++ Vector容器:灵活的动态数组秘籍

目录 ​编辑 引言 一、初识vector&#xff1a;构造与初始化 二、动态管理&#xff1a;添加与删除元素 三、访问与遍历&#xff1a;多种方式直达元素 四、容量与大小&#xff1a;动态调整的艺术 五、进阶技巧&#xff1a;高效运用vector 结语 引言 在C编程的世界里&…

C++:STL

STL 文章目录 STLSTL 绪论迭代器&#xff08;iterators&#xff09;容器&#xff08;Containers&#xff09;vectorset,multisetmap,multimapstackqueuedequepriority_queuebitset 算法&#xff08;Algorithms&#xff09;sort,count,find,lower_bound,upper_bound,binary_sear…

Java整合ELK实现日志收集 之 Elasticsearch、Logstash、Kibana

简介 Logstash&#xff1a;用于收集并处理日志&#xff0c;将日志信息存储到Elasticsearch里面 Elasticsearch&#xff1a;用于存储收集到的日志信息 Kibana&#xff1a;通过Web端的可视化界面来查看日志&#xff08;数据可视化&#xff09; Logstash 是免费且开放的服务器端数…

如何查看热门GPT应用?

1、登陆chatgpt 2、访问 https://chatgpt.com/gpts 3、在该界面&#xff0c;可以搜索并使用image generator, Write For Me&#xff0c;Language Teature等热门应用。

架构师系列-定时任务解决方案

定时任务概述 在很多应用中我们都是需要执行一些定时任务的&#xff0c;比如定时发送短信&#xff0c;定时统计数据&#xff0c;在实际使用中我们使用什么定时任务框架来实现我们的业务&#xff0c;定时任务使用中会遇到哪些坑&#xff0c;如何最大化的提高定时任务的性能。 我…

可以通过哪些方式邀请媒体报道宣传?

在我个人的职业生涯中,曾经历过一段为了公司新产品的推广,而独自踏上了寻找媒体曝光机会的征途。这段经历至今仍历历在目,它不仅是一段挑战自我的过程,也是我深刻理解到传统媒体联系方式局限性的重要转折点。 起初,我满怀激情地决定通过直接联系媒体来获取免费的宣传机会。我天…

JRT1.7发布

JRT1.7连仪器在线演示视频 JRT1.5实现质控主体、1.6基本完成质控&#xff1b;本次版本推进到1.7&#xff0c;1.7集菜单权限、登录、打印导出客户端、初始化、质控、Linux客户端、仪器连接和监控体系各种功能大全&#xff0c;上十年写系统用到的都全了。 这次直接挑战检验最难…

【fastapi+mongodb】使用motor操作mongodb

上一篇文章&#xff0c;我们在电脑上安装了mongodb数据库。这篇文章&#xff0c;我们在fastapi后端使用motor操作mongodb 如果你还没看过上一篇文章&#xff0c;链接在这里&#xff1a;【MongoDB】安装与使用 安装 motor motor 是一个用于操作 mongodb 数据库的 python 库&a…

Web开发学习总结

学习路线 Web 全球广域网&#xff0c;也称为万维网(www World Wide Web)&#xff0c;能够通过浏览器访问的网站 初识Web前端 Web标准也称为网页标准&#xff0c;由一系列的标准组成&#xff0c;大部分由W3C(World Wide Web Consortium&#xff0c;万维网联盟)负责制定。三个组…

for循环里如果std::pair的类型写不对,可能会造成性能损失

第一版 std::map<int, int> t;t.emplace(1, 1);for (const std::pair<int,int>& data : t){int i 0;std::ignore i;}中间留一些空格&#xff0c;是因为ms在调试的时候&#xff0c;尤其是模板比较多的时候&#xff0c;经常断点的行号有问题。比如第5行的断点&…

1960-2022年世界银行WDI面板数据(1400+指标)

1960-2022年世界银行WDI面板数据&#xff08;1400指标&#xff09; 1、时间&#xff1a;1960-2022年 2、来源&#xff1a;世界银行WDI 指标&#xff1a;包括健康、公共部门、农业与农村发展、城市发展、基础设施、外债、性别、援助效率、教育、气候变化、环境、社会保护与劳…

大模型应用:基于Golang实现GPT模型API调用

1.背景 当前OpenAI提供了开放接口&#xff0c;支持通过api的方式调用LLM进行文本推理、图片生成等能力&#xff0c;但目前官方只提供了Python SDK。为了后续更方便集成和应用&#xff0c;可以采用Golang对核心推理调用接口进行封装&#xff0c;提供模型调用能力。 2.相关准备…

Django框架过时了吗?新手学Flask还是Django?

文章目录 Django框架的优势与劣势优势劣势 Flask框架的优势与劣势优势劣势 如何选择&#xff1f; 近年来&#xff0c;随着Flask框架的崛起&#xff0c;一些人开始质疑Django框架是否已经过时。在选择学习框架时&#xff0c;新手们往往感到困惑&#xff0c;不知道是学习Flask还是…

2024宝藏工具EasyRecovery数据恢复软件免费版本下载

在这个数字化的时代&#xff0c;数据已经成为我们生活中的重中之重。无论是工作中的重要文件&#xff0c;还是手机中珍贵的照片&#xff0c;我们都依赖着这些数据。然而&#xff0c;数据丢失的情况时有发生&#xff0c;可能是误删&#xff0c;可能是设备故障&#xff0c;更可能…

移动端特效

一&#xff0c;触屏事件 1.触屏touch事件 2.触摸事件对象 如果侦听的是一个DOM元素&#xff0c;他俩是一样的 如果手指离开了&#xff0c;不能侦听到前两者&#xff0c;能侦听到第三个 我们一般都是触摸元素&#xff0c;所以一般都是第二个比较常用 第一个&#xff1a;屏幕…

Java核心:注解处理器

Java提供了一个javac -processor命令支持处理标注有特定注解的类&#xff0c;来生成新的源文件&#xff0c;并对新生成的源文件重复执行。执行的命令大概是这样的: javac -XprintRounds -processor com.keyniu.anno.processor.ToStringProcessor com.keyniu.anno.processor.Po…

java “错误:编码GBK 的不可映射字符”

环境&#xff1a;JDK-17 本机编码&#xff1a;utf-8 代码编码&#xff1a;GBK 错误&#xff1a;java “错误&#xff1a;编码GBK 的不可映射字符” 解决1&#xff1a;记事本打开java源文件&#xff0c;另存为选择ANSI编码 解决2&#xff1a;复制代码再将编码格式改为utf-8,…