哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处
http://blog.csdn.net/woshixingaaa/archive/2010/10/03/5919459.aspx
AT24C02是由ATMEL公司提供的,IIC总线串行EEPROM(electronic eraser programmer read only memory),其容量为2kbit(256B),工作电压在2.7v~5.5v之间,生产工艺是CMOS。
一般数字芯片都在左下角和右上角为GND,VCC。容量的计算方法:AT24Cxx :01~1024
容量 = xx * 1kbit。
写入过程:
AT24C系列EEPROM芯片的固定部分为1010,A2,A1,A0引脚接高低电平后得到确定的3位编码,形成7位编码即为该器件的地址码。
单片机进行写操作时,首先发送该器件的7位地址码和写方向位”0”(共8位,即一个字节),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为响应,单片机收到应答后就可以传送数据了。传送数据时,单片机首先发送一个字节的被写入存储器的首地址,收到存储器器件的应答后,单片机就逐个发送数据字节,但每发送一个字节后都要等待应答。AT24C系列片内地址在接收到每一个数据字节地址后自动加1,在芯片的“一次装载字节数”限度内,只需输入首地址。装载字节数超过芯片的“一次装载字节数”时,数据地址将“上卷”,前面的数据将被覆盖。
字节写:
页写:
读入过程:
单片机先发送该器件的7位地址码和写方向位“0”(“伪写”),发送完后释放SDA线并在SCL线上产生第9个时钟信号。被选中的存储器器件在确认是自己的地址后,在SDA线上产生一个应答信号作为回应。
然后,再发一个字节的要读出器件的存储区的首地址,收到应答后,单片机要重复一次起始信号并发出器件地址和读方向位(“1”),收到器件应答后就可以读出数据字节,每读出一个字节,单片机都要回复应答信号。当最后一个字节数据读完后,单片机应返回以“非应答”(高电平),并发出终止信号以结束读出操作。
当前地址读:
随机读:
有序读:
IIC总线模拟时序图:
IIC总线应答时序图:
设备地址:
写周期:
两次写之间要有一个10ms的twR间隔
写入EEPROM一个2,然后读出,在数码管上显示出来:
#include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit SCL = P3^6; sbit SDA = P3^7; void delay() { ;; } //5us void delay1(uchar x) { uchar a,b; for(a=x;a>0;a--) for(b=100;b>0;b--); } void Init(){ SCL = 1; SDA = 1; } void start(){ SDA = 1; delay(); SCL = 1; delay(); SDA = 0; delay(); } void stop(){ SDA = 0; delay(); SCL = 1; delay(); SDA = 1; delay(); } void write(uchar date) { uchar i,temp; temp=date; for(i=0;i<8;i++) { temp=temp<<1; SCL=0; delay(); SDA=CY; delay(); SCL=1; delay(); } SCL=0; delay(); SDA=1; delay(); } uchar read() { uchar i,k; SCL=0; delay(); SDA=1; delay(); for(i=0;i<8;i++) { SCL=1; delay(); k=(k<<1)|SDA; // 将SDA赋给K的每一位 SCL=0; delay(); } return k; } void response(){ int i; SCL = 1; //在SCL为高电平期间,进行应答 delay(); while((SDA == 1) && (i < 170))i++; //SCL释放总线,等待从设备应答,从设备会把SDA拉低 SCL = 0; delay(); } void At24c_Write(uchar address, uchar value){ start(); write(0xa0); //写入设备地址 response(); write(address); //写入首地址 response(); write(value); //写入数据 response(); stop(); } uchar At24c_Read(uchar address){ uchar value; start(); write(0xa0); //伪写,先写入设备地址 response(); write(address); //再写入要读取数据的首地址 response(); start(); //再次 write(0xa1); //写入要读取数据的地址,方向为1 response(); value = read(); //读取数据 stop(); return value; } void main(){ P1 = 0x0; // 位选,使最地位数码管被选中 Init(); At24c_Write(23,0x5b); // 在EEPROM的23这个地址上写数据0x5b delay1(100); // 在写和读之间要多延时一会儿,否则器件处理不完 P2 = At24c_Read(23); // 读取23地址的数据,也就是刚才写入的数据 while(1); }
#include <reg52.h> #define uchar unsigned char #define uint unsigned int sbit SCL = P3^6; sbit SDA = P3^7; uchar temp, sum; uint flag; unsigned char code duan[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F, 0x77,0x7C,0x39,0x5E,0x79,0x71}; void delay() { ;; } //5us void delay1(uchar x) { uchar a,b; for(a=x;a>0;a--) for(b=100;b>0;b--); } void Init(){ SCL = 1; SDA = 1; } void start(){ SDA = 1; delay(); SCL = 1; delay(); SDA = 0; delay(); } void stop(){ SDA = 0; delay(); SCL = 1; delay(); SDA = 1; delay(); } void write(uchar date) { uchar i,temp; temp=date; for(i=0;i<8;i++) { temp=temp<<1; SCL=0; delay(); SDA=CY; delay(); SCL=1; delay(); } SCL=0; delay(); SDA=1; delay(); } uchar read() { uchar i,k; SCL=0; delay(); SDA=1; delay(); for(i=0;i<8;i++) { SCL=1; delay(); k=(k<<1)|SDA; // 将SDA赋给K的每一位 SCL=0; delay(); } return k; } void response(){ int i; SCL = 1; //在SCL为高电平期间,进行应答 delay(); while((SDA == 1) && (i < 170))i++; //SCL释放总线,等待从设备应答,从设备会把SDA拉低 SCL = 0; delay(); } void At24c_Write(uchar address, uchar value){ start(); write(0xa0); //写入设备地址 response(); write(address); //写入首地址 response(); write(value); //写入数据 response(); stop(); } uchar At24c_Read(uchar address){ uchar value; start(); write(0xa0); //伪写,先写入设备地址 response(); write(address); //再写入要读取数据的首地址 response(); start(); //再次 write(0xa1); //写入要读取数据的地址,方向为1 response(); value = read(); //读取数据 stop(); return value; } void main(){ uint i; flag = 1; P1 = 0x0; // 位选,使最地位数码管被选中 EA = 1; ET0 = 1; sum = 0; temp = 0; TMOD = 0x01; TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; TR0 = 1; Init(); P2 = At24c_Read(23); for(i = 0; i < 10; i++) if(duan[i] == P2){ sum = i; break; flag = 0; } while(1){ if(temp == 20){ temp = 0; if(sum == 10){ sum = 0; } if(flag == 1){ At24c_Write(23,duan[sum]); delay1(100); P2 = duan[sum]; } sum++; } } } void time0() interrupt 1{ TH0 = (65536 - 50000) / 256; TL0 = (65536 - 50000) % 256; temp++; }