(求助)用51读写AT24C256问题
1.我是新手,在网上找的个51读写AT24C256程序,现在用AT89C51或STC12C5A60S2,晶振:22.1184MHz。现将程序贴如下:#include <reg51.h>
#include <INTRINS.H>
//#include <STC15F104E.h>
#defineERROR 10
sbit SDA=P2^1;
sbit SCL=P2^0;
enumeepromtype{AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};
enumeepromtype enumer;
//DataBuff为读写数据输入/输出缓冲地址
//ByteQuantity 为要读写数据的字节数量
//Address 为EEPROM片内地址
//ControlByte为EEPROM的控制字节,具体形式为(1)(0)(1)(0)(A2)(A1)(A0)(R/W)其中R/W=1,
//为读操作,R/W=0,为写操作,A2,A1,A0为EEPROM的页选或片选地址·;
//enume为枚举变量,需为AT2401至T24256中的一种,分别对应24C01ÖÁ24C256;
//ERROR为允许最大次数,若出现ERROR次操作失效后,则函数终止操作。
//SDA和SCL由用户自定义,这里P2^1和P2^0;
//其余的用户不用管,只要把子程序放在自己的程序中并调用就可以了;
/***********************************************************************************/
void RW24xx(unsigned char *DataBuff,unsigned char ByteQuantity,unsigned int Address,
unsigned char ControlByte,enum eepromtype enumer)
{
void Delay(unsigned char DelayCount);
void IICStart(void);
void IICStop(void);
bitIICRecAck(void);
void IICNoAck(void);
void IICAck(void);
unsigned char IICReceiveByte(void);
void IICSendByte(unsigned char sendbyte);
unsigned char data j,i;
idata unsigned char m_page,m_cell_first,m_cell_last;
bit errorflag=1;
if((64-Address%64)<ByteQuantity)
{
m_cell_first=64-Address%64;
}
else
{
m_cell_first=ByteQuantity;
}
m_page=(ByteQuantity-(64-Address%64))/64;
m_cell_last=(ByteQuantity-(64-Address%64))%64;
i=ERROR;
while(i--)
{
IICStart();
IICSendByte(ControlByte&0xfe);
if(IICRecAck())
continue;
if(enumer>AT2416)
{
IICSendByte((unsigned char)(Address>>8));
if(IICRecAck())
continue;
}
IICSendByte((unsigned char)Address);
if(IICRecAck())
continue;
if(!(ControlByte&0x01))
{
j=m_cell_first;
errorflag=0; //********clr errorflag
while(j--)
{
IICSendByte(*DataBuff++);
if(!IICRecAck())
continue;
errorflag=1; //发送成功不会经过此处
break;
}
}
else
{
IICStart();
IICSendByte(ControlByte);
if(IICRecAck())
continue;
while(--m_cell_first)
{
*DataBuff++=IICReceiveByte();
IICAck();
}
*DataBuff++=IICReceiveByte(); //read last byte data
IICNoAck();
errorflag=0;
break;
}
}
IICStop();
if(!(ControlByte&0x01))
{
Delay(255);
Delay(255);
Delay(255);
Delay(255);
}
Address+=(64-Address%64);
while(m_page--)
{
i=ERROR;
while(i--)
{
IICStart();
IICSendByte(ControlByte&0xfe);
if(IICRecAck())
continue;
if(enumer>AT2416)
{
IICSendByte((unsigned char)(Address>>8));
if(IICRecAck())
continue;
}
IICSendByte((unsigned char)Address);
if(IICRecAck())
continue;
if(!(ControlByte&0x01))
{
j=64;
errorflag=0; //********clr errorflag
while(j--)
{
IICSendByte(*DataBuff++);
if(!IICRecAck())
continue;
errorflag=1; //发送成功不会经过此处
break;
}
if(errorflag==1)
continue;
break;
}
else
{
IICStart();
IICSendByte(ControlByte);
if(IICRecAck())
continue;
j=64;
while(--j)
{
*DataBuff++=IICReceiveByte();
IICAck();
}
*DataBuff++=IICReceiveByte(); //read last byte data
IICNoAck();
errorflag=0;
break;
}
}
IICStop();
if(!(ControlByte&0x01))
{
Delay(255);
Delay(255);
Delay(255);
Delay(255);
}
Address+=64;
}
i=ERROR;
while(i--)
{
IICStart();
IICSendByte(ControlByte&0xfe);
if(IICRecAck())
continue;
if(enumer>AT2416)
{
IICSendByte((unsigned char)(Address>>8));
if(IICRecAck())
continue;
}
IICSendByte((unsigned char)Address);
if(IICRecAck())
continue;
if(!(ControlByte&0x01))
{
j=m_cell_last;
errorflag=0; //********clr errorflag
while(j--)
{
IICSendByte(*DataBuff++);
if(!IICRecAck())
continue;
errorflag=1; //发送成功不会经过此处
break;
}
if(errorflag==1)
continue;
break;
}
else
{
IICStart();
IICSendByte(ControlByte);
if(IICRecAck())
continue;
while(--m_cell_last)
{
*DataBuff++=IICReceiveByte();
IICAck();
}
*DataBuff=IICReceiveByte(); //read last byte data
IICNoAck();
errorflag=0;
break;
}
}
IICStop();
if(!(ControlByte&0x01))
{
Delay(255);
Delay(255);
Delay(255);
Delay(255);
}
}
void delay10us(void) //误差-0.053530092593us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=52;a>0;a--);
}
void delay4us(void) //误差-0.042824074074us
{
unsigned char a,b;
for(b=17;b>0;b--)
for(a=1;a>0;a--);
}
/****************以下对IIC总线操作子程序***/
/*****************启动总线**********************/
void IICStart(void)
{ SCL=0; /* SCL处于高电平时,SDA从高电平转向低电平*/
SDA=1; /* 一个“开始”状态,该状态必须在其他命令之前执行 */
SCL=1;
delay10us();
delay10us();
SDA=0;
delay10us();
delay10us();
SCL=0;
SDA=1;
}
/*****************停止总线****************/
void IICStop(void)
{ SCL=0; /* SCL处于高电平时,SDA从高电平转向低电平*/
SDA=0; /*一个“停止”状态,该状态终止所有通讯 */
SCL=1;
delay10us();
delay10us();
SDA=1;
delay10us();
delay10us();
SCL=0;
}
/**************检查应答位*******************/
bit IICRecAck(void)
{ SCL=0;
SDA=1;
SCL=1;
delay10us();
delay10us();
CY=SDA; /* 因返回值总是放在CY中 */
SCL=0;
return(CY);
}
/***************对IIC总线产生应答*******************/
void IICACK(void)
{ SDA=0; /* EEPROM通过在收到每个地址或数据之后 */
SCL=1; /*置SDA低电平的方式确认表示收到读SDA状态 */
delay10us();
delay10us();
SCL=0;
delay4us();
delay10us();
SDA=1;
}
/*****************不对IIC总线产生应答***************/
void IICNoAck(void)
{ SDA=1;
SCL=1;
delay10us();
delay10us();
SCL=0;
}
/*******************向IIC总线写数据*********************/
void IICSendByte(unsigned char sendbyte)
{ unsigned char data j=8;
for(;j>0;j--)
{ SCL=0;
sendbyte <<= 1; /* 使CY=sendbyte^7; */
SDA=CY; /* CY 进位标志位 */
SCL=1;
}
SCL=0;
}
/**********************´从IIC总线上读数据子程序**********/
unsigned char IICReceiveByte(void)
{ register receivebyte,i=8;
SCL=0;
while(i--)
{ SCL=1;
receivebyte = (receivebyte <<1 ) | SDA;
SCL=0;
}
return(receivebyte);
}
/***************延迟程序************************/
void Delay(unsigned char DelayCount)
{
while(DelayCount--);
}
void main()
{
unsigned int addr;
unsigned char code buf2;
unsigned char code buf1={
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,27,28,29,30,
31,32,33,34,35,36,37,38,39,40,41,42,43,44,
45,46,47,48,49,50,51,52,53,54,55,56,57,58,
59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80,81,82,83,84,85,86,
87,88,89,90,91,92,93,94,95,96,97,98,99
};
unsigned char *p1,*p2;
p1=buf1;
p2=buf2;
addr=0;
RW24xx(p1,100,addr,0xa0,AT24256);
delay10us();
delay10us();
addr=0;
RW24xx(p1,100,addr,0xa1,AT24256);
delay10us();
delay10us();
delay10us();
delay10us();
p1=buf2;
P3=buf2;
while(1);
}
2.现在问题是:
1)编译出现3警告:main2.c(346): warning C182: pointer to different objects 指向p1=buf1;p2=buf2;
2)原本是想将buf1中的数据写进AT24C256,因数据会在13K左右,(现在定义是buf1,想先看看),然后读出AT24C256中
的数据以便应用。(现暂时想读入buf2中看看),然后读buf2中第5个数据给P3口驱动LED(低电平驱动)显示。
3)运行后,现在P3口全是低,软件仿真看到buf2里全是0x00,没有读出到数据,不知问题在那里?
3.请各位高手,帮新手看看问题所在,万分感激!! buf1和buf2为数组,你这样给数据他给的是数组的地址,并不是数组中的数据。 就是在这里纠结起的,我也觉得不妥;但要怎样处理呢?谢了! C语言基础还没学好,找到个例程。
void main(void)
{
//定义花样数据,数据存放在片内 CODE 区中
unsigned char code design[]={0xFF,0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F,
0x7F,0xBF,0xDF,0xEF,0xF7,0xFB,0xFD,0xFE,0xFF,
0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80,0x0,
0xE7,0xDB,0xBD,0x7E,0xFF};
unsigned int a; //定义循环用的变量
unsigned char b;
unsigned char code * dsi; //定义基于 CODE 区的指针
do{
dsi = &design; //取得数组第一个单元的地址
for (b=0; b<32; b++)
{
}
}while(1);
}
for(a=0; a<30000; a++); //延时一段时间
P1 = *dsi; //从指针指向的地址取数据到 P1 口
dsi++; //指针加一, 它的可用程序20年前就有了。我是不想去找移动硬盘了。还有512的程庁,全却是页写入,自动连接上次尾部。 20年后也有新手呢,高手将代码共享下? 1. 复习 下C语言的const ,编译器的 code,xdata,idata 等用法.
2.24cxx 读写有问题主要还在时序,学会看时序图,学习根据mcu时钟和周期计算延时,复习i2c相关知识。 经过一段时间,现在可以连续读写了,但还不能页读写,将改动后的程序贴出,以便大家交流。
#include <reg52.h>
#include <INTRINS.H>
sbit SDA=P2^1;
sbit SCL=P2^0;
//enumeepromtype{AT2401,AT2402,AT2404,AT2408,AT2416,AT2432,AT2464,AT24128,AT24256};
//enumeepromtype enumer;
unsigned charACK_Error,Txmt_Success;
unsigned charbuf2;
unsigned charbuf1={
0xAA,0x49,0x46,0x46,0x98,0x33,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6D,0x74,0x20,
0x12,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x40,0x1F,0x00,0x00,0x40,0x1F,0x00,0xAB,
/*0x01,0x00,0x08,0x00,0x00,0x00,0x64,0x61,0x74,0x61,0x71,0x33,0x00,0x00,0x7F,0x7F,
0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x80,0x7F,0x80,0x80,0x80,0x80,0x80,0x80,
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,*/
};
void delay10us(unsigned char i)
{
unsigned char j;
do{
j = 40;
do{
_nop_();
}while(--j);
}while(--i);
}
/***************????????************************/
void Delay(unsigned char DelayCount)
{
while(DelayCount--);
}
/*****************ÒÔÏÂÊǶÔIIC×ÜÏߵIJÙ×÷×Ó³ÌÐò***/
/*****************Æô¶¯×ÜÏß**********************/
void IICStart(void)
{
SDA=1; /* Ò»¸ö"¿ªÊ¼"״̬,¸Ã״̬±ØÐëÔÚÆäËûÃüÁî֮ǰִÐÐ*/
SCL=1; /* SCL´¦Óڸߵçƽʱ,SDA´Ó¸ßµçƽתÏòµÍµçƽ±íʾ*/
delay10us(1);
SDA=0; //scl need to hold on low
delay10us(1);
SCL=0;
}
/*****************Í£Ö¹IIC×ÜÏß****************/
void IICStop(void)
{
SDA=0; /*±íʾһ¸ö"Í£Ö¹"״̬,¸Ã״̬ÖÕÖ¹ËùÓÐͨѶ */
SCL=1;
delay10us(2);
SDA=1;
delay10us(1);
}
/**************(Ö÷»ú)¼ì²éÓ¦´ðλ*******************/
bit IICRecAck(void)
{
unsigned char value;
SCL=1;
delay10us(1);
if(SDA==1)
value=1;
else
value=0;
SCL=0;
delay10us(1);
return value;
}
/***************£¨Ö÷»ú£©¶ÔIIC×ÜÏß²úÉúÓ¦´ð*******************/
void IICACK(void)
{
SCL=0; /* EEPROMͨ¹ýÔÚÊÕµ½Ã¿¸öµØÖ·»òÊý¾ÝÖ®ºó*/
delay10us(2);
SDA=1; /* ÖÃSDAµÍµçƽµÄ·½Ê½È·ÈϱíʾÊÕµ½¶ÁSDA¿Ú״̬ */
delay10us(1);
SCL=1;
delay10us(2);
delay10us(2);
SCL=0;
delay10us(2);
}
/*****************²»¶ÔIIC×ÜÏß²úÉúÓ¦´ð**************/
void IICNoAck(void)
{
SDA=1;
SCL=1;
delay10us(2);
SCL=0;
delay10us(1);
}
/*******************×Ö½ÚдÈë*********************/
void IICSendByte(unsigned char sendbyte)
{
unsigned char j;
for(j=0;j<8;j++)
{
if(sendbyte&0x80)
SDA=1;
else
SDA=0;
sendbyte=sendbyte<<1; //ÒƳöÊý¾ÝµÄ×î¸ßλ
SCL=1;
delay10us(1);
SCL=0;
delay10us(1);
}
}
/********************************×Ö½Ú¶Á³ö**************************************/
unsigned char IICReceiveByte()
{
unsigned char i=8;
unsigned char ddata=0;
SDA=1;
delay10us(1);
SCL=0;
while(i--)
{
ddata=ddata<<1;
SCL=1;
delay10us(1);
if(SDA==1)//if SDA=1
{
ddata |= 0x01;
}
SCL=0;
delay10us(1);
}
return ddata;
}
/*******************µ¥¸öÊý¾ÝдÈë*********************/
/****************************µØַΪ0x0000-0x1fff*******************************/
voidIICWriteData(unsigned int Address,unsigned char Data)
{
unsigned char addr_MSB,addr_LSB;
addr_MSB=Address>>8;
addr_LSB=Address & 0x00ff;
IICStart();
IICSendByte(0xa0);
IICRecAck();
IICSendByte(addr_MSB);
IICRecAck();
IICSendByte(addr_LSB);
IICRecAck();
IICSendByte(Data);
IICRecAck();
IICStop();
}
/*******************************¶à×Ö½ÚдÈë***************************/
/****************************µØַΪ0x0000-0x1fff*******************************/
/**************************µØÖ·£¬³¤¶È(<255),дÈëÊý¾ÝÄÚÈÝ**********************
voidFRAM_Multi_Data_Write(unsigned int Address,unsigned char Length,unsigned char *ptr)
{
unsigned char addr_MSB;
unsigned char addr_LSB;
unsigned char i;
//CLI();
Length=Length-1;
addr_MSB=Address>>8;
addr_LSB=Address & 0x00ff;
IICStart();
IICSendByte(0xa0);
IICRecAck();
IICSendByte(addr_MSB);
IICRecAck();
IICSendByte(addr_LSB);
IICRecAck();
for(i=0;i<Length;i++)
{
IICSendByte(*ptr);
IICRecAck();
ptr++;
}
IICSendByte(*ptr);
IICRecAck();
IICStop();
//SEI();
} */
/****************************µ¥¸ö×Ö½ÚÊý¾Ý¶ÁÈ¡****************************/
unsigned char IICReadData(unsigned int Address)
{
unsigned char addr_MSB;
unsigned char addr_LSB;
unsigned char ch;
//CLI();
addr_MSB=Address>>8;
addr_LSB=Address&0x00ff;
IICStart();
IICSendByte(0xa0);
IICRecAck();
IICSendByte(addr_MSB);
IICRecAck();
IICSendByte(addr_LSB);
IICRecAck();
IICStart();
IICSendByte(0xa1);
IICRecAck();
ch=IICReceiveByte();
//IICACK();
IICNoAck();
IICStop();
return ch;
}
void IICWritePageData(unsigned int Address,unsigned int Length,unsigned char *p1)
{
unsigned char i;
unsigned char addr_MSB;
unsigned char addr_LSB;
Length=Length-1;
addr_MSB=Address>>8;
addr_LSB=Address&0x00ff;
delay10us(1);
IICStart();
IICSendByte(0xa0);
IICRecAck();
delay10us(1);
IICSendByte(addr_MSB);
IICRecAck();
IICSendByte(addr_LSB);
IICRecAck();
for(i=0;i<Length;i++)
{
IICSendByte(*p1);
IICRecAck();
p1++;
}
IICSendByte(*p1);
IICRecAck();
IICStop();
}
/****************************Á¬ÐøÊý¾Ý¶Á³ö********************************/
/******************Èç¹û¶ÁÈ¡Ò»¸ö,Length¾ÍΪ1***********************************/
/***********************µØÖ·£¬¶ÁÈ¡×Ö½ÚÊý(<255),¶ÁÈ¡µÄÄÚÈÝ*********************/
void IICReadPageData(unsigned int Address,unsigned int Length,unsigned char *p)
{
unsigned char addr_MSB;
unsigned char addr_LSB;
unsigned int i;
addr_MSB = Address>>8;
addr_LSB = Address & 0x00ff;
delay10us(1);
IICStart();
IICSendByte(0xa0);
IICRecAck();
delay10us(1);
IICSendByte(addr_MSB);
IICRecAck();
IICSendByte(addr_LSB);
IICRecAck();
IICStart();
IICSendByte(0xa1);
IICRecAck();
for(i=0;i<Length;i++)
{
*p=IICReadData(Address);
Address++;
buf2=*p++;
if(i==(Length-1))
IICNoAck();
else
IICACK();
}
IICStop();
}
void init()
{
SDA=1;
Delay(1);
SCL=1;
Delay(1);
}
void main()
{
unsigned int Address,Length;
unsigned char *p1;
unsigned char *p2;
init();
p1=buf1;
p2=buf2;
Length=32;
Address=0;
IICWritePageData(Address,Length,p1);
Delay(255);
Delay(255);
Delay(255);
Delay(255);
Delay(255);
Delay(255);
Delay(255);
Delay(255);
Length=32;
Address=0;
IICReadPageData(Address,Length,p2);
P3=buf2;
Delay(255);
Delay(255);
Delay(255);
Delay(255);
}
桌面\2.jpg 基本时序搞定,后面就问题不大了。先简后繁
Protues8仿真图片
本帖最后由 Mikle2016 于 2016-7-1 09:35 编辑D\2.jpg 写得这么复杂,I2C是简单协议,什么MCU只要按其时序写,无任何问题。 楼上只说不写,可否贴出页写的程序让大家学习下? 这么一大啪啦程序,没人有耐心给你找毛病的。而且,22M的时钟,只有STC的增强系列才支持,并且时序与传统的51不一样,因为89c51的机器周期是STC12C5A的6倍,这个对软件延时的影响尤为明显 不会吧。最后贴的程序,在22.1184MHz已经可以读写一页了,只是还不能读写第二也,应该没什么难的了吧,只是判断下就可以了。
页:
[1]