STM32之八:IIC通信协议

目录

1. IIC协议简介

1.1 主从模式

1.2 2根通信线

2. IIC协议时序

2.1 起始条件和终止条件

2.2 发送一个字节

2.3 接收一个字节

2.4 应答信号


1. IIC协议简介

IIC协议是一个半双工、同步、一主多从、多主多从的串行通用数据总线。该通信模式需要2根线:SCL、SDA,即时钟线和数据线。

1.1 主从模式

IIC协议支持一主多从和多主多从,每个设备都有唯一的地址。

1.2 2根通信线

SDA:数据线,用于传输数据

SCL:时钟线,用于同步数据传输

接线时所有IIC设备的SCL连在一起,SDA连在一起,且设备的SCL的SDA均要配置成开漏输出模式,SCL和SDA需要各添加一个上拉电阻,阻值一般为4.7KΩ左右。

这里补充一下,因为有看到过一个主机一个从机的情况下,可以设置为推挽输出模式,但是在一主多从,或者多主多从的情况下,推荐开漏输出,原因请看下文。

为了能理解为什么在IIC协议总线上,IO口模式需要设置为开漏输出模式,而不能使用推挽输出模式,可以看下GPIO口的硬件结构:

I/O端口位的基本结构

看输出驱动器部分,可以看到使用了两个MOS管,分别是P-MOS和N-MOS管,这些是STM32 GPIO输出模式的关键元件。‌在推挽输出模式下,‌P-MOS管和N-MOS管都工作,‌通过控制这些管的开关状态来实现高电平和低电平的输出。‌在开漏输出模式下,‌只有N-MOS管工作,‌用于输出低电平,‌而高电平的输出则需要通过外部上拉电阻实现。

推挽输出模式:

推挽输出结构是由两个MOS收到互补控制的信号控制。推挽输出的最大特点是可以真正能真正的输出高电平和低电平,在两种电平下都具有驱动能力。推挽输出模式中,N-MOS管和P-MOS管都工作,如果我们控制输出为0(低电平),则P-MOS管关闭,N-MOS管导通,输出低电平;若控制输出为1(高电平),则P-MOS管导通,N-MOS管关闭,输出高电平。外部上拉和下拉的作用是控制在没有输出时的IO口电平。

优点:驱动能力强,电平切换能力快(根据GPIO的波特率可用作模拟其他协议)。

缺点:多个推挽输出端口相连时,由于通路上阻抗较小电流会从IO的VDD流向另一个IO的GND,会发生短路进而对端口造成伤害。(这里就解释了为什么IIC不能使用推挽输出模式,如果多个从机都接到SDA线上,一个机器发送数据0,另一个机器发送数据1,则可能会发生短路进而毁坏IIC器件)。

开漏输出模式:

开漏输出时只有N-MOS管工作,只能输出低电平。当其输出高电平时没有驱动能力(电压会被外部阻抗拉低),需要借助外部上拉电阻完成对外驱动(通断N-MOS实现对路径上的电压控制),驱动能力取决于上拉电阻阻值。

如果我们控制输出为0(低电平),则P-MOS管关闭,N-MOS管导通,输出低电平;若控制输出为1(高电平),则P-MOS管和N-MOS管都关闭,输出指令就不会起到作用,此时I/O端口的电平就不由输出的高低电平决定,而是由I/O端口外部的上拉或者下拉决定。如果没有上拉或者下拉 IO口就处于悬空状态。

半双工:一根数据线,这根数据线既可以发送数据,也可以接收数据,但是不能同时发送和接收,所以叫做半双工通信。

代码如下:注意开漏输出模式

// PB11-->SDA
// PB10-->CLKvoid MyI2C_Init(void)
{/*开启时钟*/RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//开启GPIOB的时钟/*GPIO初始化*/GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);					//将PB10和PB11引脚初始化为开漏输出/*设置默认电平*/GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);			//设置PB10和PB11引脚初始化后默认为高电平(释放总线状态)
}

2. IIC协议时序

2.1 起始条件和终止条件

IIC需要起始信号和终止信号。

/*** 函    数:I2C起始* 参    数:无* 返 回 值:无*/
void MyI2C_Start(void)
{MyI2C_W_SDA(1);							//释放SDA,确保SDA为高电平MyI2C_W_SCL(1);							//释放SCL,确保SCL为高电平MyI2C_W_SDA(0);							//在SCL高电平期间,拉低SDA,产生起始信号MyI2C_W_SCL(0);							//起始后把SCL也拉低,即为了占用总线,也为了方便总线时序的拼接
}
/*** 函    数:I2C终止* 参    数:无* 返 回 值:无*/
void MyI2C_Stop(void)
{MyI2C_W_SDA(0);							//拉低SDA,确保SDA为低电平MyI2C_W_SCL(1);							//释放SCL,使SCL呈现高电平MyI2C_W_SDA(1);							//在SCL高电平期间,释放SDA,产生终止信号
}//---------------
/*** 函    数:I2C写SCL引脚电平* 参    数:BitValue 协议层传入的当前需要写入SCL的电平,范围0~1* 返 回 值:无* 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置SCL为低电平,当BitValue为1时,需要置SCL为高电平*/
void MyI2C_W_SCL(uint8_t BitValue)
{GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);		//根据BitValue,设置SCL引脚的电平Delay_us(10);												//延时10us,防止时序频率超过要求
}/*** 函    数:I2C写SDA引脚电平* 参    数:BitValue 协议层传入的当前需要写入SDA的电平,范围0~0xFF* 返 回 值:无* 注意事项:此函数需要用户实现内容,当BitValue为0时,需要置SDA为低电平,当BitValue非0时,需要置SDA为高电平*/
void MyI2C_W_SDA(uint8_t BitValue)
{GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);		//根据BitValue,设置SDA引脚的电平,BitValue要实现非0即1的特性Delay_us(10);												//延时10us,防止时序频率超过要求
}

2.2 发送一个字节

/*** 函    数:I2C发送一个字节* 参    数:Byte 要发送的一个字节数据,范围:0x00~0xFF* 返 回 值:无*/
void MyI2C_SendByte(uint8_t Byte)
{uint8_t i;for (i = 0; i < 8; i ++)				//循环8次,主机依次发送数据的每一位{MyI2C_W_SDA(Byte & (0x80 >> i));	//使用掩码的方式取出Byte的指定一位数据并写入到SDA线MyI2C_W_SCL(1);						//释放SCL,从机在SCL高电平期间读取SDAMyI2C_W_SCL(0);						//拉低SCL,主机开始发送下一位数据}
}

2.3 接收一个字节

/*** 函    数:I2C接收一个字节* 参    数:无* 返 回 值:接收到的一个字节数据,范围:0x00~0xFF*/
uint8_t MyI2C_ReceiveByte(void)
{uint8_t i, Byte = 0x00;					//定义接收的数据,并赋初值0x00,此处必须赋初值0x00,后面会用到MyI2C_W_SDA(1);							//接收前,主机先确保释放SDA,避免干扰从机的数据发送for (i = 0; i < 8; i ++)				//循环8次,主机依次接收数据的每一位{MyI2C_W_SCL(1);						//释放SCL,主机机在SCL高电平期间读取SDAif (MyI2C_R_SDA() == 1){Byte |= (0x80 >> i);}	//读取SDA数据,并存储到Byte变量//当SDA为1时,置变量指定位为1,当SDA为0时,不做处理,指定位为默认的初值0MyI2C_W_SCL(0);						//拉低SCL,从机在SCL低电平期间写入SDA}return Byte;							//返回接收到的一个字节数据
}/*** 函    数:I2C读SDA引脚电平* 参    数:无* 返 回 值:协议层需要得到的当前SDA的电平,范围0~1* 注意事项:此函数需要用户实现内容,当前SDA为低电平时,返回0,当前SDA为高电平时,返回1*/
uint8_t MyI2C_R_SDA(void)
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);		//读取SDA电平Delay_us(10);												//延时10us,防止时序频率超过要求return BitValue;											//返回SDA电平
}

2.4 应答信号

/*** 函    数:I2C发送应答位* 参    数:Byte 要发送的应答位,范围:0~1,0表示应答,1表示非应答* 返 回 值:无*/
void MyI2C_SendAck(uint8_t AckBit)
{MyI2C_W_SDA(AckBit);					//主机把应答位数据放到SDA线MyI2C_W_SCL(1);							//释放SCL,从机在SCL高电平期间,读取应答位MyI2C_W_SCL(0);							//拉低SCL,开始下一个时序模块
}/*** 函    数:I2C接收应答位* 参    数:无* 返 回 值:接收到的应答位,范围:0~1,0表示应答,1表示非应答*/
uint8_t MyI2C_ReceiveAck(void)
{uint8_t AckBit;							//定义应答位变量MyI2C_W_SDA(1);							//接收前,主机先确保释放SDA,避免干扰从机的数据发送MyI2C_W_SCL(1);							//释放SCL,主机机在SCL高电平期间读取SDAAckBit = MyI2C_R_SDA();					//将应答位存储到变量里MyI2C_W_SCL(0);							//拉低SCL,开始下一个时序模块return AckBit;							//返回定义应答位变量
}

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

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

相关文章

ubuntu22.04安装SecureCRT8.7.3,完成顺利使用

材料准备 scrt-sfx安装包 &#xff0c; securecrt_linux_crack.pl 补丁脚本&#xff0c;和两个依赖库 其中securecrt_linux_crack.pl是找的专门适合 8.7.3版本的&#xff0c;网上很多版本的crack.pl只能打补丁以前的老版本。 而更老版本的SecureCRT对ubuntu22支持更不好&#…

【低照度图像增强系列(8)】URetinex-Net算法详解与代码实现(2022|CVPR)

前言 ☀️ 在低照度场景下进行目标检测任务&#xff0c;常存在图像RGB特征信息少、提取特征困难、目标识别和定位精度低等问题&#xff0c;给检测带来一定的难度。 &#x1f33b;使用图像增强模块对原始图像进行画质提升&#xff0c;恢复各类图像信息&#xff0c;再使用目标检…

hmallox勒索病毒科普:了解其威胁与防御策略

hmallox勒索病毒科普&#xff1a;了解其威胁与防御策略 一、引言 在数字化时代&#xff0c;网络安全威胁日益严峻&#xff0c;勒索病毒作为其中的一类恶意软件&#xff0c;给个人和企业带来了巨大损失。hmallox勒索病毒作为Mallox勒索软件家族的新变种&#xff0c;以其高度的…

求职学习笔记day1

自己一直算是一个内耗拖延的人&#xff0c;内耗着考了研&#xff0c;内耗着拖着不找工作&#xff0c;一直拖到了毕业。研究生没考上&#xff0c;工作没有&#xff0c;也羡慕着别人成功的生活&#xff0c;最后毕业的也不太开心。 一、最近总结 游戏 高考结束以来和大学期间作息…

数据结构之初始二叉树(2)

找往期文章包括但不限于本期文章中不懂的知识点&#xff1a; 个人主页&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 所属专栏&#xff1a;数据结构&#xff08;Java版&#xff09; 二叉树的前置知识&#xff08;概念、性质、、遍历&#xff09; 通过上篇文章的学习&#xff0c;我们…

TCP/IP中的复用、分解和封装

TCP/IP&#xff08;传输控制协议/互联网协议&#xff09;模型中&#xff0c;复用&#xff08;Multiplexing&#xff09;、分解&#xff08;Demultiplexing&#xff09;和封装&#xff08;Encapsulation&#xff09;是关键概念&#xff0c;它们帮助管理和传输数据在网络上的有效…

【Linux】centos7安装PHP7.4报错:libzip版本过低

问题描述 configure: error: Package requirements (libzip > 0.11 libzip ! 1.3.1 libzip ! 1.7.0) were not met: checking for libzip > 0.11 libzip ! 1.3.1 libzip ! 1.7.0... no configure: error: Package requirements (libzip > 0.11 libzip ! 1.3.1 libzi…

Java中线程启动:start()与run()方法的区别

Java中线程启动&#xff1a;start&#xff08;&#xff09;与run&#xff08;&#xff09;方法的区别 1. start()方法2. run()方法3、总结4、示例对比 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 线程是并发执行的基本单位&#xff0c;而…

中科亿海微亮相慕尼黑上海电子展

7月8-10日&#xff0c;备受瞩目的全球电子行业盛会“慕尼黑上海电子展”以空前规模启幕&#xff0c;汇聚了超过1600家参展企业&#xff0c;涵盖了从终端产品制造商到元器件供应商、组装/系统供应商、EMS、ODM/OEM、材料供应商及生产设备供应商的完整产业链。中科亿海微电子科技…

《昇思25天学习打卡营第22天|基于MindSpore的GPT2文本摘要》

#学习打卡第22天# 1. 数据集 1.1 数据下载 使用nlpcc2017摘要数据&#xff0c;内容为新闻正文及其摘要&#xff0c;总计50000个样本。 from mindnlp.utils import http_get from mindspore.dataset import TextFileDataset# download dataset url https://download.mindspor…

活用 localStorage

我维护的这款工具 https://editor.yunwow.cn/ 已经帮我写了 7 篇文章了&#xff0c; 用起来很顺手&#xff0c;因此我打算再给它升级下让它更方便&#xff0c;我决定要给它加个本地缓存功能。我给它提的要求是&#xff1a; 1. 至少能缓存 5 篇文章 2. 能有选择的加载模板 3…

MySQL-对数据库和表的DDL命令

文章目录 一、什么是DDL操作二、数据库编码集和数据库校验集三、使用步骤对数据库的增删查改1.创建数据库2.进入数据库3.显示数据库4.修改数据库mysqldump 5.删除数据库 对表的增删查改1.添加/创建表2.插入表内容3.查看表查看所有表查看表结构查看表内容 4.修改表修改表的名字修…

融云:换头像=换人设?社交应用中隐秘而重要的「用户信息管理」

当代年轻人失眠三大原因&#xff0c;最近新上的《喜人奇妙夜》帮你找到了—— 基金绿了、吵架输了、前任头像换了。 当你半夜翻看前任的社交账号&#xff0c;一场盛大的失眠就开始了&#xff0c;就算古希腊掌柜睡眠的神躺你旁边也不好使。即便 Ta 没有更新内容&#xff0c;昵…

Redis 中String类型操作命令(命令演示,时间复杂度,返回值,注意事项)

String 类型 文章目录 String 类型set 命令get 命令mset 命令mget 命令get 和 mget 的区别incr 命令incrby 命令decr 命令decrby 命令incrbyfloat 命令append 命令getrange 命令setrange 命令 字符串类型是 Redis 中最基础的数据类型&#xff0c;在讲解命令之前&#xff0c;我们…

Linux的load(负载)

负载(load)是Linux机器的一个重要指标&#xff0c;直观了反应了机器当前的状态。 在Linux系统中&#xff0c;系统负载是对当前CPU工作量的度量&#xff0c;被定义为特定时间间隔内运行队列中的平均线程数。 Linux的负载高&#xff0c;主要是由于CPU使用、内存使用、10消…

新款S32K3 MCU可解决汽车软件开发的成本和复杂性问题(器件编号包含S32K322E、S32K322N、S32K328)

全新的S32K3系列专门用于车身电子系统、电池管理和新兴的域控制器&#xff0c;利用涵盖网络安全、功能安全和底层驱动程序的增强型封装持续简化软件开发。 相关产品&#xff1a;S32K328NHT1VPCSR S32K328GHT1MPCSR S32K322NHT0VPASR S32K322EHT0VPBSR S32K322NHT0VPBSR S32K32…

Doris数据库---建表、调整表结构操作

一、简介 本文章主讲创建 Doris 自维护的表的语法&#xff0c;以下为本人最近为数据中台接入doris所踩的坑及其解决方案&#xff0c;欢迎点评。 二、doris建表语法&#xff1a; 官网建表语法网址链接&#xff1a;CREATE-TABLE - Apache Doris 官网建表语法如图所示&#xf…

【C++】构造函数详解

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

windows服务器搭建区块链环境(node.js+truffle+ganache)

windows服务器搭建区块链环境&#xff08;node.jstruffleganache&#xff09; 1&#xff0c;安装node.js中文版的2&#xff0c;更改下载源3&#xff0c;安装truffle4&#xff0c;安装ganache&#xff08;可以跳过使用ganache-cli&#xff09;5&#xff0c;安装ganache-cli&…

starRocks搭建

公司要使用新的大数据架构&#xff0c;打算用国产代替国外的大数据平台。所以这里我就纠结用doris还是starrocks&#xff0c;如果用doris&#xff0c;因为是开源的&#xff0c;以后就可以直接用云厂商的。如果用starrocks就得自己搭建&#xff0c;但是以后肯定会商业化&#xf…