IIC学习之SHT30温湿度传感器(基于STM32)

简介

附上SHT30资料和逻辑分析仪源文件,点击下载

关于IIC的介绍网上已经非常详尽,这里只说重点:

  • 双线(SDA,SCL),半双工
  • 采用主从结构,支持一主多从,通过地址寻址,每个I2C设备都有唯一的7位或10位地址,还有1bit选择读写(0为写,1为读)
  • 速率较低,I2C总线支持多种通信速率,通常有标准模式(100 kbit/s)、快速模式(400 kbit/s)、高速模式(3.4 Mbit/s)和超高速模式(5 Mbit/s)等



时序图

IIC的 SCL 和SDA 都需要接上拉电阻,以保证空闲状态的稳定性

  • 在SCL低电平的时候SDA可变,SCL高电平的时候进行采样
  • 8bit传输完后接收方需要回一个ACK,低电平表示ACK,高电平表示NACK
  • 停止条件和ACK可以没有,起始条件必须有
    在这里插入图片描述



SHT30资料

SHT30的7位地址为0x44

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

读取时序图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

CRC-8校验规则
在这里插入图片描述

计算结果
在这里插入图片描述



读取代码

void SHT30_read_result(float *temp, uint8_t *humi)
{uint8_t buff[6];uint16_t data;float temp_float, humi_float;iic_start();iic_send_byte(SHT30_ADDR << 1 | 0); // 写7位I2C设备地址加0作为写取位,1为读取位iic_wait_ack();iic_send_byte(0xE0);iic_wait_ack();iic_send_byte(0x00);iic_wait_ack();iic_start();iic_send_byte(SHT30_ADDR << 1 | 1); // 写7位I2C设备地址加0作为写取位,1为读取位iic_wait_ack();buff[0] = iic_read_byte(1);buff[1] = iic_read_byte(1);buff[2] = iic_read_byte(1);buff[3] = iic_read_byte(1);buff[4] = iic_read_byte(1);buff[5] = iic_read_byte(0);iic_stop();// 计算温度if (CRC_8(buff, 2) == buff[2]) // 进行CRC-8校验{data = buff[0] * 256 + buff[1];                // 取出16位的温度值temp_float = ((float)data) * 0.267032f - 4500; // 根据手册公式计算,为了精度,计算数值先*100temp_float = temp_float * 0.01f;               // 再除以100,得到正常温度值*temp = temp_float;}// 计算湿度if (CRC_8(&buff[3], 2) == buff[5]) // 进行CRC-8校验{data = buff[3] * 256 + buff[4];             // 取出16位的湿度值humi_float = ((float)data) * 0.152590f;     // 根据手册公式计算humi_float = (uint8_t)(humi_float * 0.01f); // 除以100,得到正常湿度值*humi = (uint8_t)humi_float;}// printf("%.1f %d\r\n", temp_float, (uint8_t)humi_float);
}static uint8_t CRC_8(uint8_t *Crc_ptr, uint8_t LEN)
{uint8_t CRC_Value = 0xFF;uint8_t i = 0, j = 0;for (i = 0; i < LEN; i++){CRC_Value ^= *(Crc_ptr + i);for (j = 0; j < 8; j++){if (CRC_Value & 0x80)CRC_Value = (CRC_Value << 1) ^ 0x31;elseCRC_Value = (CRC_Value << 1);}}return CRC_Value;
}



逻辑分析仪

在这里插入图片描述

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传



模拟IIC源码

myiic.c

#include "myiic.h"void iic_init(void)
{GPIO_InitTypeDef gpio_init_struct;IIC_SCL_GPIO_CLK_ENABLE(); /* SCL引脚时钟使能 */IIC_SDA_GPIO_CLK_ENABLE(); /* SDA引脚时钟使能 */gpio_init_struct.Pin = IIC_SCL_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;         /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                 /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;  /* 快速 */HAL_GPIO_Init(IIC_SCL_GPIO_PORT, &gpio_init_struct); /* SCL */gpio_init_struct.Pin = IIC_SDA_GPIO_PIN;gpio_init_struct.Mode = GPIO_MODE_OUTPUT_OD;         /* 推挽输出 */HAL_GPIO_Init(IIC_SDA_GPIO_PORT, &gpio_init_struct); /* SDA *//* SDA引脚模式设置,开漏输出,上拉, 这样就不用再设置IO方向了, 开漏输出的时候(=1), 也可以读取外部信号的高低电平 */iic_stop(); /* 停止总线上所有设备 */
}// 延时2us
static void iic_delay(void)
{uint32_t timer;timer = get_tim2_cnt();while (get_tim2_cnt() - timer < 20);
}/*** @brief       产生IIC起始信号* @param       无* @retval      无*/
void iic_start(void)
{IIC_SDA(1);IIC_SCL(1);iic_delay();IIC_SDA(0); /* START信号: 当SCL为高时, SDA从高变成低, 表示起始信号 */iic_delay();IIC_SCL(0); /* 钳住I2C总线,准备发送或接收数据 */iic_delay();
}/*** @brief       产生IIC停止信号* @param       无* @retval      无*/
void iic_stop(void)
{IIC_SDA(0); /* STOP信号: 当SCL为高时, SDA从低变成高, 表示停止信号 */iic_delay();IIC_SCL(1);iic_delay();IIC_SDA(1); /* 发送I2C总线结束信号 */iic_delay();
}/*** @brief       等待应答信号到来* @param       无* @retval      1,接收应答失败*              0,接收应答成功*/
uint8_t iic_wait_ack(void)
{uint8_t waittime = 0;uint8_t rack = 0;IIC_SDA(1); /* 主机释放SDA线(此时外部器件可以拉低SDA线) */iic_delay();IIC_SCL(1); /* SCL=1, 此时从机可以返回ACK */iic_delay();while (IIC_READ_SDA) /* 等待应答 */{waittime++;if (waittime > 250){iic_stop();rack = 1;break;}}IIC_SCL(0); /* SCL=0, 结束ACK检查 */iic_delay();return rack;
}/*** @brief       产生ACK应答* @param       无* @retval      无*/
void iic_ack(void)
{IIC_SDA(0); /* SCL 0 -> 1  时 SDA = 0,表示应答 */iic_delay();IIC_SCL(1); /* 产生一个时钟 */iic_delay();IIC_SCL(0);iic_delay();IIC_SDA(1); /* 主机释放SDA线 */iic_delay();
}/*** @brief       不产生ACK应答* @param       无* @retval      无*/
void iic_nack(void)
{IIC_SDA(1); /* SCL 0 -> 1  时 SDA = 1,表示不应答 */iic_delay();IIC_SCL(1); /* 产生一个时钟 */iic_delay();IIC_SCL(0);iic_delay();
}/*** @brief       IIC发送一个字节* @param       data: 要发送的数据* @retval      无*/
void iic_send_byte(uint8_t data)
{uint8_t t;for (t = 0; t < 8; t++){IIC_SDA((data & 0x80) >> 7); /* 高位先发送 */iic_delay();IIC_SCL(1);iic_delay();IIC_SCL(0);data <<= 1; /* 左移1位,用于下一次发送 */}IIC_SDA(1); /* 发送完成, 主机释放SDA线 */
}/*** @brief       IIC读取一个字节* @param       ack:  ack=1时,发送ack; ack=0时,发送nack* @retval      接收到的数据*/
uint8_t iic_read_byte(uint8_t ack)
{uint8_t i, receive = 0;for (i = 0; i < 8; i++) /* 接收1个字节数据 */{receive <<= 1; /* 高位先输出,所以先收到的数据位要左移 */IIC_SCL(1);iic_delay();if (IIC_READ_SDA){receive++;}IIC_SCL(0);iic_delay();}if (!ack){iic_nack(); /* 发送nACK */}else{iic_ack(); /* 发送ACK */}return receive;
}

myiic.h

#ifndef __MYIIC_H
#define __MYIIC_H#include "main.h"#define IIC_SCL_GPIO_PORT GPIOE
#define IIC_SCL_GPIO_PIN  GPIO_PIN_8
#define IIC_SCL_GPIO_CLK_ENABLE()                                                                                      \do                                                                                                                 \{                                                                                                                  \__HAL_RCC_GPIOE_CLK_ENABLE();                                                                                  \} while (0)#define IIC_SDA_GPIO_PORT GPIOE
#define IIC_SDA_GPIO_PIN  GPIO_PIN_7
#define IIC_SDA_GPIO_CLK_ENABLE()                                                                                      \do                                                                                                                 \{                                                                                                                  \__HAL_RCC_GPIOE_CLK_ENABLE();                                                                                  \} while (0)/******************************************************************************************//* IO操作 */
#define IIC_SCL(x)                                                                                                     \do                                                                                                                 \{                                                                                                                  \x ? HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_SET)                                       \: HAL_GPIO_WritePin(IIC_SCL_GPIO_PORT, IIC_SCL_GPIO_PIN, GPIO_PIN_RESET);                                    \} while (0) /* SCL */#define IIC_SDA(x)                                                                                                     \do                                                                                                                 \{                                                                                                                  \x ? HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_SET)                                       \: HAL_GPIO_WritePin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN, GPIO_PIN_RESET);                                    \} while (0) /* SDA */#define IIC_READ_SDA HAL_GPIO_ReadPin(IIC_SDA_GPIO_PORT, IIC_SDA_GPIO_PIN) /* 读取SDA *//* IIC所有操作函数 */
void iic_init(void);                      /* 初始化IIC的IO口 */
void iic_start(void);                     /* 发送IIC开始信号 */
void iic_stop(void);                      /* 发送IIC停止信号 */
void iic_ack(void);                       /* IIC发送ACK信号 */
void iic_nack(void);                      /* IIC不发送ACK信号 */
uint8_t iic_wait_ack(void);               /* IIC等待ACK信号 */
void iic_send_byte(uint8_t txd);          /* IIC发送一个字节 */
uint8_t iic_read_byte(unsigned char ack); /* IIC读取一个字节 */#endif

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

USB转串口芯片 国产GP232RL 低成本兼容替代FT232RL 数据手册资料参考

随着工业物联网的不断发展&#xff0c;USB接口正在逐渐替代老式电脑的各种低俗外围接口&#xff0c;然而目前的工业环境中&#xff0c;许多重要的设备仍然使用RS232、RS422、RS485接口界面设计&#xff0c;因此许多用户使用USB转RS232、RS422、RS485转换器或者是转换线&#xf…

Overmind平台推出Sui任务,帮助开发者学习Move并构建强大的应用程序

Overmind与Sui基金会合作&#xff0c;推出了其首个任务系列&#xff0c;旨在帮助开发者学习Move并开始在Sui上构建。这些任务通过提供赢取奖励的机会来将学习体验变成游戏&#xff0c;激励开发者构建高质量的代码并向Sui社区展示他们的技能。 去年推出的Overmind平台正在扩展到…

Leetcode20-唯一摩尔斯密码词(804)

1、题目 国际摩尔斯密码定义一种标准编码方式&#xff0c;将每个字母对应于一个由一系列点和短线组成的字符串&#xff0c; 比如: ‘a’ 对应 “.-” &#xff0c; ‘b’ 对应 “-…” &#xff0c; ‘c’ 对应 “-.-.” &#xff0c;以此类推。 为了方便&#xff0c;所有 26…

new mars3d.graphic.PolylineEntity({在固定高度开启编辑模式的坐标自定义处理

功能示例(Vue版) | Mars3D三维可视化平台 | 火星科技 问题场景&#xff1a; 1.在编辑航线时&#xff0c;需要指定航线坐标在固定高度值上开启编辑模式。 2.关键代码是&#xff1a; graphicLayer.startEditing({开启编辑模式&#xff0c;进行航线的编辑。 解决方案&#xf…

大模型实战营Day4 XTuner 大模型单卡低成本微调实战 作业

按照文档操作&#xff1a; 单卡跑完训练&#xff1a; 按照要求更改微调的数据&#xff1a; 完成微调数据的脚本生成&#xff1a; 修改配置文件&#xff1a; 替换好文件后启动&#xff1a; 启动后终端如图&#xff1a; 用于微调的一些数据显示&#xff1a; 训练时间&#x…

muduo网络库剖析——套接字Socket类

muduo网络库剖析——套接字Socket类 前情从muduo到my_muduo 概要socket网络编程socket编程接口介绍头文件socketbindlistenacceptaccept4connect 框架与细节成员函数使用方法 源码结尾 前情 从muduo到my_muduo 作为一个宏大的、功能健全的muduo库&#xff0c;考虑的肯定是众多…

数字孪生+人工智能突破复杂地形和气候提供可靠的电力

利用 Bentley 应用程序实现数字化交付&#xff0c;大大缩短了项目时间和成本&#xff0c;降低了碳排放量 Kalpataru Projects International Limited (KPIL) 正在扩展喀麦隆的电力网络&#xff0c;以改善该国 13% 人口的电网连接和电力供应。根据其项目管理方法&#xff0c;KPI…

Oracle 实战手册 工作实战经验总结

一、基本的数据库管理 高级开发人员需要掌握&#xff0c;了解Oracle数据库运行的基本原理&#xff0c;了解其中的概念。 1、数据库的启动和关闭 2、如何确定Oracle的版本&#xff1f; SQL> select * from v$version 2 / BANNER -------------------------------------…

电动工具直流调速专用集成电路GS069,具有电源电压范围宽、功耗小、抗干扰能力强等特性

GS069电动工具直流调速电路是CMOS专用集成电路&#xff0c;具有电源电压范 围宽、功耗小、抗干扰能力强等特点。通过外接电阻网络&#xff0c;改变与之相接 的VMOS 管的输出&#xff0c;达到控制电动工具转速的作用。该电路输出幅值宽&#xff0c; 频率变化小&#xff0c;占空比…

【微信小程序独立开发1】项目提出和框架搭建

前言&#xff1a;之前学习小程序开发时仿照别人的页面自己做了一个商城项目和小说项目&#xff0c;最近突发奇想&#xff0c;想从0开发一个关于《宠物日记》的小程序&#xff0c;需求和页面都由自己设计&#xff0c;将在这记录开发的全部流程和过程中遇到的难题等... 1、搭建小…

怎样通过交换机封锁MAC地址

第一步&#xff1a;查询该IP所对应的MAC地址 display arp | include ip地址 第二步&#xff1a;封锁mac地址 mac-address blackhole mac地址 vlan 所属vlan-id 以上操作即可封锁

怎么采集今日头条的资讯或文章-简数采集器

如何使用简数采集器快速采集今日头条新闻的资讯或优质文章&#xff1f; 很遗憾&#xff0c;简数采集器暂时不支持采集今日头条上的新闻和文章&#xff0c;不建议采集。 可以换一个采集源进行采集。 简数采集器采集网页文章非常简单&#xff0c;只需输入对应的网址&#xff0…

MySQL 删除ibdata1时怎么恢复

标题&#xff1a;MySQL InnoDB数据恢复&#xff0c;丢失ibdata1时怎么安全恢复 废话在前&#xff1a; 恭喜你&#xff0c;当你看到这篇文章的时候&#xff0c;说明有可能 你心里已经有一万匹&#x1f40e;在奔腾了。千万不要乱删除ibdata1&#xff0c;有些博客无脑抓取、复制…

方案解决:5G基站节能及数字化管理

截至2023年10月&#xff0c;我国5G基站总数达321.5万个&#xff0c;占全国通信基站总数的28.1%。然而&#xff0c;随着5G基站数量的快速增长&#xff0c;基站的能耗问题也逐渐日益凸显&#xff0c;基站的用电给运营商带来了巨大的电费开支压力&#xff0c;降低5G基站的能耗成为…

腾讯云把向量数据库“卷”到哪一步了?

“不是我不明白&#xff0c;这世界变化快”&#xff0c;崔健在20世纪写下的这句歌词&#xff0c;放在刚刚过去的2023年&#xff0c;也同样适用。技术风向的变化之快&#xff0c;让不少人感到惊讶&#xff0c;向量数据库这一年的潮起潮落&#xff0c;就是一个典型的例子。 2023年…

OpenGL ES之深入解析如何实现图像锐化

一、什么是图像锐化? 图像锐化是一种图像处理技术,其目的是增强图像中的细节和边缘,使图像看起来更加清晰。这一过程通常涉及到突出图像中的高频信息,特别是强调像素之间的灰度变化。通过增强图像的高频细节,图像锐化可以改善图像在人类视觉系统和计算机视觉系统中的感知效…

电商API接口主要应用场景有哪些?

随着互联网技术的不断进步和电商行业的迅猛发展&#xff0c;电商API接口在商品交易、物流配送、客户服务等方面发挥着越来越重要的作用。本文将深入探讨电商API接口的技术原理、应用场景、开发方法以及优缺点。 一、技术原理 电商API接口是基于HTTP、TCP、IP等网络协议实现的…

[Kubernetes]10. k8s部署Goweb+mysql项目实战演练

一.安装docker构建镜像 如果要本地构建镜像的话,对应节点还需要安装docker,安装教程见:[Docker]一.Docker 简介与安装 linux环境,centos8下 docker及docker compose安装教程 k8s部署Goweb+mysql项目有两种方法:第一种是传统部署方法,第二种是通过ConfigMap实现应用配置分离部署…

Soul App:来一场始于“兴趣”,轻松自在的“零糖”社交吧

岁末年终,回顾2023年,这一年你都做了什么呢? 记不清楚没关系,互联网都帮你记录好了。2023年,B站的年轻人当“所见所闻”刷新自身认知时,往往会发送弹幕“啊?”来抒发惊叹。这一年,支付宝“小荷包”的用户中00后占了4成,近一半更开启了“自动攒”计划“无痛攒钱”!携程上,每7…

Bubble – 非实时协作软件如何促成好点子诞生

作为一名用户体验设计师&#xff0c;参加各种各样的会议构成一周工作大部分时间&#xff0c;一个项目的推进离不开大家的共同协作。 身在外企&#xff0c;我们要与不同国家&#xff08;时区&#xff09;不同部门的同事协作&#xff0c;Teams是每天必使用的软件&#xff0c;但是…