根据开发板的原理图,我们得知,
SPI连接处理器芯片和SD卡插座(CN4)
I²C连接处理器芯片和E²PROM(256B)芯片M24C02MN6(U6)
UART2连接处理器芯片和USB转串口芯片IC_FT2232D(U3)
UART1连接处理器芯片和串口转RS232芯片ST3232ECTR(U5)
JTAG连接处理器芯片和USB转串口芯片IC_FT2232D(U3)(这是因为CN2既是USB调试接口,也是USB转串口)
Flash是处理器芯片内置的,没有专门的芯片。
一、I2C
物理层:
1.I²C有俩根引脚,SCL(串行时钟线)和SDA(串行双向数据线),所以是半双工通信模式
2.每一个连接到I²C总线上的设备都有一个独立的地址(可以是7位或10位地址),主机(处理器)利用这个地址对不同设备进行访问。(rbt6开发板默认I²C总线只连接了E²PROM)
3.I²C支持一主多从式通信,所有设备共享总线。(从发送器模式、从接收器模式、主发送器模式、主接收器模式)
4.3种传输模式:标准模式(100kb/s)、快速模式(400kb/s)、高速模式(3.4mb/s)(CCR寄存器控制)
3种状态:高电平、低电平、高阻态
(1)当某个设备空闲时,处于高阻态,相当于把这个设备断开,此时其他设备进行通信时,不会受空闲设备干扰。
(2)当所有从设备处于空闲态,那么,所有从设备处于高阻态,SCL和SDA都会被上拉电阻拉到高电平。SCL不会再有脉冲变化。
(3)I²C总线规定,同一时间只能有一个设备占用总线。
(4)当某个设备要输出高电平,其他的设备一定是空闲,此时,相当于总线上只有主机和从设备,不论该设备是高阻态还是输出高电平,对于主机来说,都是高电平,因为如果这个设备也处于高阻态,上拉电阻会把整个总线电平拉高,使主机读取到高电平。
(5)I²C的从设备一般是使用高阻态来表示高电平
(6)那么,怎么区分总线是在输出高电平还是空闲?看SCL线,如果输出高电平,肯定是在SCL的一个边沿脉冲时读取到的,而如果是空闲,SCL也会被上拉电阻拉到高电平,自然不会有什么边沿脉冲,所以就不会读取到高电平了
(7)当某个设备输出低电平,其他的设备一定是空闲,此时,相当于总线上只有主机和从设备,总线的电平会被从设备接地的低电平拉低,变成低电平,主机读取到的就是低电平。
(8)如果没有高阻态,一旦一个从设备是低电平,另一个输出高电平,就可能导致短路。
(9)高阻态表示:总线处于空闲,可以和从设备进行通信。总线是低电平,表示总线正在被占用,不能和其他设备进行通信。
协议层:
由上面三个图,我们知道,不论是哪一种通信方式,都需要主机产生开始和终止信号。终止信号的产生,往往都是源于非应答信号。我们在计算机网络中的学习得知,非应答信号一般是由于数据传输完毕、数据丢失或数据错误产生的。前俩种都是在没有考虑数据丢失或数据错误的情况下的传输,第三个复合通信则考虑进来了;一旦接受到非应答信号,就重新发送一个起始信号,然后重新传递这些信息。
从发送和主接受需要在结束前发送非应答信号,主发送和从接受可以直接发送结束信号。
我们知道,当从设备都处于空闲,SCL和SDA都是处于高电平状态。那么,起始信号之前和终止信号之后,SCL和SDA都是处于高电平状态。
因此,起始信号是SCL高电平时,SDA的下降沿脉冲;终止信号是SCL高电平时,SDA的上升沿脉冲。
高低电平的获取则是在SCL的高电平时读取SDA的电平(不是边沿脉冲读取)。
主模式时, I2C接口启动数据传输并产生时钟信号。串行数据传输总是以起始条件开始并以停止条件结束。起始条件和停止条件都是在主模式下由软件控制产生。
从模式时, I2C接口能识别它自己的地址(7位或10位)和广播呼叫地址。软件能够控制开启或禁止广播呼叫地址的识别。
数据和地址按8位/字节进行传输,高位在前。跟在起始条件后的1或2个字节是地址(7位模式为1个字节, 10位模式为2个字节)。地址只在主模式发送。
在一个字节传输的8个时钟后的第9个时钟期间,接收器必须回送一个应答位(ACK)给发送器。
I2C有俩种实现发送:
硬件实现协议
软件模拟协议
I2C默认I2C1是PB6、PB7(开发板上就是这个);PB10、PB11是I2C2(开发板没有支持)
库函数:
根据原理图和AT24C02参考手册,我们知道,E²PROM的地址前4位固定是1010,后3位由硬件的引脚决定,在原理图中,A0、A1、A2都是接地,所以地址后3位应该是000,即E²PROM地址为1010000,最后一位位读/写位,至于到底何处写7位地址,何处写8位地址,看源码注释即可。
我们在自己编写IIC的传输函数时,应该严格遵守IIC传输时的时序编写
如,要给E²PROM传数据时,如上图,先传一个S(起始信号),然后检测事件EV5,然后传递7位设备地址加读写位的8位地址,(ACK在初始化IIC时已经设置为自动发送),然后检测EV6事件,然后发送数据,检测EV8事件,直到最后一个数据发送完毕,检测EV8_2事件,然后发送P(结束信号)。
接受一个E²PROM的数据,时序同样应该遵守。二、E²PROM
对E²PROM进行操作,在开发板中,其地址为1010000,最后一位位读/写位。
写E²PROM:按字节写入、按页写入
读E²PROM:顺序读取(从某一字节连续读取)、随机读取(指定某一字节读取)、读取当前地址(因为一般不知道当前地址,所以很少用)
E²PROM的数据传输需要在IIC传输的从设备地址后面再加一个E²PROM的内部地址,然后再传输数据
这个是EEPROM只写入一个字节。同样的,也应该严格的遵守时序。
我们可以发现,在EEPROM的时序基本和IIC时序相同。但如果想给EEPROM传递数据,第一个数据应该是EEPROM的内部地址(即0到255),第二个数据才是真正的数据。
这个是EEPROM写入多个字节
这个是从EEPROM读出一个字节。
读出字节时,又有所不同。分为俩个阶段。第一个阶段:发S信号,传EEPROM设备写地址,检测EV6事件后,传第一个数据(EEPROM内部地址)。第二个阶段:发S信号,传EEPROM设备读地址,然后检测EV6事件(EV6有俩个,这里应该是接收器模式的EV6),然后读出一个字节数据,检测EV7事件。然后手动发送一个NACK,最后发送P(结束信号)。下同。
这个是从EEPROM读出n多个字节
步骤:
一·、初始化I2C(只需要简单的调用库函数)
1.初始化I2C的GPIO接口
2.配置I2C的结构体
3.初始化I2C
4.使能I2C
二、读写EEPROM(需要严格按照时序编写)
5.编写I2C写入E2PROM的函数(按字节)
6.编写I2C读取E2PROM的函数(随机读取)
7.使用read和write进行校验
8.编写I2C写入和读取E2PROM的函数(按页写入、顺序读取)
初始化I2C
向EEPROM写一个字节
向EEPROM写n个字节(页写入)
页写入必须页对齐
(我们查看AT24C02手册时,会知道,大小为2kb的EEPROM,每页是8B,所以,页写入每次最多8个字节)
从EEPROM读n字节
等待EEPROM内部时序完成
这是因为EEPROM是非易失性存储器,速度比CPU要慢的多。在执行完写入EEPROM函数后,EEPROM内部时序仍然没有彻底完成。直接读数据,有可能卡在设备地址的发送上,导致程序卡死。(为什么是卡在这,我也不清楚)所以要等内部时序完成。(也可以直接进行简单的延时函数)
SB标志位:起始条件是否发送。
ADDR标志位:地址是否被发送
向EEPROM写n个字节
(不需要页对齐,且能写入任意不大于256个字节的数据)
以上都是属于i2c.c的内容
uart.c
(为什么需要写串口函数?)
因为我们需要通过串口调试助手回显I2C传递数据的结果到电脑屏幕。
main.c
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/18454.html