1、AT24CXX存储器工作原理
1.1、特点:
- 与400KHz,I2C总线兼容
- 1.8到6.0伏工作电压范围
- 低功耗CMOS技术
- 写保护功能当WP为高电平时进入写保护状态
- 页写缓冲器
- 自定时擦写周期
- 100万次编程/擦除周期
- 可保存数据100年
- 8脚DIP SOIC或TSSOP封装
- 温度范围商业级和工业级
1.2、概述
CAT24WC01/02/04/08/16是一个1K/2K/4K/8K/16K位串行CMOS,EEPROM内部含有128/256/512/1024/2048个8位字节CATALYST公司的先进CMOS技术实质上减少了器件的功耗,CAT24WC01有一个8字节页写缓冲器CAT24WC02/04/08/16有一个16字节页写缓冲器,该器件通过I2C总线接口进行操作有一个专门的写保护功能。
总线时序
1.3、驱动程序编写
//<main.c>
#include "reg52.h"
#include "i2c.h"
typedef unsigned int u16;
typedef unsigned char u8;
//使用单片机上四个独立按键
sbit k1=P3^1; //保存显示的数据
sbit k2=P3^0; //读取上次保存的数据
sbit k3=P3^2; //对显示的数据进行累加
sbit k4=P3^1; //清零
// 38译码器
sbit LBA=P2^2;
sbit LBB=P2^3;
sbit LBC=P2^4;
u8 num=0,
disp[4]; //4位数码管显示
// 发生字码:code关键词,保持变量到flash里面,如果没有code保持在data里面
u8 code smgduan[16] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void delay(u16 i)
{
while(i--)
}
void Keypros()
{
if(k1=0)
{
delay(1000); //按键消抖
if(k1==0)
{
At24c02Write(1,num);
}
while(!k1); //判断按键是否松开
}
if(k2=0)
{
delay(1000); //按键消抖
if(k2==0)
{
num = At24c02read(1);
}
while(!k2); //判断按键是否松开
}
if(k3=0)
{
delay(1000); //按键消抖
if(k3==0)
{
num++;
if(num>255) num=0;
}
while(!k3); //判断按键是否松开
}
if(k4=0)
{
delay(1000); //按键消抖
if(k4==0)
{
num=0;
}
while(!k4); //判断按键是否松开
}
}
void datapros()
{
disp[0]=smgduan[num/1000]; //因为数码管四位,所以最高显示9999
disp[1]=smgduan[num%1000/100]; //取百位
disp[2]=smgduan[num%1000%100/10];
disp[3]=smgduan[num%1000%100%10];
}
void Digplsplay()
{
u8 i;
for(i=0;i<4;i++){
switch(i)
{
case 0:
LSA = 0;LSB = 0;LSC = 0;break;
case 1:
LSA = 1;LSB = 0;LSC = 0;break;
case 2:
LSA = 0;LSB = 1;LSC = 0;break;
case 3:
LSA = 0;LSB = 0;LSC = 1;break;
}
P0=disp[3-i];
delay(100);
p0=0x00;
}
}
void main()
{
while(1){
Keypros();
datapros();
Digplsplay();
}
}
//<i2c.h>
#ifndef _I2C_H
#define _I2C_H
#include <reg52.h>
sbit SCL=p2^1;
sbit SDA=P2^0;
void At24c02Write(unsigned char addr,unsigned char dat);
unsigned char At24c02Read(unsigned char addr);
#endif
//<i2c.c>文件
#include "i2c.h"
/**
编写单片机时序,单片机小精灵工具生成
12MHZ晶振,延迟10us
*/
void Delay10us(void)
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--)
}
//起始信号S
void I2cStart()
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();
SDA=0;
Delay10us();
SCL=0;
Delay10us();
}
//终止信号
void I2cStop()
{
SDA=0;
Delay10us();
SCL=1;
Delay10us();
SDA=1;
Delay10us();
}
//发送字节,一个个发送,先发送高位后发送地位,应答 “0”
unsigned char I2cSendByte(unsigned char dat)
{
unsigned char a=0,b;
for(a=0;a<8;a++){
SDA=dat>>7; //传送最高位
dat=dat<<1; //右移一位,次高位变成最高位
Delay10us(); //延迟10us
//SCL为低电平可以变化,为高电平保持稳定
SCL=1; //移位的数据就会保持稳定
Delay10us();
SCL=0; //数据可以改变
Delay10us();
}
//将数据线和时钟线释放出来
SDA=1;
Delay10us();
SCL=1;
while(SDA) //如果从机对主机发送的字节产生应答SDA会变成 0
{
//发送失败SDA始终为高电平
b++ //设置个等待时间
if(b>200){ //至少200us,1条指令1us
SCL=0;
Delay10us();
return 0;
}
}
//产生应答 SCL=0拉低
SCL=0;
Delay10us();
return 1;
}
/**
接收数据
*/
unsigned char I2cReadByte()
{
unsigned char a=0,dat=0;
SDA=1; //拉高SDA使处于空闲状态
Delay10us();
for(a=0;a<0;a++)
{
SCL=1;
Delay10us();
dat<<=1; // dat=0 00 01 10
dat|=SDA; // 01 11 把SDA的值给dat
Delay10us();
SCL=0;
Delay10us();
}
return dat;
}
/**针对AT24C02的读写函数
S-器件地址+0 A 写入首地址 A Data1 A ..... Data0 A P
*/
void At24c02Write(unsigned char addr,unsigned char dat)
{
I2cStart(); //起始信号
I2cSendByte(0xa0); //器件地址
I2cSendByte(addr); // 首地址
I2cSendByte(dat); // 发送数据
I2cStop(); //停止
}
unsigned char At24c02Read(unsigned char addr)
{
unsigned char num;
I2cStart(); //起始信号
I2cSendByte(0xa0); //器件地址
I2cSendByte(addr); // 首地址
//在传送过程中,当需要改变传送方向时,起始信号和从机地址都被重复产生一次,但两次读/写方向位正好反相
I2cStart(); //起始信号
I2cSendByte(0xa1); //器件地址
num=I2cReadByte();
I2cStop();
return num;
}