历史上的今天
今天是:2025年01月14日(星期二)
2021年01月14日 | STM32F10x_模拟I2C读写EEPROM
2021-01-14 来源:eefocus
Ⅰ、写在前面
说到IIC,大家都应该不会陌生,我们初学单片机的时候或多或少都知道或http://yunpan.cn/c6WawSRZLjJIa 访问密码
模拟I2C读写EEPROM综合版(切换SDA方向、检测ACK位)实例源代码工程:
http://yunpan.cn/c6WacI2eTkikZ 访问密码
I2C EEPROM(AT24xx)资料:
https://yunpan.cn/c667rIDPgvwTf 访问密码 1099
STM32F1资料:
https://yunpan.cn/crBUdUGdYKam2 访问密码 ca90
Ⅲ、关于I2C协议
I2C协议的描述请网上搜索,下面将结合时序图+源代码程序一起讲解关于I2C协议中重要的几点。
SCL时钟电平为高:
SDA数据线由高 -> 低 为总线开始条件;
SDA数据线由低 -> 高 为总线结束条件;
(注意:开始之后将SCL变为低电平,防止误操作SDA使其通信停止,见源代码)
时序图:

源代码程序:

2.数据位传输
SCL时钟电平为低, 可以改换SDA数据线的电平,在SCL上升沿的过程将SDA数据发送出去。
(切记:请先将SCL变为低电平,再改变SDA电平状态。 主要用于I2C读写Byte函数,这两个函数网上很多人写的不规范,引用需注意,在下面我会举例说明)
时序图:

发送一位“高”数据流程:
SCL_LOW时钟低 -> SDA_HIGH数据 -> SCL_HIGH时钟高
3.应答位信息
I2C 是以字节(8位)的方式进行传输,总线上每传输完1字节之后会有一个应答信号,主器件(主机)需要产生对应的一个额外时钟。
应答位产生及接收:
1.在(主机)写数据的时候是从机应答(给主机),主机检测;
2.在(主机)读数据的时候是主机应答(给从机),从机检测;
(这里可以借助I2C读写函数一起理解)
1.时序图(主机写,从机应答,主机读取应答):


2.时序图(主机读,主机产生应答):


4.I2C写一字节
这里说的I2C写,是主机往从机接入1Byte的数据;
“写”要求按照上面的“数据为传输”来操作:在SCL时钟为低电平时准备好,待SCL为高电平时发送出去。
写完一字节(8位)之后,读取从机的应答位:
若为0,表示从机应答,可以继续下一步操作;
若为1,表示从机非应答,不能进行下一步操作。
注意:
I2C写一字节不是EEPROM写一字节(需要区分开来)。
“简洁版”没有对应答信号做出检测判断,需要检测应答信号,可参考“综合版”
写一字节时序(前面8位数据 + 最后1为应答):

源代码程序:

I2C写数据(网上常见几种不规范写法 - 或许整个I2C驱动能通信成功,但各个函数之间依赖关系很强,不便理解,也不是标准的函数):
1.首先将SCL置高:
void I2C_WriteByte(uint8_t Data)
{
uint8_t cnt;
for(cnt=0; cnt<8; cnt++)
{
I2C_SCL_HIGH;
if(Data & 0x80)
I2C_SDA_HIGH;
else
I2C_SDA_LOW;
Data <<= 1;
I2C_SCL_LOW;
}
I2C_GetAck();
}
这种程序的写法有一个致命的地方(有可能停止,或重新开始I2C通信):
首先将SCL置高:
A.若之前SDA是低电平,第一位写入高电平,将停止I2C通信。
B.若之前SDA是高电平,第一位写入低电平,将重新开始I2C通信。
2.写完8位数据之后,未将SCL置低(也就是SCL保持高电平状态):
由于写完8位数据之后,将要读取应答信号,也就是要SDA将从输出状态变为输入状态。
这个时候SCL为高,如果SDA最后一位是低且SDA是开漏模式,需要将SDA释放,也就是要将SDA置位高,那么,这个时候就进行了一个停止操作。
3.时序混乱:
void I2C_WriteByte(uint8_t Data)
{
uint8_t cnt;
I2C_SCL_HIGH;
for(cnt=0; cnt<8; cnt++)
{
if(Data & 0x80)
I2C_SDA_HIGH;
else
I2C_SDA_LOW;
Data <<= 1;
I2C_SCL_LOW;
I2C_SCL_HIGH;
}
I2C_GetAck();
}
多种问题的例子,有可能产生以下问题:
A.有可能多写1位数据;
B.有可能停止I2C通信;
C.有可能重新开始I2C通信。
5.I2C读一字节
I2C的读一字节函数,其实和“写一字节”类似,只是数据传输方向相反,应答的方向也是相反。
读完一字节(8位)之后,由主机产生应答(或非应答)位:
若产生应答,表示可以继续读下一字节操作(从设备地址指向下一字节);
若产生非应答,表示不可以继续读下一字节操作;
网上I2C读数据程序和“写数据”类似,存在很多不标准的版本,参考时请注意。
读一字节时序(主机读取前面8位数据 + 主机产生1为非应答<连续读,主机产生应答位>):

读字节源代码程序:

Ⅳ、EEPROM读写
EEPROM的种类比较多,大多数都遵循I2C协议通信,我们这里就以典型的AT24Cxx为例来讲述通过I2C通信读写AT24Cxx芯片。
EEPROM读(或写)一字节数据需要I2C多次通信过程,下面将讲述几个重要的内容:
1.设备(从机、器件)地址

I2C的开始信号之后的第一步就是发送设备物理地址, AT24Cxx的物理地址的格式如上面:
前面四位固定为:1010
第567位对应A2 A1 A0(有些器件未使用)
第8位是读/写位。
一个设备一般是接地,这就是为什么我们看到A0这个宏定义的来由。
2.数据地址长度
有些芯片数据地址只有8位(如:AT24C01、AT24C02),那么它只发送一字节地址即可;
有些芯片有16位地址,它需要发送两字节地址(看下面读写函数)。

3.EEPROM写一字节数据
EEPROM写数据一般包含下面五步骤(见下面源代码)。这里的写数据,相当于手册中是随机写(任意地址,写一字节数据)。
(未检测应答,需要可以看我提供的另一个源代码程序)
注意两个地方:1.设备地址更加需要看你看引脚的情况;
2.数据地址长度根据芯片不同而不同。

4.EEPROM读一字节数据
EEPROM读数据和写数据相比,要多两个步骤(见下面源代码)。由于要先确定读的地址,所以要先发送地址,使其EEPROM指向对应的地址。(当然,如果当前地址就是需要读取的地址,也可以省略前面发送地址的步骤)。
(在手册中有这么一个步骤“Dummy Write”,有些人把它翻译为“伪操作”,可能很多人不明白它的意思,其实就是确定地址,先要发送地址的意思)
具体请看源代码:(未检测应答,需要可以看我提供的另一个源代码程序)
跟多关于EEPROM的操作(如:页写、多字节读写等),相对来说复杂一点,当你理解单字节读写操作之后,再去理解就容易的多了。具体内容可以下载我提供的实例参考学习。
Ⅴ、说明
EEPROM的读写操作按照I2C标准协议通信,请参看数据手册,有助于提高对I2C的理解。
以上总结仅供参考,若有不对之处,敬请谅解。
史海拾趣
|
汽车的方便、舒适等都和车身电子控制技术密不可分,车身电子控制技术也日益引起业界重视。 目前国际上车身电子集成控制技术比较成熟,其中有代表性的公司有德科电子、博世、欧姆龙等,他们在电子控制ECU方面已经历经几十年的研发和生产,技术较 ...… 查看全部问答> |
|
提供基于Vxworks的各种PowerPC平台(MPC82XX/MPC85XX/MPC7448/AMCC440GX等) Beijing Freesense是专业PowerPC设计公司,提供基于Vxworks和Liunx的各种PowerPC平台(MPC82XX/MPC85XX/MPC7448/AMCC440GX等),提供设计开发服务。Tel: 010-82790138、13501394847,zhytang@freesense.com.cn… 查看全部问答> |
|
移动软件开发工程师 职位要求: 1、嵌入式平台(WinCE,平台),应用软件开发; 2、熟悉J2ME开发。 3、具有良好的团队精神。 4、一年以上WinCE平台开发经验。 请有意者将简历mail至 suntjl@sina.com ...… 查看全部问答> |
|
下面是nboot(steldr——boot)里关于休眠唤醒的处理代码 WAKEUP_POWER_OFF ; Release SCLKn after wake-up from the POWER_OFF mode. ldr r1, =MISCCR & ...… 查看全部问答> |
|
各位,我不是很清楚嵌入式系统,请问我们外面买的那些MP3/4属于嵌入式系统吗?还有一个问题,我在网上看到基本上嵌入式系统好像就分两种,什么LINUX和WINCE,怎么区分呢,我做MP3开发的,是C语言和汇编混合的,不知道这个是属于哪种呢?谢谢!… 查看全部问答> |
|
1. 智能电网。智能电网可能是本次FTF最为突出的主题,其实去年FTF也就在推这个理念,当然大家都相信智能电网是大势所趋,飞思卡尔在智能电表和集中器方面展示了解决方案,其中集中器用的就是传说中的MCF54418 ...… 查看全部问答> |




