请教大神,我这个程序利用AT24C02存储2字节数据,为啥存储读取第二个字节出错呢。

m0_37814612 2020-07-10 03:47:27
本人初学,请教大神,我这个程序利用AT24C02存储2字节数据,为啥存储读取第二个字节出错呢。我是想着把两个char数据存储进I2PROM里,然后读取出来合并成一个int数据,然后利用动态数码管显示出来(动态数码管显示函数没毛病)。单字节存储及读取都没问题,两个字节时候读取第二个就出错了。


代码为:


void Delay10us() //延时10us
{
unsigned char a,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}



void I2c_Start()
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();
SDA=0;
Delay10us();
SCL=0;
Delay10us();
}

void I2c_Stop()
{
SDA=0;
Delay10us();
SCL=1;
Delay10us();
SDA=1;
Delay10us();
}

void I2c_Send(unsigned char dat)
{
unsigned char a;//b=0;
for(a=0;a<8;a++)
{
SDA=dat>>7;
dat=dat<<1;
Delay10us();
SCL=1;
Delay10us();
SCL=0;
Delay10us();
}
SDA=1;
Delay10us();
SCL=0; //
// while(SDA)
// {
// b++;
// if(b>200)
// { //如果超过2000us没有应答发送失败,或者为非应答,表示接收结束返回0
// SCL=0;
// Delay10us();
// return 0;
// }
// }
// SCL=0;
// Delay10us();
// return 1;

}



void I2c_Ack() //发送应答
{
SDA=0;
Delay10us();
SCL=1;
Delay10us();
SCL=0;

}

void I2c_Noack() //发送非应答
{
SDA=1;
Delay10us();
SCL=1;
Delay10us();
SCL=0;

}


unsigned char I2c_Read() //读取函数
{
unsigned char a,dat=0;
SDA=1;
Delay10us();
for(a=0;a<8;a++)
{
SCL=1;
Delay10us();
dat<<=1;
dat|=SDA;
Delay10us();
SCL=0;
Delay10us();
}
return dat;
}

void At24c02_Write(unsigned char addr,unsigned char dat,unsigned char addr1,unsigned char dat1)
{
I2c_Start();
I2c_Send(0xa0); //发送写器件地址
I2c_Ack();
I2c_Send(addr); //发送要写器件内存地址
I2c_Ack();
I2c_Send(dat); // 发送存入的数据
I2c_Ack();
I2c_Send(addr1); //发送要写器件内存地址
I2c_Ack();
I2c_Send(dat1); // 发送存入的数据
I2c_Ack();
I2c_Stop();
}
unsigned char At24c02_Read(unsigned char addr)
{
unsigned char num;
I2c_Start();
I2c_Send(0xa0); //首先发送写器件地址
I2c_Ack();
I2c_Send(addr); //发送要读取的内存地址
I2c_Ack();
I2c_Start(); //再次发送开始信号,使通信方向翻转
I2c_Send(0xa1); //发送器件地址 通讯方向由发送变为接收
I2c_Ack();
num=I2c_Read(); //读取器件内地址为addr的数据保存在变量内
I2c_Noack();
I2c_Stop(); //结束信号
return num; //函数返回的数据值
}

typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;
u8 nlm=0;
u8 nhm=0;
u16 Rundata=0;
void Keypro()
{
if(k1==0)
{
delay(1000);
if(k1==0)
{
nlm++;
if(nlm>20)
{
nhm=nhm+1;
nlm=0;
}
}
while(!k1);
}
if(k2==0)
{
delay(1000);
if(k2==0)
{
At24c02_Write(1,nlm,2,nhm);

}
while(!k2);
}
if(k3==0)
{
delay(1000);
if(k3==0)
{
nlm=At24c02_Read(1);
nhm=At24c02_Read(2);
Rundata=nhm*256+nlm;
}
while(!k3);
}
if(k4==0)
{
delay(1000);
if(k4==0)
{
nlm=0;
}
while(!k4);
}
if(k5==0)
{
delay(1000);
if(k5==0)
{
At24c02_Write(1,0,2,0);
}
while(!k5);
}

}
...全文
7763 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Brendon_Tan 2020-07-13
  • 打赏
  • 举报
回复
希望楼主好好利用,上面的这个程序是亲测能用的。 如果帮到你了,请给我加分吧。
Brendon_Tan 2020-07-13
  • 打赏
  • 举报
回复
接上一回复。 AT24C04 读写函数

#include "24cxx.h"


/* Write One Byte to AT24CXX 	*/
/* write_addr:		写入地址	*/
/* data:			写入数据	*/
/* return:		0:	写入成功	*/
unsigned char AT24CXX_Write_Byte(unsigned short int write_addr, unsigned char data)
{
	IIC_Start();
	
	if(EE_TYPE > AT24C16)
	{
		IIC_Send_Byte(AT24CXX_ADDR <<1 | IIC_WR);
		IIC_Wait_Ack();
		IIC_Send_Byte(write_addr>>8);
	}
	else 
		IIC_Send_Byte(AT24CXX_ADDR <<1 | IIC_WR);
	IIC_Wait_Ack();
    IIC_Send_Byte(write_addr%256);
	IIC_Wait_Ack();
	IIC_Send_Byte(data);
	IIC_Wait_Ack();
    IIC_Stop();
	delay_ms(10);		//必须要加,否则写入不了多个数据
	return 0;
}


/* Read One Byte from AT24CXX 	*/
/* read_addr:		读取地址	*/
/* *data:			读取数据	*/
/* return:		0:	读取成功	*/
unsigned char AT24CXX_Read_Byte(unsigned short int read_addr, unsigned char *data)
{
    IIC_Start();
	if(EE_TYPE > AT24C16)
	{
		IIC_Send_Byte(AT24CXX_ADDR <<1 | IIC_WR);
		IIC_Wait_Ack();
		IIC_Send_Byte(read_addr >> 8);
	}
	else
		IIC_Send_Byte(AT24CXX_ADDR <<1 | IIC_WR);
	IIC_Wait_Ack();
    IIC_Send_Byte(read_addr % 256);
	IIC_Wait_Ack();
	IIC_Start();
	IIC_Send_Byte(AT24CXX_ADDR <<1 | IIC_RD);
	IIC_Wait_Ack();
    *data=IIC_Read_Byte(0);
    IIC_Stop();
	
	return 0;
}


/* Write len Byte to AT24CXX 	*/
/* write_addr:		写入地址	*/
/* data:			写入数据	*/
/* len:				写入字节数	*/
/* return:		0:	写入成功	*/
unsigned char AT24CXX_Write_LenByte(unsigned short int write_addr, unsigned int data, unsigned char len)
{
	unsigned char temp=0;
	
	while(len--)
	{
		temp=data>>(8*len) & 0xFF;
		AT24CXX_Write_Byte(write_addr, temp);
		write_addr++;
	}
	return 0;
}


/* Read len Byte from AT24CXX 	*/
/* read_addr:		读取地址	*/
/* *data:			读取数据	*/
/* len:				读取字节数	*/
/* return:		0:	读取成功	*/
unsigned char AT24CXX_Read_LenByte(unsigned short int read_addr, unsigned int *data, unsigned char len)
{
	unsigned char temp=0;
	*data=0;
	while(len--)
	{
		temp=0;
		AT24CXX_Read_Byte(read_addr, &temp);
		*data=(*data<<8) + temp;
		read_addr++;
	}
	return 0;
}


/* Write num Data to AT24CXX 	*/
/* write_addr:		写入地址	*/
/* *buf:			写入数组	*/
/* num:				写入数量	*/
/* return:		0:	写入成功	*/
unsigned char AT24CXX_Write_nData(unsigned short int write_addr, unsigned char *buf, unsigned char num)
{
	while(num--)
	{
		AT24CXX_Write_Byte(write_addr, *buf);
		write_addr++;
		buf++;
	}
	return 0;
}


/* Read num Data from AT24CXX 	*/
/* write_addr:		读取地址	*/
/* *buf:			读取数组	*/
/* num:				读取数量	*/
/* return:		0:	读取成功	*/
unsigned char AT24CXX_Read_nData(unsigned short int read_addr, unsigned char *buf, unsigned char num)
{
	unsigned char temp;
	while(num--)
	{
		temp=0;
		AT24CXX_Read_Byte(read_addr, &temp);
		*buf=temp;
		read_addr++;
		buf++;
	}
	return 0;
}


/************************ END of the File *************************/


#ifndef _24cxx_H
#define _24cxx_H

#include "includes.h"


#define AT24C01		127
#define AT24C02		255
#define AT24C04		511
#define AT24C08		1023
#define AT24C16		2047
#define AT24C32		4095
#define AT24C64	    8191
#define AT24C128	16383
#define AT24C256	32767

#define EE_TYPE		AT24C04

#define AT24CXX_ADDR	0x50	// 1010 000x


unsigned char AT24CXX_Write_Byte(unsigned short int write_addr, unsigned char data);
unsigned char AT24CXX_Read_Byte(unsigned short int read_addr, unsigned char *data);
unsigned char AT24CXX_Write_LenByte(unsigned short int write_addr, unsigned int data, unsigned char len);
unsigned char AT24CXX_Read_LenByte(unsigned short int read_addr, unsigned int *data, unsigned char len);
unsigned char AT24CXX_Write_nData(unsigned short int write_addr, unsigned char *buf, unsigned char num);
unsigned char AT24CXX_Read_nData(unsigned short int read_addr, unsigned char *buf, unsigned char num);


#endif

/************************ END of the File *************************/

Brendon_Tan 2020-07-13
  • 打赏
  • 举报
回复
直接附上我前几年写的IIC读写AT24C04的数据。 IIC 驱动

/*********************** V1.0 - 2016.11.27  ***********************/
//1.支持发送一个字节数据,接收一个字节数据
//2.支持往多个连续地址发送多个数据
//3.支持从多个连续地址读取多个数据
/*********************** V1.1 - 2016.11.30  ***********************/
//4.支持对设备任一可写寄存器中数据任一位进行修改
//5.支持对设备任一可写寄存器中数据多个位进行修改
/************************* END of Record  *************************/

#include "iic.h"


/* IIC Init */
void IIC_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(IIC_RCC , ENABLE);					//使能 IIC 时钟
	
	GPIO_InitStructure.GPIO_Pin = IIC_SCL_Pin | IIC_SDA_Pin;	//IIC对应IO口
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;				//普通输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;				//管脚推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;			//管脚频率2MHz
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;			//管脚上拉
	
	GPIO_Init(IIC_Port , &GPIO_InitStructure);					//初始化IIC GPIO
	
	IIC_SCL_H;
	IIC_SDA_H;
}


/* IIC Start */
void IIC_Start(void)
{
	IIC_SDA_H;
	IIC_SCL_H;	IIC_delay();			// SDA	-- __ __
	IIC_SDA_L;	IIC_delay();			// SCL	-- -- __
	IIC_SCL_L;	IIC_delay();
}


/* IIC Stop */
void IIC_Stop(void)
{
	IIC_SCL_L;	IIC_delay();
    IIC_SDA_L;	IIC_delay();			// SDA	__ __ --
	IIC_SCL_H;	IIC_delay();			// SCL	__ -- --
	IIC_SDA_H;	IIC_delay();
}


/* IIC Send Ack */
void IIC_Ack(void)
{
	IIC_SCL_L;
    IIC_SDA_L;	IIC_delay();
	IIC_SCL_H;	IIC_delay();			// SDA	__ __ __ --
	IIC_SCL_L;	IIC_delay();			// SCL	__ -- __ __
	IIC_SDA_H;
}


/* IIC Send NAck */
void IIC_NAck(void)
{
	IIC_SCL_L;
    IIC_SDA_H;	IIC_delay();			// SDA	-- -- -- --
	IIC_SCL_H;	IIC_delay();			// SCL	__ -- __ __
	IIC_SCL_L;	IIC_delay();
	IIC_SDA_H;
}


/* IIC Wait a Ack 	*/
/* return:			*/
/* ack=1	有应答	*/
/* ack=0	无应答	*/
unsigned char IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	
	IIC_SCL_L;	IIC_delay();
	IIC_SDA_H;	IIC_delay();
	IIC_SCL_H;	IIC_delay();
	while(IIC_SDA_READ())
	{
		ucErrTime++;
		if(ucErrTime > 50)
		{
			IIC_Stop();
			return 0;
		}
	}
	IIC_SCL_L;
	IIC_delay();
	
	return 1;
}


/* IIC Send One Byte */
void IIC_Send_Byte(unsigned char data)
{
    unsigned char i;
	
	IIC_SCL_L;	IIC_delay();
	for(i = 0; i < 8; i++)
	{
		if(data & 0x80)
		{
			IIC_SDA_H;
			IIC_delay();
		}
		else
		{
			IIC_SDA_L;
			IIC_delay();
		}
		IIC_SCL_H;	IIC_delay();
		IIC_SCL_L;	IIC_delay();
		data <<= 1;
		if(i == 7)
		{
			IIC_delay();
			IIC_SDA_H;
		}
	}
}


/* IIC Read One Byte	*/
/* ack=1	发送Ack		*/
/* ack=0	发送NAck	*/
unsigned char IIC_Read_Byte(unsigned char ack)
{
    unsigned char i;
	unsigned char data=0;
	
	for(i = 0; i < 8; i++)
	{
		data <<= 1;
		IIC_SCL_L;	IIC_delay();
		IIC_SCL_H;	IIC_delay();
		if(IIC_SDA_READ())
		{
			data |=0x01;
		}
				
	}
	IIC_SCL_L;
	if(ack == 0)
	{
		IIC_NAck();
	}
	else
	{
		IIC_Ack();
	}
	return data;
}


/* A simple IIC delay */
static void IIC_delay(void)
{
    unsigned char i;
	for(i = 0; i < 20; i++);	//i>10,才能保证通讯时序
}


/* Write One Data to Register 		*/
/* slaveaddr:		器件地址		*/
/* reg_addr:		寄存器地址		*/
/* reg_data:		发送的数据		*/
unsigned char IIC_Write_Data(unsigned char slaveaddr, unsigned char reg_addr, unsigned char reg_data)
{
	IIC_Start();
	IIC_Send_Byte(slaveaddr << 1 | IIC_WR);
	if(IIC_Wait_Ack() == 0)
	{
		IIC_Stop();
		return 1;
	}
	IIC_Send_Byte(reg_addr);
	IIC_Wait_Ack();
	IIC_Send_Byte(reg_data);
	IIC_Wait_Ack();
	IIC_Stop();

	return 0;
}


/* Write n Data to Register 		*/
/* slaveaddr:		器件地址		*/
/* reg_addr:		寄存器地址		*/
/* num:				数据数量		*/
/* reg_data:		发送的数据		*/
unsigned char IIC_Write_nData(unsigned char slaveaddr, unsigned char reg_addr, unsigned int num, unsigned char *buf)
{
	IIC_Start();
	IIC_Send_Byte(slaveaddr << 1 | IIC_WR);
	if(IIC_Wait_Ack() == 0)
	{
		IIC_Stop();
		return 1;
	}
	IIC_Send_Byte(reg_addr);
	IIC_Wait_Ack();
	while(num--)
	{
		IIC_Send_Byte(*buf);
		IIC_Wait_Ack();
		buf++;
	}
	IIC_Stop();

	return 0;
}


/* Read One Data from Register 		*/
/* slaveaddr:		器件地址		*/
/* reg_addr:		寄存器地址		*/
/* *reg_data:		接收的数据地址	*/
unsigned char IIC_Read_Data(unsigned char slaveaddr, unsigned char reg_addr, unsigned char *reg_data)
{
	IIC_Start();
	IIC_Send_Byte(slaveaddr << 1 | IIC_WR);
	if( IIC_Wait_Ack() == 0 )
	{
		IIC_Stop();
		return 1;
	}
	IIC_Send_Byte(reg_addr);
	IIC_Wait_Ack();
	IIC_Start();
	IIC_Send_Byte(slaveaddr << 1 | IIC_RD);
	IIC_Wait_Ack();
	*reg_data = IIC_Read_Byte(0);
	IIC_Stop();

	return 0;
}


/* Read n Data from Register 		*/
/* slaveaddr:		器件地址		*/
/* reg_addr:		寄存器地址		*/
/* num:				数据数量		*/
/* *buf:			接收的数据地址	*/
unsigned char IIC_Read_nData(unsigned char slaveaddr, unsigned char reg_addr, unsigned int num, unsigned char *buf)
{
//	unsigned int i=0;
	IIC_Start();
	IIC_Send_Byte(slaveaddr << 1 | IIC_WR);
    if( IIC_Wait_Ack() == 0 )
	{
		IIC_Stop();
		return 1;
	}
	IIC_Send_Byte(reg_addr);
	IIC_Wait_Ack();
	
	IIC_Start();
	IIC_Send_Byte(slaveaddr << 1 | IIC_RD);
	IIC_Wait_Ack();
	while(num)
	{
		if(num == 1)
		{
			*buf = IIC_Read_Byte(0);
		}
		else
		{
			*buf = IIC_Read_Byte(1);
		}
		buf ++;
		num --;
	}
//	for(i = 0; i < (num -1); i++)
//	{
//		*buf = IIC_Read_Byte(1);
//	    buf++;
//	}
//	*buf = IIC_Read_Byte(0);
    IIC_Stop();
	return 0;
}


/* Write One Bit Data to REG Data 		*/
/* slaveaddr:		器件地址			*/
/* reg_addr:		寄存器地址			*/
/* bit_num:			位的序号(第几位)	*/
/* bit_data:		位的数据(位的状态)	*/
void IIC_Write_Bit(unsigned char slaveaddr, unsigned char reg_addr, unsigned int bit_num, unsigned char bit_data)
{
	unsigned char b;
	IIC_Read_Data(slaveaddr, reg_addr, &b);
	b=(bit_data != 0) ? (b | (1 << bit_num)) : (b & ~(1 << bit_num));
	IIC_Write_Data(slaveaddr, reg_addr, b);
}


/* Write len Bit Data to REG Data 		*/
/* slaveaddr:		器件地址			*/
/* reg_addr:		寄存器地址			*/
/* bit_start:		开始位的序号(第几位)*/
/* len:				修改位的个数		*/
/* bit_data:		位的数据(位的状态)	*/
void IIC_Write_nBit(unsigned char slaveaddr, unsigned char reg_addr ,unsigned char bit_start,unsigned int len, unsigned char bit_data)
{
	unsigned char b,temp;
	IIC_Read_Data(slaveaddr, reg_addr, &b);
	temp= (0xFF << (bit_start + 1)) | 0xFF >> ((8 - bit_start) + len -1);
	bit_data <<= (8 - len);
	bit_data >>= (7 - bit_start);
	b &=temp;
	b |=bit_data;
	IIC_Write_Data(slaveaddr, reg_addr, b);
}


/************************ END of the File *************************/


#ifndef _iic_H
#define _iic_H

#include "includes.h"


//Define of the IIC GPIO
#define IIC_RCC				RCC_AHB1Periph_GPIOB
#define IIC_Port			GPIOB
#define IIC_SCL_Pin			GPIO_Pin_10
#define IIC_SDA_Pin			GPIO_Pin_11


//Define of the IIC
#define IIC_SCL_H			GPIO_SetBits(IIC_Port ,IIC_SCL_Pin)
#define IIC_SCL_L			GPIO_ResetBits(IIC_Port ,IIC_SCL_Pin)

#define IIC_SDA_H			GPIO_SetBits(IIC_Port ,IIC_SDA_Pin)
#define IIC_SDA_L			GPIO_ResetBits(IIC_Port ,IIC_SDA_Pin)

#define IIC_SDA_READ()  	GPIO_ReadInputDataBit(IIC_Port, IIC_SDA_Pin)

#define IIC_WR	0		
#define IIC_RD	1


void IIC_Init(void);

void IIC_Start(void);
void IIC_Stop(void);
void IIC_Ack(void);
void IIC_NAck(void);
unsigned char IIC_Wait_Ack(void);
void IIC_Send_Byte(unsigned char Data);
unsigned char IIC_Read_Byte(unsigned char ack);

static void IIC_delay(void);

unsigned char IIC_Write_Data(unsigned char slaveaddr, unsigned char reg_addr, unsigned char reg_data);
unsigned char IIC_Write_nData(unsigned char slaveaddr, unsigned char reg_addr, unsigned int num, unsigned char *buf);
unsigned char IIC_Read_Data(unsigned char slaveaddr, unsigned char reg_addr, unsigned char *reg_data);
unsigned char IIC_Read_nData(unsigned char slaveaddr, unsigned char reg_addr, unsigned int num, unsigned char *buf);

void IIC_Write_Bit(unsigned char slaveaddr, unsigned char reg_addr, unsigned int bit_num, unsigned char bit_data);
void IIC_Write_nBit(unsigned char slaveaddr, unsigned char reg_addr, unsigned char bit_start,unsigned int len, unsigned char bit_data);


#endif

/************************ END of the File *************************/

放不下,见下一回复
dceacho 2020-07-11
  • 打赏
  • 举报
回复
引用 5 楼 m0_37814612 的回复:
if(k2==0) { At24c02_Write(1,nlm); } if(k1==0) { delay(1000); if(k1==0) { nlm++; if(nlm>20) { nhm=nhm+1; nlm=0; At24c02_Write(2,nhm); } } 这样分开存储行, 不能连续存呢 。中间是需要延迟吗?
是有个指标,你看PDF, 5ms还是7ms的随机写入时间
m0_37814612 2020-07-10
  • 打赏
  • 举报
回复
if(k2==0)
{
At24c02_Write(1,nlm);

}
if(k1==0)
{
delay(1000);
if(k1==0)
{
nlm++;
if(nlm>20)
{
nhm=nhm+1;
nlm=0;
At24c02_Write(2,nhm);
}
}


这样分开存储行, 不能连续存呢 。中间是需要延迟吗?
m0_37814612 2020-07-10
  • 打赏
  • 举报
回复
引用 2 楼 dceacho 的回复:
好久没用这个了,看起来是你的写入流程有问题
如果你单字节的写,第一个字节写入后有个STOP ACK, STOP的, 然后重新START再来一次
如果你是连续写,则只需要写入第一个字节的存储位置,不需要写后面数据的存储地址


好的 我试一下哈,不知道是写的时候不对 还是读取的时候不对。
m0_37814612 2020-07-10
  • 打赏
  • 举报
回复
引用 1 楼 智者知已应修善业 的回复:
用数码管显示一下读到的2个数据是否为存入的数据?

写入的第二个数据地址2,读取出来数据是2. 应该是0才对。 不知道哪不对劲。
dceacho 2020-07-10
  • 打赏
  • 举报
回复
好久没用这个了,看起来是你的写入流程有问题 如果你单字节的写,第一个字节写入后有个STOP ACK, STOP的, 然后重新START再来一次 如果你是连续写,则只需要写入第一个字节的存储位置,不需要写后面数据的存储地址
  • 打赏
  • 举报
回复
用数码管显示一下读到的2个数据是否为存入的数据?

27,374

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧