最近有个项目使用AT24C1024存储参数,但是读写有时正常,有时不正常,请各位高手帮看看。上代码如下:
#ifndef AT24C1024_H_
#define AT24C1024_H_
/////////////////////////////////////////////////////////////////////
#include "sys.h"
#include "delay.h"
#include "config.h"
//#define PARAM_WRITE_ERROR 1
//#define PARAM_WRITE_SUCCESS 0
#define PARAM_LEN_ADDR 0x00
#define PARAM_CURR_PAGE 0
#define PARAM_PAGE_SIZE 256
#define PARAM_PAGE_COUNT 512
#define PARAM_READ_DEVICE_ADDR 0xA1
#define PARAM_WRITE_DEVICE_ADDR 0xA0
///////////////////////////////////////////////////////////////////
////设置PIN高低电平
///////////////////////////////////////////////////////////////////
#define SET_BIT(_port,_bit); _port->ODR|=1<<_bit;
#define CLR_BIT(_port,_bit); _port->ODR&=~(1<<_bit);
//SDA PB15
//SCL PB14
#define PARAM_SDA_HIGH SET_BIT(GPIOB,15)
#define PARAM_SDA_LOW CLR_BIT(GPIOB,15)
#define PARAM_SCL_HIGH SET_BIT(GPIOB,14)
#define PARAM_SCL_LOW CLR_BIT(GPIOB,14)
#define PARAM_SCL_OUT {GPIOB->CRH&=0xF0FFFFFF;GPIOB->CRH|=0x03000000;}
#define PARAM_SDA_OUT {GPIOB->CRH&=0x0FFFFFFF;GPIOB->CRH|=0x30000000;}
#define PARAM_SDA_IN {GPIOB->CRH&=0x0FFFFFFF;GPIOB->CRH|=0x80000000;}
#define GET_PARAM_SDA ((GPIOB->IDR&(1<<15))>>15)
void AT24C1024_Init(void);
void PARAM_Idle(void);
void PARAM_Start(void);
void PARAM_Stop(void);
u8 PARAM_Write(u8 dat);
void PARAM_Write_Byte(u8 H_add,u8 L_add, u8 data);
void PARAM_Write_Bytes(u8 H_add,u8 L_add,u8 data[],u8 len);
u8 PARAM_Read(u8 ackBit);//ackBit: low for ACK, high for None ACK;
u8 PARAM_Read_Byte(u8 H_add,u8 L_add);
void PARAM_Read_Bytes(u8 H_add,u8 L_add,u8 data[],u8 len);
#endif /* AT24C1024_H_ */
源文件如下:
#include "AT24C1024.h"
void AT24C1024_Init(void)
{
PARAM_SDA_OUT;
PARAM_SCL_OUT;
PARAM_SDA_HIGH;
PARAM_SCL_HIGH;
}
void PARAM_Idle(void)
{
PARAM_SDA_HIGH;
PARAM_SCL_HIGH;
}
void PARAM_Start(void)
{
PARAM_SDA_OUT;
//PARAM_SCL_OUT;
PARAM_SDA_HIGH;
//delay_us(10);
PARAM_SCL_HIGH;
delay_us(4);
PARAM_SDA_LOW;
delay_us(4);
PARAM_SCL_LOW;
//delay_us(10);
}
void PARAM_Stop(void)
{
PARAM_SDA_OUT;
PARAM_SCL_LOW;
PARAM_SDA_LOW;
delay_us(4);
PARAM_SCL_HIGH;
PARAM_SDA_HIGH;
delay_us(4);
}
u8 PARAM_Write(u8 dat)
{
u8 i=0,max_try_times=0;
PARAM_SDA_OUT;
PARAM_SCL_LOW;
delay_us(10);
for(i=0;i<8;i++)
{
if(dat&0x80)
{
PARAM_SDA_HIGH;
}
else
{
PARAM_SDA_LOW;
}
PARAM_SCL_HIGH;
delay_us(2);
PARAM_SCL_LOW;
delay_us(2);
dat<<=1;
}
//read the ack bit
PARAM_SDA_IN;
PARAM_SDA_HIGH;
delay_us(10);
PARAM_SCL_HIGH;
delay_us(10);
while((u8)GET_PARAM_SDA)
{
max_try_times++;
if(max_try_times>=500)
{
   ARAM_Stop();
return 1;
}
}
delay_us(4);
PARAM_SCL_LOW;
delay_us(4);
return 0;
}
void PARAM_Write_Byte(u8 H_add,u8 L_add, u8 data)
{
PARAM_Start();
PARAM_Write(PARAM_WRITE_DEVICE_ADDR);
PARAM_Write(H_add);
PARAM_Write(L_add);
PARAM_Write(data);
PARAM_Stop();
}
u8 PARAM_Read(u8 ackBit)//ackBit: low for ACK, high for None ACK
{
u8 i,temp;
u16 dat=0x0000;
PARAM_SDA_IN;
//PARAM_SDA_HIGH;
for(i=0;i<8;i++)
{
dat<<=1;
PARAM_SCL_LOW;
delay_us(2);
PARAM_SCL_HIGH;
delay_us(2);
temp=GET_PARAM_SDA;
dat|=temp;
delay_us(2);
}
PARAM_SCL_LOW;
PARAM_SDA_OUT;
if(ackBit)
{
PARAM_SDA_HIGH;
}
else
{
PARAM_SDA_LOW;
}
delay_us(2);
PARAM_SCL_HIGH;
delay_us(2);
PARAM_SCL_LOW;
delay_us(10);
// PARAM_SDA_IN;
// PARAM_SDA_HIGH;
return dat;
}
u8 PARAM_Read_Byte(u8 H_add,u8 L_add)
{
u8 dat;
PARAM_Start();
PARAM_Write(PARAM_WRITE_DEVICE_ADDR);
PARAM_Write(H_add);
PARAM_Write(L_add);
PARAM_Start();
PARAM_Write(PARAM_READ_DEVICE_ADDR);
dat=PARAM_Read(1);
PARAM_Stop();
return dat;
}
void PARAM_Write_Bytes(u8 H_add,u8 L_add,u8 data[],u8 len)
{
u8 i;
for(i=0;i<len;i++)
{
PARAM_Write_Byte(H_add,L_add+i,data);
}
}
void PARAM_Read_Bytes(u8 H_add,u8 L_add,u8 data[],u8 len)
{
u8 i;
for(i=0;i<len;i++)
{
data=PARAM_Read_Byte(H_add,L_add+i);
}
}
声明:GPIOB时钟已经使能了。电路原理图见附件。
|