51读写串行EEPROM芯片at2402程序
51读写串行EEPROM芯片at2402程序(C)
/* Name:AT24C02存储器的读写程序,用到I2C总线,含相对独立的I2C总线读写函数 */
#include
#include
#include
#define DELAY_TIME 60 /*经实验,不要小于50~否则可能造成时序混乱*/
#define TRUE 1
#define FALSE 0
sbit SCL=P1^7;/*假设由P1.7和P1.6控制*/
sbit SDA=P1^6;
/********** Function Definition 函数定义 ************/
void DELAY(unsigned int t) /*延时函数*/
{
while(t!=0)
t--;
}
void I2C_Start(void)
{
/*启动I2C总线的函数,当SCL为高电平时使SDA产生一个负跳变*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SDA=0;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void I2C_Stop(void)
{
/*终止I2C总线,当SCL为高电平时使SDA产生一个正跳变*/
SDA=0;
SCL=1;
DELAY(DELAY_TIME);
SDA=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void SEND_0(void) /* SEND ACK */
{
/*发送0,在SCL为高电平时使SDA信号为低*/
SDA=0;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
void SEND_1(void)
{
/*发送1,在SCL为高电平时使SDA信号为高*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME);
SCL=0;
DELAY(DELAY_TIME);
}
bit Check_Acknowledge(void)
{
/*发送完一个字节后检验设备的应答信号*/
SDA=1;
SCL=1;
DELAY(DELAY_TIME/2);
F0=SDA;
DELAY(DELAY_TIME/2);
SCL=0;
DELAY(DELAY_TIME);
if(F0==1)
return FALSE;
return TRUE;
}
void WriteI2CByte(char b)reentrant
{
/*向I2C总线写一个字节*/
char i;
for(i=0;i<8;i++)
if((b< SEND_1();
else
SEND_0();
}
char ReadI2CByte(void)reentrant
{
/*从I2C总线读一个字节*/
char b=0,i;
for(i=0;i<8;i++)
{
SDA=1; /*释放总线*/
SCL=1; /*接受数据*/
DELAY(10);
F0=SDA;
DELAY(10);
SCL=0;
if(F0==1)
{
b=b<<1;
b=b|0x01;
}
else
b=b<<1;
}
return b;
}
/**********以下为读写24c02的函数**********/
void Write_One_Byte(char addr,char thedata) {
bit acktemp=1;
/*write a byte to mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
WriteI2CByte(thedata);/*thedata*/
acktemp=Check_Acknowledge();
I2C_Stop();
}
void Write_A_Page(char *buffer,char addr) {
bit acktemp=1;
bit wrtmp;
int i;
/*write a page to at24c02*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
for(i=0;i<7;i++)
{
WriteI2CByte(buffer[i]);
if(!Check_Acknowledge())
{
I2C_Stop();
}
}
I2C_Stop();
}
char Read_One_Byte(char addr)
{ bit acktemp=1;
char mydata;
/*read a byte from mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
mydata=ReadI2CByte();
acktemp=Check_Acknowledge();
return mydata;
I2C_Stop();
}
void Read_N_Bytes(char *buffer,char n,char addr)
{
bit acktemp=1;
int i=0;
/*read 8 bytes from mem*/
I2C_Start();
WriteI2CByte(0xa0);
acktemp=Check_Acknowledge();
WriteI2CByte(addr);/*address*/
acktemp=Check_Acknowledge();
I2C_Start();
WriteI2CByte(0xa1);
acktemp=Check_Acknowledge();
for(i=0;i {
buffer[i]=ReadI2CByte();
if(i!=n-1)
SEND_0(); /*发送应答*/
else
SEND_1(); /*发送非应答*/
}
I2C_Stop();
}
void main()
{
int i;
char mybyte;
char myarray[8];
char myarray2[8];
char rdarray[16];
for(i=0;i<8;i++)
{
myarray[i]=i;
myarray2[i]=i+0x08;
}
Write_One_Byte(0x20,0x28);
Write_A_Page(myarray,0x10);
Write_A_Page(myarray2,0x18);
mybyte=Read_One_Byte(0x20);
Read_N_Bytes(rdarray,16,0x10);
}
参考链接:
51读写串行EEPROM芯片at2402程序(汇编)
SDA BIT P3.7 ;定义24C02数据线
SCL BIT P3.6 ;定义24C02时钟线
TEMP EQU 30H
DISSTART EQU 40H ;显示单元首地址
LED_DATA EQU P0 ;数码管数据口定义
;-----------------------------------------------------
ORG 0000H
AJMP MAIN
ORG 0030H
;-----------------------------------------------------
MAIN:
MOV SP,#60H
MOV P0,#0FFH
MOV P2,#0FFH
MOV TEMP,#00H
ACALL READ_DATA
CALL CONVT
CALL PLAY
MOV A,TEMP
INC A
ACALL WRITE_DATA M_LOOP:
MOV A,TEMP
CALL CONVT
CALL PLAY
JMP M_LOOP
;-----------------------------------------------------
;写1字节数据子程序
;-----------------------------------------------------
WRITE_DATA:
MOV R0,#00h ;数据写入首地址
MOV B,A
LCALL WRITE_BYTE ;将计数值写入24C02
RET
;-----------------------------------------------------
;读1字节数据子程序
;-----------------------------------------------------
READ_DATA:
MOV R0,#00H ;读取的首地址
LCALL READ_BYTE ;读EEPROM
CALL STOP
MOV TEMP,A
RET
;---------------------------------------------------------
;代码变换 (HEX TO BCD)
;---------------------------------------------------------
CONVT:
MOV A,TEMP
MOV B,#100
DIV AB
MOV DISSTART+2,A ;百位存放在DISSTART,2
MOV A,#10
XCH A,B
DIV AB
MOV DISSTART+1,A ;十位存放在DISSTART,1
MOV DISSTART,B ;个位存放在DISSTART
MOV A,DISSTART+2
JNZ CONVT_END
MOV DISSTART+2,#0AH ;百位为0,关闭百位显示
MOV A,DISSTART+1
JNZ CONVT_END
MOV DISSTART+1,#0AH CONVT_END:
RET
;----------------------------------------------------
;写操作子程序
;输入参数: R0---要写入的地址,B---要写入的数据 ;----------------------------------------------------
WRITE_BYTE:
CALL START
MOV A,#0A0H
CALL SENDBYTE
CALL WAITACK
MOV A,R0
CALL SENDBYTE
CALL WAITACK
MOV A,B
CALL SENDBYTE
CALL WAITACK
CALL STOP
RET
;----------------------------------------------------
;读操作子程序
;输入参数:R0---要读的字节地址,
;输出参数: A---结果
;----------------------------------------------------
READ_BYTE:
CALL START
MOV A,#0A0H
CALL SENDBYTE
CALL WAITACK
MOV A,R0
CALL SENDBYTE
CALL WAITACK
CALL START
MOV A,#0A1H
CALL SENDBYTE
CALL WAITACK
CALL RCVBYTE
RET
;-----------------------------------------------------
;从IIC总线上接收一个字节数据
;出口参数:A---接收数据存放在A中
;-----------------------------------------------------
RCVBYTE:
MOV R7,#08 ;一个字节共接收8位数据
CLR A
SETB SDA ;释放SDA数据线 R_BYTE:
CLR SCL
NOP
NOP
NOP
NOP
SETB SCL ;启动一个时钟周期,读总线
NOP
NOP
NOP
NOP
MOV C,SDA ;将SDA状态读入C
RLC A ;结果移入,
SETB SDA ;释放SDA数据线
DJNZ R7,R_BYTE ;判断8位数据是否接收完全,
RET
;----------------------------------------------------
;向IIC总线发送一个字节数据
;入口参数:A---待发送数据存放在A中 ;----------------------------------------------------
SENDBYTE:
MOV R7,#08 S_BYTE:
RLC A
MOV SDA,C
SETB SCL
NOP
NOP
NOP
NOP
CLR SCL
DJNZ R7,S_BYTE ;8位发送完毕?
RET
;-----------------------------------------------------
;等待应答信号
;等待从机返回一个响应信号
;-----------------------------------------------------
WAITACK:
CLR SCL
SETB SDA ;释放SDA信号线
NOP
NOP
SETB SCL
NOP
NOP
NOP
MOV C,SDA
JC WAITACK ;SDA为低电平,返回了响应信号
CLR SDA
CLR SCL
RET
;----------------------------------------------------
;启动信号子程序
;----------------------------------------------------
START:
SETB SDA
SETB SCL
NOP
CLR SDA
NOP
NOP
NOP
NOP
CLR SCL
RET
;----------------------------------------------------
;停止信号子程序
;----------------------------------------------------
STOP:
CLR SDA
NOP
SETB SCL
NOP
NOP
NOP
NOP
SETB SDA
NOP
NOP
CLR SCL
CLR SDA
RET
;---------------------------------------------------------
PLAY:
MOV R0,#DISSTART ;获得显示单元首地址
MOV R1,#07FH ;从第一个数码管开始
MOV R2,#03H ;共显示3位数码管
DISP1:
MOV A,@R0 ;获得当前位地址
MOV DPTR,#TAB_NU ;获得表头
MOVC A,@A+DPTR ;查表获得显示数据
MOV LED_DATA,A ;显示数据
MOV P2,R1 ;开始显示当前位
MOV A,R1 ;准备显示下一位
RR A
MOV R1,A ;下一位
INC R0 ;取下一个单元地址
LCALL DELAY2MS ;延时 2 MS
DJNZ R2,DISP1 ;重复显示下一个
MOV P2,#0FFH ;关闭显示
RET ;显示完成,返回 ;---------------------------------------------------------
;延时子程序
;---------------------------------------------------------
DELAY2MS:
MOV R6,#10 DEL1:
MOV R7,#100
DJNZ R7,$
DJNZ R6,DEL1
RET
TAB_NU:
DB 21H,77H,0A2H,62H,74H,68H,28H 73H,20H,60H,0FFH
本文档为【51读写串行EEPROM芯片at2402程序】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。