| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 嵌入式 -> STM32单片机初学4-IIC通信(软件模拟) -> 正文阅读 |
|
[嵌入式]STM32单片机初学4-IIC通信(软件模拟) |
IIC(Inter-Integrated Circuit)又称I2C(习惯读“I方C”),是IICBus简称,中文名为集成电路总线,它是一种串行通信总线,使用多主从架构,由飞利浦公司在1980年代为了让主板、嵌入式系统或手机用以连接低速周边设备而发展。适用于IC间的短距离数据传输。 最初的IIC通信速率只有100Kbps(12.5KB/s),后来又发展到400Kbps(50KB/s),再后来发展到1Mbps和3.4Mbps(高速模式)。速度越快,对通信设备的要求就越高,所以很多IIC通信设备并不支持高速模式。 IIC是单片机最常用的通讯方式之一,如果单片机需要扩展EEPROM存储芯片,就会用到IIC通信来读写EEPROM的数据。 除此很多传感器(如温湿度传感器,加速度传感器等)、外设(如OLED屏幕、LCD显示板等)也会采用IIC与单片机进行数据的传输。 所以IIC是单片机中必不可少的学习内容。 本文标题特别强调了“软件模拟”IIC通信,那是不是也有硬件IIC通信?是的。 硬件IIC:我们知道,STM32外设丰富,包括硬件级的IIC通信,也就是在其内部集成有专门用于IIC通信的硬件模块,只要在程序中配置相关的参数,就能启用该模块,再通过官方已经做好的库函数,就能很容易的实现IIC通信了。 但是由于STM32的硬件IIC存在着应答信号卡死的问题,所以很多开发者更喜欢使用软件模拟IIC通信。另外,软件模拟IIC还有方便移植到其他设备的优点。 那么软件模拟IIC到底是什么呢?又是如何实现的呢? 首先知道一点,不管何种有线通信方式,都是通过通信线传输高低电平信号实现的。数据的最小单位为bit,1个bit能表示0或者1,高低电平正好能代表这两种状态。高低电平不断变换,就能表示不断变化的0和1,将其连起来,就组成了一连串的数据。 所以理论上,只要是能产生高低电平信号的东西,就能用来通信。而单片机的IO口不就能输出高低电平,所以只要我们通过程序让IO口按照一定的规律输出高低电平,就能实现通信了。这样的通信方式就称为软件模拟通信。上面提到的规律,就是通信协议。 为了让数据发送端发送的数据能被接收端识别,必须约定一种特定的协议,双方都按照协议的规定发送或者接受数据,我们把这种协议叫做通信协议。 通常,我们所说的通信方式既包括物理接口也包括其通信协议。 物理接口:通俗地说就是要几根通信线,各通信线的定义与接法,比如IIC需要SCL与SDA两根通信线,缺少任何一根线都是无法通信的。 通信协议:包括各种信号、数据帧形式等定义。发送端将要发送的数据按照协议规定重新排列再发出去,接收端则按照协议将接收到的数据进行解析,得到正确的数据。未按照协议规定发送的数据接收端认为是无效数据,不做处理。 这就是不同通信方式的设备之间不能通信的原因。不同的通信方式有不同的通信协议,但可能采用相同的通信接口。比如RS485与RS422物理接口相同,但通信协议不一样;RS232则与前两者的物理接口也不一样。 所以建立通信的条件有:物理接口,通信协议。 现在我们回到IIC通信。 IIC物理接口:IIC串行总线有两根信号线,一根是双向的数据线SDA,另一根是时钟线SCL。所有接到I2C总线设备上的串行数据SDA都接到总线的SDA上,各设备的时钟线SCL接到总线的SCL上,属于一主多从总线。主机一次只能跟一个从机通信,如果要跟多个从机传输数据,则需要采用轮询的方式。通常会给SDA和SCL外接上拉电阻,确保无数据传输时,总线处于闲置状态。但是不接也可以,可以使用STM32的片内上拉电阻。 这两根线中,SCL是时钟线,用来同步时钟信号;SDA是数据线,用来传输数据。 如果是硬件IIC,那么这两根线必须接到STM32的特定引脚上,以STM32F03C8T6为例,其IIC2的SCL为PB10,SDA为PB11,那从机的SCL就只能接在PB10,SDA只能接在PB11。 ?但对于软件模拟IIC,就没有任何限制,你可以定义任意两个IO口分别作为SCL与SDA。 IIC通信协议:IIC通信协议较简单,主要由起始信号、数据帧、应答信号,停止信号组成。 其发送数据的形式如下。 ?传输数据前,STM32先产生一个起始信号,各从机接收到该信号后就知道主机要发送数据了,就会做好接受数据的准备。然后单片机开始发送一串数据(8位二进制数),然后进入等待应答状态,从机接收这串数据后,会返回一个应答信号给单片机,告诉单片机刚才的数据我已经接收到了。单片机收到应答信号后继续发送下一个数据帧,然后又进入等待应答状态,直到收到从机的应答信号。 一直循环下去,直到所有数据发送完。然后,单片机会发送一个停止信号,告诉从机,我的数据已经发送完了,你们可以休息了。从机收到停止信号后,就会停止接收数据,除非再次收到起始信号。当然,如果是与一个从机建立通信,发送完数据后也可以不发送停止信号,让通信一直保持,下次再发送数据就不需要再发送起始信号了。但如果有多个从机的话,不发送停止信号的话会让总线一直处于占用状态,导致其他从机无法与单片机通信(就好像跟女朋友打电话聊完了要及时挂断,否则你的好兄弟就无法呼叫你)。所以多从机下,发完数据就要及时发出停止信号。 接下来详细讲解各个信号以及如何在程序里实现。 首先我们这里先定义SCL与SDA的引脚,以及两个引脚置高、置低的函数。 将PA1作为SCL,PA2作为SDA。
延时函数:
由于SDA需要在输入输出模式之间切换(等待应答时需要将PA2切换成输入模式),所以还要定义这两个函数。输出模式用推挽输出即可,输入模式采用上拉输入模式(如果总线外接了上拉电阻,采用浮空输入也可以)。 关于STM32GPIO的模式可参考文章STM32_GPIO详解
起始信号: 发送起始信号之前,肯定要保证IIC总线处于空闲状态,如果总线正忙,起始信号肯定不能起作用的。所以先说说IIC的空闲状态。 IIC的空闲状态下,SCL与SDA都处于高电平。这种状态下,总线被释放(单片机从机都没有拉低总线),无数据传输。 起始信号是SCL处于高电平时,SDA出现下降沿。如下图虚线框内所示。 图中电平变化的坡度是为了便于理解,实际上的坡度不明显。 用程序实现如下
程序中,SDA与SCL都置高后,延时了1us再将SDA置低,这是为了保证SDA置低时,SCL处于高电平状态(单片机发出置高的指令后,IO口并不能立马置高,会有短暂的延时),同时也是给IIC从机有足够的时间采集总线电平状态。像一些低速IIC设备,他们采集电平状态速度较慢,主机就得跟着减缓发送数据的速度,即加大电平变换时的延时。而对于高速IIC设备,则可以减小延时。这也是制约IIC通信速率的因素之一。? 停止信号: 停止信号是SCL处于高电平,SDA出现上升沿。如下图虚线框内所示。 ?可以看到,停止信号过后,SDA与SCL都处于高电平状态,正好就是总线空闲状态。 用程序实现停止信号如下:
数据帧: 数据帧是数据发送的最小单位。 每个数据帧承载1KB数据,也就是8bit,对应着一个8位二进制数,这里我把它称为数据串。 IIC的是先发高字节再发低字节。例如,有一个数据为11001010,IIC在数据串中就是1-1-0-0-1-0-1-0,数据发送的先后顺序也是按照上面的排列顺序。 在IIC的协议中规定:SCL为低电平时,SDA才允许变换状态;SCL为高电平时,才读取SDA状态。 通俗的讲:在SCL为高电平时,IIC总线上的设备才会读取SDA的状态,在SCL为低电平时,则绝对不读取。这样规定是为了让IIC总线上的设备保持时序同步。 所以数据串的时序为:SCL置低——SDA根据要传输的数据位是0还是1置低或高——SCL置高——延时——SCL置低——SDA根据要传输的数据位是0还是1置低或高...? ? ? ? 以此循环八次,把8位数据传输完毕。 假设现在需要传输11001010这个8位二进制数,其电平变化应当如下: 用程序实现如下:
应答信号 应答信号就是用于确认对方已经收到数据的信号。一个完整的数据帧由数据串与一个应答信号组成。 在数据串发送完成之后,将SCL置低,SDA置高电平,然后STM32将SDA的IO口切换成输入模式(前面的SDA置高电平可以省略,因为切换成输入模式后总线会自动变成高电平),再将SCL置高电平。然后延时等待,如果从机收到刚才发送的数据,则会将SDA拉低,这个低电平就是应答信号。 此时的STM32因为处于输入模式,就会收到应答信号,则认为上个数据发送成功,就再切回输出模式,继续下一帧的数据传输,或者发出停止信号。如果没有收到应答信号,则认为数据发送失败,可以重新发送一遍刚才的数据,或者直接发送停止信号。 接着刚才的数据帧表示应答信号如下: 从程序实现如下:
IIC数据传输就是以上述信号和数据帧为基础,不断循环,将数据一帧一帧发送出去。 这篇文章只是简单的讲了IIC的时序与各信号与数据帧的程序实现,实际的IIC运用还跟从机的寄存器地址、命令有关,在下一篇文章中将以在OLED屏幕上显示"Hello world"为例,讲解STM32通过IIC与OLED屏幕的数据传输。 |
|
嵌入式 最新文章 |
基于高精度单片机开发红外测温仪方案 |
89C51单片机与DAC0832 |
基于51单片机宠物自动投料喂食器控制系统仿 |
《痞子衡嵌入式半月刊》 第 68 期 |
多思计组实验实验七 简单模型机实验 |
CSC7720 |
启明智显分享| ESP32学习笔记参考--PWM(脉冲 |
STM32初探 |
STM32 总结 |
【STM32】CubeMX例程四---定时器中断(附工 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 5:25:57- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |