STM32 IIC EEPROM(24C02)__摘自<STM32库开发实战指南>
- F1系列似乎有硬件缺陷,使用软件模拟通信协议
- 物理层
- 数据线(传输数据)和时钟线(同步数据)
- 它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。
-
每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之间的访问。
- 总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而当所有设备都空闲,都输出高阻态时,由上拉电阻把总线拉成高电平
- 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用总线。
- 具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s ,高速模式下可达 3.4Mbit/s,但目前大多 I2C 设备尚不支持高速模式。
- 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制 。
- 协议层
- I2C 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节。
数据由主机传输至从机 S : 传输开始信号
SLAVE_ADDRESS: 从机设备地址
数据由从机传输至主机 R/W: 传输方向选择位,1 为读,0 为写
A/ A : 应答(ACK)或非应答(NACK)信号
P : 停止传输信号
- 读和写数据
- 除了基本的读写,I2C 通讯更常用的是复合格式,即第三幅图的情况,该传输过程有两次起始信号(S)。一般在第一次传输中,主机通过 SLAVE_ADDRESS 寻找到从设备后,发送一段“数据”,这段数据通常用于表示从设备内部的寄存器或存储器地址(注意区分它与 SLAVE_ADDRESS 的区别);在第二次的传输中,对该地址的内容进行读或写。也就是说,第一次通讯是告诉从机读写地址,第二次则是读写的实际内容。
- 起止信号
- 起始:
- 当 SCL 是高电平, SDA 线从高电平向低电平切换
- 终止
- 当 SCL 是高电平, SDA线由低电平向高电平切换,
- 数据有效性
- 时钟线高电平时,数据有效
-
时钟线低电平时,数据无效,此时进行电平切换,准备下一次传输
- 传输单位是字节,传输长度不受限制
- 地址和传输方向
- 紧跟设备地址的一个数据位用来表示数据传输方向,它是数据方向位(R/W),
- 数据方向位为“1”时表示主机由从机读数据,该位为“0”时表示主机向从机写数据。
- 响应
- I2C 的数据和地址传输都带响应。响应包括“应答(ACK)”和“非应答(NACK)”两种信号。作为数据接收端时,当设备(无论主从机)接收到 I2C 传输的一个字节数据或地址后,若希望对方继续发送数据,则需要向对方发送“应答(ACK)”信号,发送方会继续发送下一个数据;若接收端希望结束数据传输,则向对方发送“非应答(NACK)”信号,发送方接收到该信号后会产生一个停止信号,结束信号传输。
- 传输时主机产生时钟,在第 9 个时钟时,数据发送端会释放 SDA 的控制权,由数据接收端控制 SDA,
- 若 SDA 为高电平,表示非应答信号(NACK),低电平表示应答信号(ACK)。
- IIC外设简介(软件模拟可以不看)
- 通讯引脚
- 主发送器
- (1) 控制产生起始信号(S),当发生起始信号后,它产生事件“EV5”,并会对 SR1 寄存器的“SB”位置 1,表示起始信号已经发送;
- (2) 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6”及“EV8”,这时 SR1 寄存器的“ADDR”位及“TXE”位被置 1,ADDR 为 1 表示地址已经发送,TXE 为 1 表示数据寄存器为空;
- (3) 以上步骤正常执行并对 ADDR 位清零后,我们往 I2C 的“数据寄存器 DR”写入要发送的数据,这时 TXE 位会被重置 0,表示数据寄存器非空,I2C 外设通过SDA 信号线一位位把数据发送出去后,又会产生“EV8”事件,即 TXE 位被置 1,重复这个过程,就可以发送多个字节数据了;
- (4) 当我们发送数据完成后,控制 I2C 设备产生一个停止信号(P),这个时候会产生EV8_2 事件,SR1 的 TXE 位及 BTF 位都被置 1,表示通讯结束。假如我们使能了 I2C 中断,以上所有事件产生时,都会产生 I2C 中断信号,进入同一个中断服务函数,到 I2C 中断服务程序后,再通过检查寄存器位来判断是哪一个事件。
- 主接收器
- (1) 同主发送流程,起始信号(S)是由主机端产生的,控制发生起始信号后,它产生事件“EV5”,并会对 SR1 寄存器的“SB”位置 1,表示起始信号已经发送;
- (2) 紧接着发送设备地址并等待应答信号,若有从机应答,则产生事件“EV6”这时SR1 寄存器的“ADDR”位被置 1,表示地址已经发送。
- (3) 从机端接收到地址后,开始向主机端发送数据。当主机接收到这些数据后,会产生“EV7”事件,SR1 寄存器的 RXNE 被置 1,表示接收数据寄存器非空,我们读取该寄存器后,可对数据寄存器清空,以便接收下一次数据。此时我们可以控制 I2C 发送应答信号(ACK)或非应答信号(NACK),若应答,则重复以上步骤接收数据,若非应答,则停止传输;
- (4) 发送非应答信号后,产生停止信号(P),结束传输。在发送和接收过程中,有的事件不只是标志了我们上面提到的状态位,还可能同时标志主机状态之类的状态位,而且读了之后还需要清除标志位,比较复杂。我们可使用STM32 标准库函数来直接检测这些事件的复合标志,降低编程难度。
裸机--IIC--EEPROM
- 引脚连接
- 设备地址
- EEPROM 芯片的设备地址一共有 7 位,其中高 4 位固定为:1010 b,低 3 位则由 A0/A1/A2信号线的电平决定,图中的 R/W 是读写方向位,与地址无关。
- 按照我们此处的连接,A0/A1/A2 均为 0,所以 EEPROM 的 7 位设备地址是:1010000b ,即 0x50。
- 由于 I2C 通讯时常常是地址跟读写方向连在一起构成一个 8 位数,且当R/W 位为 0 时,表示写方向,所以加上 7 位地址,其值为“0xA0”,常称该值为 I2C 设备的“写地址”;
- 当 R/W 位为 1 时,表示读方向,加上 7 位地址,其值为“0xA1”,常称该值为“读地址”。
- 流程
- (1) 配置通讯使用的目标引脚为开漏模式(SDA,SCL);
- (2) 使能 I2C 外设的时钟;
- (3) 配置 I2C 外设的模式、地址、速率等参数并使能 I2C 外设;
- (4) 编写基本 I2C 按字节收发的函数;
- (5) 编写读写 EEPROM 存储内容的函数;
- (6) 编写测试程序,对读写数据进行校验。
- 单字节写入时序
- 页写入时序
- 对输入的数据进行分页(本型号芯片每页 8 个字节),通过“整除”计算要写入的数据NumByteToWrite 能写满多少“完整的页”,计算得的值存储在 NumOfPage 中,但有时数据不是刚好能写满完整页的,会多一点出来,通过“求余”计算得出“不满一页的数据个数”就存储在 NumOfSingle 中。计算后通过按页传输 NumOfPage 次整页数据及最后的NumOfSing 个数据,使用页传输,比之前的单个字节数据传输要快很多。
- 除了基本的分页传输,还要考虑首地址的问题,若首地址不是刚好对齐到页的首地址,会需要一个 count 值,用于存储从该首地址开始写满该地址所在的页,还能写多少个数据。实际传输时,先把这部分 count 个数据先写入,填满该页,然后把剩余的数据(NumByteToWrite-count),再重复上述求出 NumOPage 及 NumOfSingle 的过程,按页传输到 EEPROM。
- EEPROM 支持的页写入只是一种加速的 I2C 的传输时序,实际上并不要求每次都以页为单位进行读写,EEPROM 是支持随机访问的(直接读写任意一个地址),如前面的单个字节写入。在某些存储器,如 NAND FLASH,它是必须按照 Block 写入的,例如每个 Block 为 512 或 4096 字节,数据写入的最小单位是 Block,写入前都需要擦除整个 Block;NOR FLASH 则是写入前必须以 Sector/Block 为单位擦除,然后才可以按字节写入。而我们的 EEPROM 数据写入和擦除的最小单位是“字节”而不是“页”,数据写入前不需要擦除整页。
浙公网安备 33010602011771号