目录
一、竞赛板AT24C02相关资料解析
AT24C02是一款I2C总线的存储器芯片,竞赛现场提供了电路接口(竞赛板的店原理图)、AT24C02芯片资料(英文版)、基础程序模块(I2C总线驱动程序)。下面从竞赛的视角地掌握这些,快速地写出应用程序。
1、AT24C02硬件接口
从图中可见,AT24C02的与CPU芯片接口电路用了2个I/O口线:P2.0时钟线,P2.1数据线。在编写程序时对它们进行设置。
2、AT24C02模块程序
竞赛现场提供了底层驱动程序,根据I2C总线的操作时序以C语言形式编写,具体模块如下:
void i2c_delay(unsigned char i);//I2C总线中一些必要的延时函数
void i2c_start(void);//产生I2C总线启动条件
void i2c_stop(void);//产生I2C总线停止条件
void operate_delay(unsigned char t);//读写操作过程中一些必要的延时
void i2c_sendbyte(unsigned char byt);//I2C发送一个字节的数据
unsigned char i2c_waitack(void); //等待应答
unsigned char i2c_receivebyte(void); //I2C接收一个字节数据
void i2c_sendack(unsigned char ackbit);//发送应答
在了解AT24C02芯片资料和操作时序后就可以根据上述函数快速地编写应用程序。
3、AT24C02芯片资料解读
(1)器件读写地址
上图是从AT24C02资料上截取的器件地址格式,由8位二进制数构成,高4位是固定的1010,A2、A1、A0是芯片的引脚地址,与芯片的工作电路有关,最低位是读/写,R/W=0为写操作地址,R/W=1为读操作地址。
结合前面的硬件接口电路,竞赛板上的AT24C02的写操作地址为:a0h。读操作地址为a1h。
(2)AT24C02工作时序
上图为字节写时序,即向AT24C02内部指定空间写入1个字节数据。
上图为页写时序,AT24C02分页是8个连续的空间为一页,页写时不能跨页,因此页写需要注意,一次页写最多写入8个字节数据,并且地址必须能被8整除,即低位是0h或8h。不是从页的开头页写需要注意写入数据的字节数。另外两次写入操作中需要10ms左右的延时。
上图时随机读时序,从AT24C02指定的地址空间读出1个字节信息。
掌握上面3个操作时序,就可以编写竞赛板上AT24C02的操作。
AT24C02的操作时序是标准的I2C时序,软件资料C语言模块中提供了时序函数,如图中的START、STOP、ACK、写字节、读字节等。把这些函数与时序图对应起来就可以实现对AT24C02读写操作。分别以页写和随机读为例:
页写时序对应函数:
i2c_start(); //启动
i2c_sendbyte(unsigned char byt);//写字节,参数器件写地址
i2c_waitack(void); //等待应答
i2c_sendbyte(unsigned char byt);//写字节,AT24C02空间地址
i2c_waitack(void); //等待应答
i2c_sendbyte(unsigned char byt);//写字节,写入的第一个数据
i2c_waitack(void); //等待应答
i2c_sendbyte(unsigned char byt);//写字节,写入的第二个数据
i2c_waitack(void); //等待应答
……
i2c_sendbyte(unsigned char byt);//写字节,写入的最后一个数据
i2c_waitack(void); //等待应答
i2c_stop(); //停止
随机读时序对应函数:
i2c_start(); //启动
i2c_sendbyte(unsigned char byt);//写字节,参数器件写地址
i2c_waitack(void); //等待应答
i2c_sendbyte(unsigned char byt);//写字节,AT24C02空间地址
i2c_waitack(void); //等待应答
i2c_start(); //再次启动
i2c_sendbyte(unsigned char byt);//写字节,参数器件读地址
i2c_waitack(void); //等待应答
i2c_receivebyte(void); //I2C接收字节
i2c_sendack(unsigned char ackbit);//发送应答 应答非
i2c_stop(); //停止
二、程序设计
1、完善I2C总线模块程序
(1)新建i2C.C模块同名的头文件
在头文件中对C函数进行声明,程序如下:
#ifndef __I2C_H
#define __I2C_H
//函数声明
void i2c_delay(unsigned char i);//I2C总线中一些必要的延时函数
void i2c_start(void);//产生I2C总线启动条件
void i2c_stop(void);//产生I2C总线停止条件
void operate_delay(unsigned char t);//读写操作过程中一些必要的延时
void i2c_sendbyte(unsigned char byt);//I2C发送一个字节的数据
unsigned char i2c_waitack(void); //等待应答
unsigned char i2c_receivebyte(void); //I2C接收一个字节数据
void i2c_sendack(unsigned char ackbit);//发送应答
//新增24C02操作函数
//向24C02指定地址写入1个字节
void Write_24C02_1(unsigned char add,unsigned char val);
//向24C02指定地址写入2个字节
void Write_24C02_2(unsigned char add,unsigned char val1,unsigned char val2);
//从24C02指定地址读出1字节
unsigned char Read_24C02(unsigned char add);
#endif
(2)在i2C.C文件添加对AT24C02的读写函数
引用寄存器定义头文件,硬件P2.0、P2.1进行定义,本例新增加3个函数:
//向24C02指定地址写入1个字节
void Write_24C02_1(unsigned char add,unsigned char val);
//向24C02指定地址写入2个字节
void Write_24C02_2(unsigned char add,unsigned char val1,unsigned char val2);
//从24C02指定地址读出1字节
unsigned char Read_24C02(unsigned char add);
页写更多字节与写入2个字节类似,在竞赛这根据需要编写,多字节读可以多次随机读实现。
新增部分程序如下:
#include "stc15f2k60s2.h"
#include "intrins.h"
#include "i2c.h"
#define DELAY_TIME 5
/** 定义I2C总线时钟线和数据线 */
sbit scl = P2^0;
sbit sda = P2^1;
//向24C02指定地址写入1个字节
void Write_24C02_1(unsigned char add,unsigned char val)
{
i2c_start(); //启动
i2c_sendbyte(0xa0);//发送器件写地址
i2c_waitack(); //等待应答
i2c_sendbyte(add); //发送24C02空间写入地址
i2c_waitack(); //等待应答
i2c_sendbyte(val); //发送写入数据
i2c_waitack(); //等待应答
i2c_stop(); //停止
operate_delay(10); //延时,两次写必须
}
//向24C02指定地址写入2个字节
void Write_24C02_2(unsigned char add,unsigned char val1,unsigned char val2)
{
i2c_start(); //启动
i2c_sendbyte(0xa0); //发送器件写地址
i2c_waitack(); //等待应答
i2c_sendbyte(add); //发送24C02空间写入地址
i2c_waitack(); //等待应答
i2c_sendbyte(val1); //发送写入数据1
i2c_waitack(); //等待应答
i2c_sendbyte(val2); //发送写入数据2
i2c_waitack(); //等待应答
i2c_stop(); //停止
operate_delay(10); //延时,两次写必须
}
//从24C02指定地址读出1字节
unsigned char Read_24C02(unsigned char add)
{
unsigned char da;
i2c_start(); //启动
i2c_sendbyte(0xa0); //发送器件写地址
i2c_waitack(); //等待应答
i2c_sendbyte(add); //发送24C02空间写入地址
i2c_waitack(); //等待应答
i2c_start(); //再次启动
i2c_sendbyte(0xa1); //发送器件读地址
i2c_waitack(); //等待应答
da = i2c_receivebyte();//读出数据
i2c_sendack(1); //发送应答
i2c_stop(); //停止
return da; //返回数据
}
2、键盘函数功能修改
AT24C20读写验证直接通过键盘功能实现,将数码管显示的数据写入AT24C02内部,读出送另外的数码管显示。按键功能如下:
S7: 数码管Led1写入AT24C02内部00h。
S6: 数码管Led1写入AT24C02内部10h、11h。
S5: 读出AT24C02内部00h送数码管Led4显示。
S4: 读出AT24C02内部10h、11h送数码管Led7、Led8显示。
修改后的键盘功能程序:
S7:
Write_24C02_1(0x00,Led1); //调用单字节写函数 数码管1
// Led1++; //原功能
// if(Led1==10)Led1=0; //原功能
S6:
Write_24C02_2(0x10,Led1,Led2); //调用2字节写函数 数码管1、2
// Led1++; //原功能
// if(Led1==10)Led1=0; //原功能
S5:
Led4=Read_24C02(0x00); //调用单字节读函数 数码管4
// Led1++; //原功能
// if(Led1==10)Led1=0; //原功能
S4:
Led7=Read_24C02(0x10);//调用单字节读函数 数码管7
Led8=Read_24C02(0x11);//调用单字节读函数 数码管8
// Led1++; //原功能
// if(Led1==10)Led1=0; //原功能