学习AT24C02的基本原理和使用方法——蓝桥杯单片机比赛第十课
基本原理
AT24C02实际上就是一个具有 I2C 总线接口的存储器,可以读写数据。AT24C02 存储器特点如下:容量为 256×8( 2KB);具体的i2c协议这里就不讲了,我们这里只讲AT24C02在比赛中的使用方法,这样能让我们快速的上手参加比赛。
AT24C02实际上和PCF8591差不多,都是8位寄存器,如下图1,高4位是生产厂家规定器件地址为1010(不可编程更改);低4位为可编程更改,其中A3、A1、A0默认接地(GND)如下图2,所以此寄存器的前7位都是不需要更改的,需要编程更改地址只有最后一位方向位 R/W,当主控器对 存储器进行读操作时为 1,进行写操作时为 0。也就是我们通常写的IIC_SendByte(0xA0)、IIC_SendByte(0xA1);。0xA0表示写操作;0xA1表示读操作。


使用方法
读存储器数据
步骤:
1.写操作 IIC_SendByte(0xa0);
2.确定要读取的地址 IIC_SendByte(addr);
3.读操作 IIC_SendByte(0xa1);
4.从要读取的地址中读取数据 dat=IIC_RecByte();
代码如下:
unsigned char read_AT24C02(unsigned char addr)//因为该存储器为8位寄存器,所以我们返回值的类型为unsigned char(8位)
{
unsigned char dat=0;
IIC_Start();
IIC_SendByte(0xa0);/* 写操作 */
IIC_WaitAck();
IIC_SendByte(addr);/* 将要读取的地址写入 */
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);/* 读操作 */
IIC_WaitAck();
dat=IIC_RecByte();/* 用变量将数据保存 */
IIC_SendAck(1);//(非应答)停止数据传输
IIC_Stop();
return dat;
}
向存储器内写入数据
步骤:
1.写操作 IIC_SendByte(0xa0);
2.确定要写入的地址 IIC_SendByte(addr);
3.写入数据 IIC_SendByte(dat);
代码如下:
void write_AT24C02(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);/* 写操作 */
IIC_WaitAck();
IIC_SendByte(addr);/* 确定要写入的地址 */
IIC_WaitAck();
IIC_SendByte(dat);/* 写入数据 */
IIC_SendAck(1);
IIC_Stop();
}
注意:当我们要连续写入数据时,在每次写入数据之后都要至少延迟5ms再进行下一次数据写入!!!!!!!!!!。
write_AT24C02(0x01,dat1);/* 向地址0x01地址中写入dat1数据 */
delay_ms(5); /* 必须延迟5ms以上,否则对后面写入的数据有影响!!! */
write_AT24C02(0x03,dat2);
delay_ms(5);
write_AT24C02(0x05,dat3);
delay_ms(5);
代码实现
此处借助小蜜蜂老师的题目
main.c文件:
#include "iic.h"
unsigned char dat1=0,dat2=0,dat3=0;
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0x88,0x83,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
void Delay1ms() //@12.000MHz
{
unsigned char i, j;
i = 12;
j = 169;
do
{
while (--j);
} while (--i);
}
void delay_ms(int x)
{
while(x--)
{
Delay1ms();
}
}
void Select_HC573(unsigned char channel,unsigned char dat)
{
P0=0x00;
P0=dat;
switch(channel)
{
case 4:
P2=(P2&0X1F)|0X80;
break;
case 5:
P2=(P2&0X1F)|0Xa0;
break;
case 6:
P2=(P2&0X1F)|0Xc0;
break;
case 7:
P2=(P2&0X1F)|0Xe0;
break;
case 0:
P2=(P2&0X1F)|0X00;
break;
}
P2=(P2&0X1F)|0X00;
}
void SMG_Display_Bit(unsigned char pos,unsigned char value)
{
Select_HC573(6,0x01<<pos-1);
Select_HC573(7,value);
delay_ms(2);
Select_HC573(6,0x01<<pos-1);
Select_HC573(7,0xff);
}
void SMG_Display_All(unsigned char value)
{
Select_HC573(6,0xff);
Select_HC573(7,value);
}
void SMG_Display(void)
{
SMG_Display_Bit(1,SMG_NoDot[dat1/10]);
SMG_Display_Bit(2,SMG_NoDot[dat1%10]);
SMG_Display_Bit(3,SMG_NoDot[0xbf]);
SMG_Display_Bit(4,SMG_NoDot[dat2/10]);
SMG_Display_Bit(5,SMG_NoDot[dat2%10]);
SMG_Display_Bit(6,SMG_NoDot[0xbf]);
SMG_Display_Bit(7,SMG_NoDot[dat3/10]);
SMG_Display_Bit(8,SMG_NoDot[dat3%10]);
}
unsigned char read_AT24C02(unsigned char addr)
{
unsigned char dat=0;
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0xa1);
IIC_WaitAck();
dat=IIC_RecByte();
IIC_SendAck(1);//(非应答)停止数据传输
IIC_Stop();
return dat;
}
void write_AT24C02(unsigned char addr,unsigned char dat)
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_SendAck(1);
IIC_Stop();
}
void read_write24c02(void)
{
dat1=read_AT24C02(0x01);
dat2=read_AT24C02(0x03);
dat3=read_AT24C02(0x05);
dat1=dat1+1;
dat2=dat2+2;
dat3=dat3+3;
if(dat1>10)
dat1=0;
if(dat2>20)
dat2=0;
if(dat3>30)
dat3=0;
write_AT24C02(0x01,dat1);
delay_ms(5);
write_AT24C02(0x03,dat2);
delay_ms(5);
write_AT24C02(0x05,dat3);
delay_ms(5);
}
void System_init(void)
{
Select_HC573(0,0x00);
Select_HC573(4,0xff);
Select_HC573(5,0x00);
SMG_Display_All(0xff);
}
void main(void)
{
System_init();
read_write24c02();
while(1)
{
SMG_Display();
}
}
iic.c文件:
#include "iic.h"
#define DELAY_TIME 5
//I2C总线内部延时函数
void IIC_Delay(unsigned char i)
{
do{_nop_();}
while(i--);
}
//I2C总线启动信号
void IIC_Start(void)
{
SDA = 1;
SCL = 1;
IIC_Delay(DELAY_TIME);
SDA = 0;
IIC_Delay(DELAY_TIME);
SCL = 0;
}
//I2C总线停止信号
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;
IIC_Delay(DELAY_TIME);
SCL = 1;
IIC_Delay(DELAY_TIME);
SCL = 0;
SDA = 1;
IIC_Delay(DELAY_TIME);
}
//等待应答
bit IIC_WaitAck(void)
{
bit ackbit;
SCL = 1;
IIC_Delay(DELAY_TIME);
ackbit = SDA;
SCL = 0;
IIC_Delay(DELAY_TIME);
return ackbit;
}
//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;
}
//I2C总线接收一个字节数据
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
#include "stc15f2k60s2.h"
#include "intrins.h"
sbit SDA = P2^1;
sbit SCL = P2^0;
void IIC_Start(void);
void IIC_Stop(void);
bit IIC_WaitAck(void);
void IIC_SendAck(bit ackbit);
void IIC_SendByte(unsigned char byt);
unsigned char IIC_RecByte(void);
#endif