又见面啦,已经有太久没有更新过文章哩,今天心血来潮想更新一下这两天调试IIC的收获。
最近在用64*16的点阵屏做一个可调时钟,其中有一个功能就是时间日历信息的显示啦,我在做硬件的时候选择了DS3231这个时钟芯片,这颗IC不用外挂晶振,通讯方式的话就是IIC通讯,我们都知道STM32的硬件I2C似乎有一点不靠谱,因此我在软件设计上采用了软件模拟I2C时序的方法实现MCU和DS3231的通讯。几年前在做I2C的时候那时候仅仅局限于代码和时序,并没有详细的抓出他的波形来分析,所以总会感觉欠缺了什么,有问题的话也比较难排查,因此今天的重点也就是I2C通讯的时序问题了。
在软件上我配置了两个GPIO为推挽输出,在通讯线上加了4.7K的上拉电阻(上拉电阻很重要),如果没有这个上拉电阻会怎么样呢,小编亲测过,如果没有的话,你用逻辑分析仪去抓取I2C的通讯时序的时候会发现有时候能抓到,有时候怎么都抓不到,即便是抓到了波形,分析一下数据也是错误的,不是我们发送或者读取的数据。
接下来简单的看一下硬件,为等下说软件打一个基础,下图是小编画的DS3231的图:
外围电路很简单,没什么好说的,如果想要知道每个元件具体有什么作用我在这里就不详细说明了,有兴趣的话可以加我联系方式问我,或者可以直接去看数据手册,上面写的简直不要太清楚。
从上面的图可以看出,I2C有两根线,一根SDA:数据线,一根SCL:时钟线
稍微有点基础的应该都知道I2C通讯无非就是几个模块,分为:
1、起始信号
2、终止信号
3、应答/非应答信号
4、写时序
5、读时序
那我们就一个一个来说吧!
- 起始信号
先来看看起始信号的时序图是怎样的吧!
这就是起始信号,第一次看的话会不会有点迷糊呢,其实很简单,请看下面一句话搞定:
重点!重点!重点!
起始信号信号时序:
在时钟线(SCL)为高电平期间,数据线(SDA)产生一个下降沿
对,就是这么简单,那我们就可以先敲出起始信号的代码啦!如下图
再来看看第二个吧
- 终止信号
时序图如下:
一句话理解:
在SCL为高电平期间,SDA产生一个上升沿
因此,代码如下
- 应答/非应答信号
还是一样来看看时序吧!
这个图就再简单不过啦,
应答信号一句话理解:
SCL为高电平期间,SDA为低电平时产生应答信号
非应答信号时序图
非应答信号一句话理解:
SCL为高电平期间,SDA为高电平时产生非应答信号
从上面可以看出应答和非应答信号的区别就在于SCL线高电平期间的SDA线的不同,进而产生应答或非应答信号!那代码,我们可以这样写:
函数中形参ACK写1的时候为非应答,写0的时候即为应答信号
四、写时序
写时序的时序图要稍微复杂一点点一点点而已,仅此而已
看图的话可能又进入懵逼的状态了
起始就是发送一个字节,一位一位的传输而已,直接看代码就能很好理解啦
读时序的代码也放上来吧
定义了一个有返回值的函数,返回Read_Dat即为I2C读取到的数据,此时要注意的是,stm32中需要把SDA线配置为输入模式
我在这里也就只是用了一个宏定义,如下图
用这个宏定义来读取SDA线的状态,一位一位的发送给主机,让主机读取
再来看一下发送数据和读取数据的过程是什么样子的
发送数据:
S:表示起始信号
A:表示应答信号
P:表示终止信号
Data:即为发送的数据
来看一下代码上怎么实现发送数据
也简直不要太简单,先产生起始信号,再发送地址,再发送数据,最后一个停止信号,这样就完成I2C完整的发送数据啦
读取数据也是差不多的,先看看图
这里就直接放代码啦:(以DS3231为例)
好啦,关键的代码都放的差不多啦,主要写出来代码后一定一定要用逻辑分析仪去看波形,才能知道错在那里,为什么通讯不成功,这样才能彻底弄懂I2C通讯的过程!
有到了说再见的时候的了(心中一万个不舍),哈哈哈哈!拜拜
如果有什么不对的地方请联系小编更改修正哦!