读写eeprom就要牵扯到iic通信了,通过查看原理图可知板子已将SCL和SDA拉高。
那么比赛的时候因为我们的赛点数据包只有一个英文的手册,没有查看手册基础的、英文不好的同学就容易看不懂手册。接下来我们来看看,使用eeprom都需要看那些内容。
1.地址 2.读写控制位 3.读和写的时序
地址:
根据图我们可以看到有八位数据数据分别是 1010 A2 A1 A0 R/W 根据原理图的接法,我们可以看到A2 A1 A0 都是连接地的,所以地址基本上就已经确定了,当执行写的时候R/W的值就是0 按权值相加得到的结果就是 0xa0 如下所示
1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
如果是写操作的话R/W的值为 1 按权值相加得到的结果就是 0xa1 如下所示
1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 |
读和写的时序:
写的时序:
将代码和时序进行对照我们不难读懂这个时序的意思。
根据对应的点,可以通过查看数据手册进行使用而不用进行死记硬背了。
unsigned char readAT24C02(unsigned char address)
{
unsigned char date;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(address);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
date = IIC_RecByte();
IIC_Stop();
return date;
}
根据同样的方式,我们不难将时序图上的点和代码对应起来,这样就不需要进行死记硬背。
写完 eeprom的读写驱动后,在使用的时候需要在读写操作之间添加 10ms 左右的延时,例如下方所示,延时函数可以在 STC-isp中生成。
write_eeprom(0x01,0xfe);
Delay10ms();
date=read_eeprom(0x01);
以下是赛点数据包提供的底层驱动代码
IIC.c
#include "reg52.h"
#include "intrins.h"
#include "iic.h"
#define DELAY_TIME 5
#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1
//总引脚定义
sbit SDA = P2^1; /* 数据线 */
sbit SCL = P2^0; /* 时钟线 */
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//总线启动条件
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//总线停止
void IIC_Stop(void)
{
SDA = 0;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//发送应答
void IIC_SendAck(bit ackbit)
{
SCL = 0;
SDA = ackbit; // 0£ºÓ¦´ð£¬1£º·ÇÓ¦´ð
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
SDA = 1;
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
if(SDA)
{
SCL = 0;
IIC_Stop();
return 0;
}
else
{
SCL = 0;
_nop_();
return 1;
}
}
//通过i2c总线发送数据
void IIC_SendByte(unsigned char byt)
{
unsigned char i;
for(i=0; i<8; i++)
{
SCL = 0;
IIC_Delay(DELAY_TIME);
if(byt & 0x80) SDA = 1;
else SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 1;
byt <<= 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
}
//从总线上接收数据
unsigned char IIC_RecByte(void)
{
unsigned char i, da;
for(i=0; i<8; i++)
{
SCL = 1;
IIC_Delay(DELAY_TIME);
da <<= 1;
if(SDA) da |= 1;
SCL = 0;
IIC_Delay(DELAY_TIME);
}
return da;
}
iic.h
#ifndef _IIC_H
#define _IIC_H
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char dat);
unsigned char IIC_RecByte(void);
#endif