最近在调试24c256,出了点问题老是找不出毛病,就是对24C256写数据的时候,前面有可能用得好好的,后面就突然数据开始错位了
正常读出来的数据应该是这样的:1803041000030028130161
但是出现问题后读出来的数据都是:
0627110546002812016100
0627110712000004000000
0627150724000004000000
(我是每次写入16字节的数据,前11个字节是有效,后5个是补零)
我每次只写16个字节的数据,写入的间隔时间也不短,出问题是应该是地址错位了。
但是程序里面是没有问题的。所以想请问大神们,有什么原因可能导致我出现这个问题,谢谢
下面我贴下我的程序,请帮忙看下
这是main里使用的:
IIC_Transmit(0xA0,Wddr, &Savedata[0], 16);//往24C256写入数据
Delayms(400);
下面是24c256的子程序:
**************************************************************************************************************************/
/*
********************************************************
函数名称:void AT24C256_Init(void)
函数功能:初始化IO口
********************************************************
*/
void AT24C256_Init(void)
{
DDRE |= 0xC0;
PORTE |= 0xC0;
}
/*
********************************************************
函数名称:static void IIC_delay(void)
函数功能:延时
********************************************************
*/
static void IIC_delay(void)
{
asm("nop");
}
/*
********************************************************
函数名称:static void IIC_delay(void)
函数功能:主机发送开始信号
********************************************************
*/
static void IIC_Start(void)
{
MODE_OUT;
SDA_H;
asm("nop");
SCL_H;
asm("nop");
asm("nop");
asm("nop");
SDA_L;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
SCL_L;
asm("nop");
asm("nop");
}
/*
********************************************************
函数名称:static void IIC_Stop(void)
函数功能:主机发送结束信号
********************************************************
*/
static void IIC_Stop(void)
{
MODE_OUT;
SCL_L;
asm("nop");
asm("nop");
SDA_L;
asm("nop");
asm("nop");
SCL_H;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
SDA_H;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
}
/*
********************************************************
函数名称: static unsigned char IIC_ACK_Check(void)
函数功能: 主机成功发送一个字节数据后,AT24C256会发送一
应答信号。
返回值 : 1 没有应答信号,即从机没有成功接收到数据
0 有应答信号,即从机已接收到了数据
********************************************************
*/
static unsigned char IIC_ACK_Check(void)
{
unsigned char Bitmun;
MODE_IN;
SCL_L;
asm("nop");
asm("nop");
SDA_H;
asm("nop");
asm("nop");
SCL_H;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
Bitmun = PINE;
SCL_L;
asm("nop");
asm("nop");
Bitmun =(Bitmun >> 7)&0x01;
return Bitmun;
}
/*
********************************************************
函数名称: static void IIC_NO_ACK(void)
函数功能: 主机发送一个字节数据后,
不会检测从机的应答信号
********************************************************
*/
static void IIC_NO_ACK(void)
{
MODE_OUT;
SCL_L;
asm("nop");
asm("nop");
SDA_H;
asm("nop");
asm("nop");
SCL_H;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
SCL_L;
asm("nop");
asm("nop");
}
/*
********************************************************
函数名称: static void IIC_ACK_Creat(void)
函数功能: 主机向从机请求一个字节数据后,
发送应答信号,告诉从机继续发送数据。(连读读模式)
********************************************************
*/
static void IIC_ACK_Creat(void)
{
MODE_OUT;
SCL_L;
asm("nop");
asm("nop");
SDA_L;
asm("nop");
asm("nop");
SCL_H;
asm("nop");
asm("nop");
asm("nop");
asm("nop");
SCL_L;
asm("nop");
asm("nop");
}
/*
********************************************************
函数名称: static void IIC_Send8Bit(unsigned char SendByte)
函数功能: 主机发送一个字节数据
********************************************************
*/
static void IIC_Send8Bit(unsigned char SendByte)
{
char counter;
MODE_OUT;
SDA_L;
asm("nop");
asm("nop");
asm("nop");
for (counter = 8; counter >0; counter--)
{
SCL_L;
asm("nop");
asm("nop");
if (SendByte & 0x80)
{
SDA_H;
asm("nop");
}
else
{
SDA_L;
asm("nop");
asm("nop");
}
SCL_H;
asm("nop");
SendByte = SendByte << 1;
}
SCL_L;
asm("nop");
asm("nop");
}
/*
********************************************************
函数名称: static unsigned char IIC_Receive8Bit(void)
函数功能: 主机接收一个字节数据
********************************************************
*/
static unsigned char IIC_Receive8Bit(void)
{
char counter;
unsigned char ReceiveByte=0;
unsigned char IOstatus=0;
MODE_IN;
SCL_L;
asm("nop");
asm("nop");
SDA_H;
asm("nop");
asm("nop");
for (counter = 8; counter > 0; counter--)
{
SCL_L;
asm("nop");
asm("nop");
SCL_H;
asm("nop");
asm("nop");
IOstatus = PINE;
ReceiveByte = ReceiveByte<<1;
ReceiveByte |= (IOstatus >>7)& 0x01;
}
SCL_L;
return ReceiveByte;
}
/*
********************************************************
函数名称: char IIC_Transmit(unsigned char lcv_device,unsigned int liv_addr,unsigned char *lcv_pdata, char counter)
函数功能: 主机往指定地址发送数据
unsigned char lcv_device 从机地址
unsigned int liv_addr 从机内部存储地址
unsigned char *lcv_pdata 发送数据缓存区
char counter 发送多少个数据
返回值 : 1 写入数据失败
0 写入成功
注: AT24C256在连续读写过程中,会自动增加地址,但是不会自动跳转到下一页,
所以要注意连续读写过程中不要超过页的存储空间,避免最先存储的数据被覆盖从而导致
数据丢失。
********************************************************
*/
char IIC_Transmit(unsigned char lcv_device,unsigned int liv_addr,unsigned char *lcv_pdata, char counter)
{
IIC_Start();
/* 发送从机地址 */
IIC_Send8Bit(lcv_device);
if ( IIC_ACK_Check() ) //调用函数char IIC_ACK_Check(void),没有从机回应则结束本次发送。
{
IIC_Stop();
return FAIL;
}
/* 发送内存地址*/
IIC_Send8Bit((unsigned char)(liv_addr >> 8) & 0x0FF); //高八位
if ( IIC_ACK_Check()) //调用函数char IIC_ACK_Check(void),没有从机回应则结束本次发送。
{
IIC_Stop();
return FAIL;
}
IIC_Send8Bit((unsigned char)((liv_addr)&0x0FF)); //低八位
if ( IIC_ACK_Check()) //调用函数char IIC_ACK_Check(void),没有从机回应则结束本次发送。
{
IIC_Stop();
return FAIL;
}
/* 发送数据 */
for(;counter > 0;counter-- )
{
IIC_Send8Bit(*lcv_pdata);
if ( IIC_ACK_Check()) //调用函数char IIC_ACK_Check(void),没有从机回应则结束本次发送。
{
IIC_Stop();
return FAIL;
}
lcv_pdata++;
}
IIC_Stop();
return SUCCEED;
}
/*
********************************************************
函数名称 : char IIC_Receive(unsigned char lcv_device, unsigned int liv_addr, unsigned char *lcv_pdata, char counter)
函数功能 : 主机接收数据
unsigned char lcv_device 从机地址
unsigned int liv_addr 从机内部存储地址
unsigned char *lcv_pdata 发送数据缓存区
char counter 发送多少个数据
返回值 : 1 读数据失败
0 读成功
注: AT24C256在连续读写过程中,会自动增加地址,但是不会自动跳转到下一页,
所以要注意连续读写过程中不要超过页的存储空间,避免最先存储的数据被覆盖从而导致
数据丢失。
读模式: 需要先配置为写模式,然后才能改为读模式
********************************************************
*/
char IIC_Receive(unsigned char lcv_device, unsigned int liv_addr, unsigned char *lcv_pdata, char counter)
{
/* 先将从机配置为写模式 */
IIC_Start();
/* 发送从机地址 */
IIC_Send8Bit(lcv_device);
if ( IIC_ACK_Check())//调用函数char IIC_ACK_Check(void),没有从机回应则结束本次发送。
{
IIC_Stop();
return FAIL;
}
/* 发送内存地址 */
IIC_Send8Bit((unsigned char)((liv_addr >> 8)&0x0FF));
if ( IIC_ACK_Check()) //调用函数char IIC_ACK_Check(void),没有从机回应则结束本次发送。
{
IIC_Stop();
return FAIL;
}
IIC_Send8Bit((unsigned char)((liv_addr)&0x0FF));
if ( IIC_ACK_Check()) //调用函数char IIC_ACK_Check(void),没有从机回应则结束本次发送。
{
IIC_Stop();
return FAIL;
}
/* 然后将从机配置为写模式 */
IIC_Start();
/* 发送从机地址 */
IIC_Send8Bit(lcv_device+1);
if ( IIC_ACK_Check()) ////调用函数char IIC_ACK_Check(void),没有从机回应则结束本次发送。
{
IIC_Stop();
return FAIL;
}
for( ; counter > 0; )
{
*lcv_pdata = IIC_Receive8Bit();
counter--;
if ( counter >0)
{
IIC_ACK_Creat();
lcv_pdata++ ;
}
}
IIC_NO_ACK();
IIC_Stop();
return SUCCEED;
} |
你先用 IIC_delay 调出一个SCL方波,频率是400khz, 方便调用。 宏定义一个mcu工作频率,和总线工作频率,自适应生成IIC_delay 函数。
应该是硬件问题。 不知道延时够不够。mcu 运行频率是多少? 比如运行频率 16MHZ, 24256 总线是400khzMax。 16/0.4MHZ = 40; 看你软件延时使用nop,AVR 是risc ,从scl 之间至少的有19 个NOP 或者其他指令。