写的不知道好不好,有什么不对的地方还请指出,谢了。
1、上节已经单独写好了IIC驱动代码,本次驱动AT24C02就直接拿来用了。
2、首先,运用了go to语句,不知道如何使用的可自行学习。
3、驱动AT24C02,接口代码5个:写1字节数据、读1字节数据、页写(1页16个字节)、页读(1字节,搭配for循环可以16个字节)、擦除EEPROM。
4、本代码里加入了判断通讯是否异常,感觉好啰嗦,应该单独写一个测试代码(测试代码以后在写),把正常通讯的精简一下。
#ifndef __AT24C02_H__
#define __AT24C02_H__
//向某个器件存入数据,字节写,ddr表示器件地址,a_datax表示要将数据准备写入eeprom哪个地方,datax表示要写入到eeprom里的数据
//函数返回1表示写入成功,0表示写入失败
bit write_1byte_at24c02(unsigned char ddr, unsigned char a_datax, unsigned char datax);
//向器件存入数据,页写,ddr表示器件地址,a_datax表示要EEPROM地址,数组datax【16】表示要写入16个数据
//函数返回1表示写入成功,0表示写入失败
bit write_page_at24c02(unsigned char ddr, unsigned char a_datax, unsigned char datax[16]);
//向器件读取数据,字节读
//函数返回0表示通讯失败,不为0则读取正常。
unsigned char read_1byte_at24c02(unsigned char ddr, unsigned char a_datax);
//向器件读取数据,页读 本函数只读取一个字节的数据,需要搭配for循环使用
unsigned char read_page_at24c02(unsigned char ddr, unsigned char a_datax);
//擦除器件数据 ddr为器件地址,本开发板器件地址为0xa0 (0xa0写 0xa1读)
//函数返回1表示擦除成功,0表示擦除失败,并且iic通讯异常
bit erase_at24c02(unsigned char ddr);
#endif // !__AT24C02_H__
//P2^1;//时钟连接P2.1口
//P2^0;//时钟连接P2.0口
//at24c02芯片地址为1010 xxxy最后4位看原理图,在本单片机里芯片地址位1010 000y其中y位表示是读取器件还是向器件写入
//at24c02芯片内部地址为256字节,一页16个字节,共计16页,高4位为页地址(0-16),低4位为页单元地址(0-16)
//页写:发送16个字节的数据,每发送一个字节,芯片响应一个应答信号,同时,寻址字节低位自动加1,而高位不变。
//字节写:写地址,写数据,接收应答,然后在写地址,再写数据,在接收应答。。。。。。。
#include "iic.h"
#include"delay.h"
//向某个器件存入数据,字节写,ddr表示器件地址,a_datax表示要将数据准备写入eeprom哪个地方,datax表示要写入到eeprom里的数据
//函数返回1表示写入成功,0表示写入失败
bit write_1byte_at24c02(unsigned char ddr,unsigned char a_datax,unsigned char datax)
{
unsigned char x;
do
{
START_IIC();
write_1_byte_IIC(ddr);//器件
if (read_ACK_IIC() == 0)
{
write_1_byte_IIC(a_datax);//地址
if (read_ACK_IIC() == 0)
{
write_1_byte_IIC(datax);//数据
if (read_ACK_IIC() == 0)
{
STOP_IIC();
delay_ms(60);//延迟一段时间让at24c02开始写数据进入eeprom里面
return 1;//函数返回1,iic通讯正常
}
else
{
STOP_IIC();
}
}
else STOP_IIC();
}
else STOP_IIC();
x++;
if (x == 10)//如果循环10次还没有写入数据进去,表示通讯有异常
{
STOP_IIC();
return 0;//函数返回0,iic通讯异常
}
}while (1);
}
//向器件存入数据,页写,ddr表示器件地址,a_datax表示要EEPROM地址,数组datax【16】表示要写入16个数据
//函数返回1表示写入成功,0表示写入失败
bit write_page_at24c02(unsigned char ddr,unsigned char a_datax, unsigned char datax[16])
{
unsigned char x = 0;//流水号
unsigned char y;
page:
START_IIC();//iic通讯开始信号
write_1_byte_IIC(ddr);//0xa0表示at24c02器件地址,0表示要向它接下来写入数据
if (!read_ACK_IIC())//检测从器件ACK信号
{
write_1_byte_IIC(a_datax);//a_datax页,第0地址准备写入数据
if (!read_ACK_IIC())//检测从器件ACK信号
{
for (y = 0;y < 16;y++)//共计写16个字节数据,每次写入一页
{
write_1_byte_IIC(datax[y]);//开始向eeprom写入数据
if (!read_ACK_IIC());//读取ACK
else
{
x++;//流水号
STOP_IIC();//未收到ack则结束本次通讯
goto page;//从头开始
}
if (y == 15)
{
STOP_IIC();//第y页写入完成
delay_ms(10);//结束本页擦除,延迟10ms,让芯片处理擦除操作
return 1;//函数返回1,本次通讯结束
}
}
}
else//器件未发送应答信号,本次通讯异常,需要重新建立通讯
{
x++;//流水号
STOP_IIC();
goto page;
}
}
else
{
x++;//流水号
STOP_IIC();
if (x >10) return 0;//如果芯片不发送ack应答信号10次则返回0表示iic通讯异常
goto page;//重新发送器件地址
}
}
//选择地址从器件读取数据,字节读
//函数返回0表示通讯失败,不为0则读取正常。
unsigned char read_1byte_at24c02(unsigned char ddr, unsigned char a_datax)
{
unsigned char datax;
unsigned char i = 0;
read: //先开始信号,空写器件,接收应答,发送空写eeprom地址,接收应答,发送开始信号,发送读器件,接收应答,接收发来的数据
START_IIC();//开始信号
write_1_byte_IIC(ddr&0xfe);//操作地址 空写
if(!read_ACK_IIC())
write_1_byte_IIC(a_datax);//eeprom地址
if(!read_ACK_IIC())
START_IIC();
write_1_byte_IIC(ddr);//器件地址及准备读取数据
if (!read_ACK_IIC())
{
datax = read_1_byte_IIC();
write_ACK_IIC(1);//发送No ack
STOP_IIC();//结束本次通讯
return datax;//返回结果给函数
}
else
{
i++;
if (i > 10)
{
STOP_IIC();
return 0;
}
else
{
STOP_IIC();
goto read;
}
}
}
//向器件读取数据,页读 本函数只读取一个字节的数据,需要搭配for循环使用
unsigned char read_page_at24c02(unsigned char ddr, unsigned char a_datax)
{
unsigned char datax;
START_IIC();
write_1_byte_IIC(ddr);
read_ACK_IIC();
write_1_byte_IIC(a_datax);
read_ACK_IIC();
datax = read_1_byte_IIC();
write_ACK_IIC(1);
STOP_IIC();
return datax;
}
//擦除器件数据 ddr为器件地址,本开发板器件地址为0xa0 (0xa0写 0xa1读)
//函数返回1表示擦除成功,0表示擦除失败,并且iic通讯异常
bit erase_at24c02(unsigned char ddr)
{
unsigned char x=0;
unsigned char i;
unsigned char y;
erase:
START_IIC();//iic通讯开始信号
write_1_byte_IIC(ddr);//0xa0表示at24c02器件地址,0表示要向它接下来写入数据
if (!read_ACK_IIC())//检测从器件ACK信号
{
for (i = 0;i < 16;i++)//循环16页
{
write_1_byte_IIC(0x00 + i * 16);//向i页,第0地址准备写入数据
if (!read_ACK_IIC())//检测从器件ACK信号
{
for (y=0;y < 16;y++)//共计写16个字节数据,每次擦除一页
{
write_1_byte_IIC(0xff);//开始写1即擦除eeprom
if (!read_ACK_IIC());//读取ACK
else
{
STOP_IIC();//未收到ack则结束本次通讯
goto erase;//从头开始
}
if (y == 15)
{
STOP_IIC();//第i页写入完成
delay_ms(10);//结束本页擦除,延迟10ms,让芯片处理擦除操作
START_IIC();//开始i+1页写入
write_1_byte_IIC(ddr);//器件地址
if (!read_ACK_IIC());
else
{
if (i == 15)//判断没有ack应答16页是否传送完了,若传送完了就结束通讯
{
STOP_IIC();//16页传送完成,结束擦除
return 1; //函数返回1表示本次擦除eeprom成功
}
else
{
STOP_IIC();//未收到ack则结束本次通讯
goto erase;//从头开始
}
}
}
}
}
else//器件未发送应答信号,本次通讯异常,需要重新建立通讯
{
i--;
STOP_IIC();
goto erase;
}
if (i==15)
{
STOP_IIC();
return 1;//擦除成功,函数返回1
}
}
}
else
{
x++;
STOP_IIC();
if (x == 10) return 0;//如果芯片不发送ack应答信号10次则返回0表示iic通讯异常
goto erase;//重新发送器件地址
}
}