时序回顾(加速版)
先回顾 IIC 的时序 ——
总线空闲:SDA = 1,SCL = 1;
启动信号:SCL = 1,SDA 1 -> 0;
停止信号:SCL = 1,SDA 0 -> 1;
数据传输:SCL为1时,SDA必须保持稳定,即为0或1;
SCL为0时,才允许改变SDA状态;
SCL在上升沿时写入数据,在下降沿时读出数据;
应答信号:为0时,是有效应答,为1时,是无效应答;
传输到最后一个字节后,要发送一个无效应答,再发送停止信号;
总线封锁:将SCL锁定为0即可;
多次数据通信,采用复启动信号,即写一个停止信号,再接上一个启动信号;
单片机为主机,24C02为从机;
SCL时钟由主机控制;
写时应答信号从机给出;
读时由主机给出;
24C02器件地址:前四位默认为1010,后四位的前三位为A0,A1,A2,均已接地,即为0,
最后一位为读写保护位,写时为0(0xA0),读时为1(0xA1).
器件地址:
单字节写与页写:
当前地址读取与随机地址读取:
连续地址读取:
代码快速配置
打开赛点资源数据包_嵌入式\3-底层驱动代码参考——
将i2c.c与i2c.h加入工程文件,然后在.c文件写入字节读取和写入函数。
函数代码
根据时序图写代码 ——
单字节写入
void E2PROM_Write(unsigned char addr, unsigned char data)
{
do{
I2CStart();//起始信号
I2CSendByte(0xa0);//发送器件地址
if(I2CWaitAck() == SUCCESS)break; //等待应答
I2CStop();
}while(1);
I2CSendByte(addr);//发送数据地址
I2CWaitAck();//等待应答
I2CSendByte(data);//发送数据
I2CWaitAck();//等待应答
I2CStop();//停止信号
}
注意:应答信号
注意:此次应答信号不能写为 if(I2CWaitAck() == 0)break;
在应答信号函数的定义中,无效应答返回FAILURE,有效应答返回SUCCESS;
跳转到两个字符常量的定义可以发现,FAILURE为0,SUCCESS为1。
所以这里应答信号我们要写为 等于SUCCESS。
多字节页写
/*******************************************************************************
* 函数名 :E2PROM_Write_long
* 输入值 :unsigned char *buf,unsigned char addr,unsigned char len
* 返回值 :none
* 作者 :Moqim Flourite.
* 时间 :2022年3月2日
* 功能描述:连续写入一页数据
* 备注 :buf为源数据指针,addr为E2PROM中要写入的数据起始地址,len为写入长度。
*******************************************************************************/
void E2PROM_Write_long(unsigned char *buf,unsigned char addr,unsigned char len){
while(len){
do{
I2CStart();
I2CSendByte(0xa0); //用寻址操作查询当前是否可进行读写操作
if(I2CWaitAck() == SUCCESS)break; //应答则跳出循环,非应答则进行下一次查询
I2CStop();
}while(1);
I2CSendByte(addr);
I2CWaitAck();
while(len --){
I2CSendByte(*buf ++); //写入一个字节数据
I2CWaitAck();
addr ++; //E2PROM地址递增
if((addr & 0x07) == 0)break;//检查地址是否到达页边界,24C02每页8字节
} //到达页边界时,跳出循环,结束本次写操作
I2CStop();
}
}
单字节读取:
unsigned char E2PROM_Read(unsigned char addr)
{
unsigned char data;
do{
I2CStart();
I2CSendByte(0xa0);
if(I2CWaitAck() == SUCCESS)break;
I2CStop();
}while(1);
I2CSendByte(addr);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
data = I2CReceiveByte();
I2CSendNotAck();
I2CStop();
return data;
}
多字节读取:
/*******************************************************************************
* 函数名 :E2PROM_Read_long
* 输入值 :unsigned char *buf,unsigned char addr,unsigned char len
* 返回值 :none
* 作者 :Moqim Flourite.
* 时间 :2022年3月2日
* 功能描述:连续读取多字节数据
* 备注 :buf为存储数组指针,addr为E2PROM中要读取的数据起始地址,len为读取长度。
*******************************************************************************/
void E2PROM_Read_long(unsigned char *buf,unsigned char addr,unsigned char len){
do{
I2CStart();
I2CSendByte(0xa0);
if(I2CWaitAck() == SUCCESS)break;
I2CStop();
}while(1);
I2CSendByte(addr);
I2CWaitAck();
I2CStop();
I2CStart();
I2CSendByte(0xa1);
I2CWaitAck();
while(len --){
*buf++ = I2CReceiveByte();
I2CSendAck();
}
I2CSendNotAck();
I2CStop();
}