专栏首页行走的机械人【通信专栏】STM32单片机/I2C通信(上篇)

【通信专栏】STM32单片机/I2C通信(上篇)

本文使用STM32FI03RCT6型号的单片机,
基于正点原子的函数库进行总结讲解

想来单片机这块儿除了USART串口通信外,常见的便是I2C通信了,因为I2C通信 硬件连接简单,可扩展性强,但是这种硬件连线的简洁,是以协议的复杂来弥补的。I2C通信是一种半双工通信,也就是可以双向传输数据但不能同时进行。

STM32单片机是可以进行硬件I2C通信或者软件模拟进行I2C通信的,硬件I2C通信只需要对I2C引脚以及通信模式这两个结构体进行初始化即可,但I2C硬件通信由于硬件原因并不稳定(原子哥说的),不过在STM32F4系列有所改善,但我都没试过(寒假在家手头硬件条件不足)。


下面我们基于软件I2C模拟进行说明。

I2C通信物理层原理

1:二线传输:I2C通信除了地线GND和电源线VCC外,只需要两条线,一条双向串行数据线(SDA),一条时钟线(SCL)。

2:无中心主机:可以多个设备并联到总线上,每一个设备都可以做为主机(或者从机)来发送,接受设备。但每一时刻只能有一个主机。

3:软件寻址:总线上的每一个设备都有一个唯一地址供识别,地址可以是7位或10位。

I2C通信协议层:传输过程

以STM32作为主设备发送数据为例:

步1:主机产生传输启示信号S,并联在总线上的所有设备都可以接收到

步2:所有从机开始准备接收接下来主机广播的从机地址,被选中设备(从设备)开始待命接收数据。其他设备便不再接收接下来的信息。

步3:主机开始向从设备发送数据,数据被拆分为数据包发送,每个数据包大小为8位(也就是一个字节一个字节的打包发送),从设备每接收到一个字节,便返回一个应答信号,主机再继续发送。

步4:如此传输N个数据后,主设备发送停止信号,数据传输停止

当主机读数据时:

主机广播完地址,接收到应答信号后,从机开始向主机返回数据包,大小也为8位。从机每发送一个包,等待主机的应答信号。如此反复发送N个字节后,当主机想要停止接收数据时,便向从机返回一个非应答信号,则从机停止数据发送。

到此我们了解了I2C通信的基本过程,但正点原子并没有直接操纵这些过程的库函数,所以我们需要需要更接近底层一步的时序问题;

1:空闲状态

总线的SDA和SCL两条信号线同时处于高电平时,规定为总线的空闲状态。空闲状态就是没有数据传输的状态啦。我们需要在每次数据传输之前将总线置为空闲状态

代码如下图:

图中代码为IIC初始化代码,先开启时钟,再设置引脚PC11,PC12模式。最后红框内为将时钟线SCL和数据线SDA均置高,即初始化为空闲状态。

2:起始信号与停止信号

在上面的IIC通信流程分析中,我们在通信开始时要由主机先发一个起始信号start,停止时要发一个停止信号stop:

  • 起始信号:当SCL为高期间,SDA由高到低的跳变;启动信号是一种电平跳变时序信号,而不是一个电平信号。
  • 停止信号:当SCL为高期间,SDA由低到高的跳变;停止信号也是一种电平跳变时序信号,而不是一个电平信号。

时序图如下:

ST32的代码实现:

在上面两图开头的SDA_OUT()为宏定义;含义如下图:

3:应答信号

主机每接收到一个数据包,都需要给从机返回一个应答信号A,应答信号为低电平时,规定为有效应答位(ACK简称应答位),表示接收器已经成功地接收了该字节;应答信号为高电平时,规定为非应答位(NACK),一般表示接收器接收该字节没有成功。

但这只是在过程上是如此,在时序上是如何进行的呢?我们知道每一个数据包都是八位,所以传输一个数据包在占据数据线SDA的同时,遵循时钟线SCL的脉冲时序(也就是一个脉冲发送一位,传输一个包需要占用8个时钟脉冲信号),而我们便在第九个时钟脉冲信号时释放数据线SDA(也就是拉低),然后空闲出来发送应答信号A。

不过我们只需要控制在该发送应答信号的第九个脉冲时序就可以了。

下面我们看代码:

上图是STM32做为主机发送数据等待从机的应答信号。

当STM32需要做出应答或者非应答信号时,便比较简单了:

在熟悉了上述过程以后,我们便可以进行写一个过程层面的函数,进行发送一整个字节或者接收一整个字节了(当然,是原子哥写的):

I2C的硬件实现:

据此我们便将I2C软件模拟的一些基本操作说完了,硬件I2C便是将上述这些我们手写的代码(原子哥手写的)作为硬件封装起来,我们只需要配置I2C模式结构体就可以了,就是下面这个结构体(注意啊,这个结构体是使用硬件I2C时使用的,别搞混了):

1:I2C_ClockSpeed设置的是I2C的传输速率

2:I2C_Mode设置的是I2C的使用模式,有I2C模式(I2C_Mode_I2C)和SMBus模式(I2C_Mode_SMBusDevice,I2C_Mode_SMBusHost)。

3:I2C_DutyCycle设置的是I2C的时钟线的占空比,可以设置高电平与时间之比为16:9(I2C_DutyCycle_16_9)或者2:1(I2C_DutyCycle_2)。

4:I2C_OwnAddress1设置的为STM32自己的I2C设备地址,每个连接在I2C总线上的设备都有一个自己的地址,作为主机也不例外。该地址可以自行设置,可以选择7位或者10位。

5:I2C_Ack设置的位I2C的应答,若为I2C_Ack_Enable,则允许应答;若为I2C_Ack_Disable,则不许应答。往往设为允许应答。

6:I2C_AcknowledgedAddress设置的为I2C寻址模式,需要根据通信对方的地址进行设置。对方地址为7位,则设置为7位寻址。


到此我们对于I2C通信的理论知识应该有了大概的了解了,但这远远不够,因为我们要对一个外部设备(从机)进行读写操作,还需要了解:

  • 从机的地址
  • 从机的数据组织形式(存储形式)
  • 从机的数据写入时序
  • 如何结合I2C时序编写对某外设的读写操作

这些内容我们在"STM32单片机/I2C通信(下篇)"进行介绍。

本文分享自微信公众号 - Opencv视觉实践(gh_31e12b1be0e0),作者:周旋

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-01-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 图像处理的回眸女郎是何方神圣?

    我以前没对她产生过太多的疑问,感觉人们都用这个图,肯定和我平时丧心病狂的图像处理一定要用二次元图片一个心理。

    周旋
  • 【电工与电子技术A】一:电路及其基本物理量

    一类电路用以实现电能的生产,传输,转换和分配,如店里供电设备与各用电设备组成的电力系统。

    周旋
  • 【通信专栏】附录一:单片机C语言基础/逻辑运算/按位运算/结构体/宏定义

    在单片机开发中,总有一些C语言基础知识是常常用到的而我们又不易掌握的,今天以STM32单片机为例,总结一下那些常用的C语言基础知识,例如逻辑运算符,结构体,宏定...

    周旋
  • M41T11-RTC(实时时钟)

    一、理论准备 1. 主要器件:STM8单片机、M41T11时钟IC、32.768kHz晶振等。 2. 外围设备:烧录工具ST-Link/v2、串口、5v供电SA...

    Christal_R
  • CTF从入门到提升(六)order_by注入及例题分享

    我们都知道常规的注入,比如id=100这种类型可以查询出一篇文章,如果把100换成99+1它一样可以查出,因为它会做计算。order_by 去判断列数的时候,如...

    牛油果
  • Android音视频系列:视频容器操作篇 -- mp4容器打包实现

    经过视频编码后的帧数据,需要放到视频容器里,才能成为一个常规的视频文件。我们以mp4容器为例子,聊一聊代码层面上帧数据如何放到mp4容器里。

    天天P图攻城狮
  • 干货 | 实践Hadoop MapReduce 任务的性能翻倍之路

    摘要:eBay的CAL(Central Application Logging)系统负责收集eBay各种应用程序的日志数据,并且通过Hadoop MapRedu...

    Spark学习技巧
  • (转)WPF Custom Control Dependency Property Gotcha

    原文地址:http://geekswithblogs.net/thibbard/archive/2008/04/22/wpf-custom-control-de...

    明年我18
  • 从企业关心角度,梳理“北上广深杭”五市惠企政策

    ? 来源:经纬创投  ID:matrixpartnerschina ---- 复工在即,我们梳理了北京、上海、广州、深圳、杭州对于中小企业的扶植政策,包含了大...

    腾讯SaaS加速器
  • 翻译 | Qt 5.15中自定义窗口的装饰

      这只是Qt 5.15中一个新功能的快速更新,我对此感到非常兴奋。传统上,窗口装饰一直是一件很无聊的事情。标题栏,边框,最小化,最大化,调整大小和退出,差不多...

    Qt君

扫码关注云+社区

领取腾讯云代金券