本帖最后由 lixin91985 于 2014-11-1 17:06 编辑
本来是认为是一个很简单的事情。
IO模拟IIC,使用了不知道多少次。花了整整两天时间,参考了不知道多少个以前成功的程序。。。。。还是没有成功
硬件 外部上拉,有试过1k,4,7k 10k。
IC没有问题,因为焊接到STM32上面测试过。。
写入之间的延时有调整过。
测试过多个PCB。排除焊接问题。
用示波器观察,IO有电平输出。逻辑眼观是正确的。
现象:能读出来,,先这么认为吧。
10个数据,第一个能正常写入,每隔两个能正常一个。
#define SCL_H (P1_3=1)
#define SCL_L (P1_3=0)
#define SDA_H (P1_2=1)
#define SDA_L (P1_2=0)
//#define SCL_read (P1_3)
#define SDA_Out (P1DIR|=(1<<2))
#define SDA_In (P1DIR&=~(1<<2))
#define SDA_read (P1_2)
、、----------------------------------------------------下面是程序--------------------------------------------------------------
void EEPROM_HAL_Init(void)
{
// P0DIR|=((1<<6)|(1<<7));
//P1_0=0;P0_6=0;P0_7=0;
//-------------------------------------
SDA_H;SCL_H;
P1DIR|=((1<<3)|(1<<2));// CLK pin is output
// P1INP&=~((1<<3)|(1<<2));
P1SEL&=~((1<<3)|(1<<2));
EE_Delay_ms(100);
I2C_Test();
}
void I2C_delay(void)
{
uint8 i=20; //这里可以优化速度 ,经测试最低到5还能写入
while(i)
{
i--;
}
}
void delayus(uint8 time)
{
while(time)
{
time--;//nop();
}
}
bool I2C_Start(void)
{
SDA_Out;
SDA_H;
SCL_H;
delayus(5);
SDA_L;
delayus(5);
SCL_L; //拉低
delayus(5); return TRUE;
}
void I2C_Stop(void)
{
SDA_Out;
SDA_L;
SCL_H;
delayus(5);
SDA_H;
delayus(5);
SCL_L;
delayus(250);delayus(50);
}
void I2C_Ack(void)
{
SCL_L;I2C_delay();
SDA_Out;SDA_L;
I2C_delay();
SCL_H;
I2C_delay();
SCL_L;
I2C_delay();
}
void I2C_NoAck(void)
{
SDA_Out;
SCL_H;
SDA_H;
delayus(5);
SCL_L;
SDA_L;
delayus(5);
}
bool I2C_WaitAck(void) //返回为:=1有ACK,=0无ACK
{uint8 cnt=255;
//SCL_L;
//I2C_delay();
SDA_Out;
SDA_H;
SCL_H;
I2C_delay();
SDA_In;
//I2C_delay();
while(SDA_read&&cnt) cnt--;
if(cnt==0)
{ SCL_L;//I2C_delay();
return FALSE;
}
SCL_L;//SDA_Out;
return TRUE;
}
void I2C_SendByte(uint8 SendByte) //数据从高位到低位//
{
uint8 i,temp;
SDA_Out;
for(i = 0;i < 8;i ++)
{
temp = SendByte & 0x80;
if(temp)
SDA_H;
else
SDA_L;
SCL_H;
delayus(5);
SCL_L;
delayus(5);
SendByte <<= 1;
}
}
uint8 I2C_ReceiveByte(void) //数据从高位到低位//
{
uint8 i,temp;
SDA_In;
for(i = 0;i < 8;i ++)
{
temp <<= 1;
SCL_H;
delayus(5);
if(SDA_read)
{
temp |= 1;
}
SCL_L;
delayus(5);
}
return temp;
}
void EE_Delay_ms(uint16 Count)
{uint16 i;
uint8 J;
for(;Count>0;Count--)
{for(i=0;i<0x4fff;i++) J++;
}
}
//写入1字节数据 待写入数据 待写入地址 器件类型(24c16或SD2403)
bool I2C_WriteByte(uint8 SendByte, uint16 WriteAddress, uint8 DeviceAddress)
{
I2C_Start();
I2C_SendByte(0xa0);//((WriteAddress & 0x0700) >>7) | DeviceAddress & 0xFFFE);//设置高起始地址+器件地址
I2C_WaitAck();
I2C_SendByte(WriteAddress);//& 0x00FF)); //设置低起始地址
I2C_WaitAck();
I2C_SendByte(SendByte);
I2C_WaitAck();
I2C_Stop();
//注意:因为这里要等待EEPROM写完,可以采用查询或延时方式(10ms)
EE_Delay_ms(10);///EE_Delay_ms(1000);
return TRUE;
}
//读出1串数据 存放读出数据 待读出长度 待读出地址 器件类型(24c16或SD2403)
bool I2C_ReadByte(uint8* pBuffer, uint8 length, uint16 ReadAddress)
{
while(length--)
{
*pBuffer=I2C_ReadChar(ReadAddress);
pBuffer++;ReadAddress++;
EE_Delay_ms(5);
}
return TRUE;
}
uint8 I2C_ReadChar(uint8 addr)
{
uint8 temp;
I2C_Start();
I2C_SendByte(0xa0);
I2C_WaitAck();
I2C_SendByte(addr);
I2C_WaitAck();
I2C_Start();
I2C_SendByte(0xa0 +0x01);
I2C_WaitAck();
temp=I2C_ReceiveByte();
I2C_NoAck();
I2C_Stop();
return temp;
}
void I2C_ReadS_24C(uint16 addr ,uint8* pBuffer,uint16 no)
{I2C_ReadByte(pBuffer,(uint8)no,addr);
}
void I2C_WriteS_24C(uint16 addr,uint8* pBuffer, uint16 no)
{
while(no)
{I2C_WriteByte(*pBuffer,addr,EEPROM_ADDR);// I2C_WriteByte(u8 SendByte, u16 WriteAddress, u8 DeviceAddress)
pBuffer++;addr++;
no--;
//Delay_ns(20);
}
/*
HAL_ENTER_ISR();
I2C_Start();
I2C_SendByte(0xa0);//((addr & 0x0700) >>7) | EEPROM_ADDR& 0xFFFE);//设置高起始地址+器件地址
I2C_WaitAck();
I2C_SendByte((uint8)(addr& 0x00FF)); //设置低起始地址
I2C_WaitAck();
while(no--)
{I2C_SendByte(*pBuffer);pBuffer++;
I2C_WaitAck();
}
I2C_Stop();
HAL_EXIT_ISR();*/
}
void I2C_ByteWrite_24C(uint16 addr,uint8 dat)
{I2C_WriteByte(dat,addr,EEPROM_ADDR);
}
//测试用
void I2C_Test(void)
{
uint8 i;
uint8 I2c_Buf[30];
//I2C_Standby_24C();
//填充缓冲
for(i=0;i<20;i++)
I2c_Buf=i+0x70;
//写
I2C_WriteS_24C(10,I2c_Buf,20);EE_Delay_ms(100);
I2C_WriteByte(0x41,31,EEPROM_ADDR);
I2C_WriteByte(0x42,32,EEPROM_ADDR);
I2C_WriteByte(0x43,33,EEPROM_ADDR);
//清缓冲
for(i=0;i<20;i++)
I2c_Buf=0;
//读
EE_Delay_ms(100);
I2C_ReadS_24C(10,I2c_Buf,30);
EE_Delay_ms(100);
}
、、--------------------------
混论坛这么久,一直都不敢让坛友看这么长的程序。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
{
uint16 i;
IIC_Start();
IIC_Send(0xa0|((Addr/256)<<1));
IIC_Send(Addr%256);
IIC_Send(Data);
IIC_Stop();
for(i=0;i<5000;i++); //这个时间很重要
}
这个是我一直用的写字节的代码,是不是延时不足?
24C02硬件地址三根线需要接,是不是地址不对?
一周热门 更多>