使用I2C通讯EEPROM,无法正确读取数据,请教各位大神。
时间:10-02
整理:3721RD
点击:
这个是使用STM8数据库的I2C通讯,我遇到的问题是,在跟EEPROM通讯的时候,第一次写入数据,一个一个读取的话,能知道写入EEPROM的值是没有错的,但是在连续读取数据的时候,就会出现,上电第一次读取数据串的时候,是全部读取正确,然后再读取一遍数据串的时候,只有第一个读取的数据是正确的,后面的数据会全部变成FF FF 这是怎么回事?
#define OWN_ADDRESS 0x00FE
#define EEPROM_ADDRESS 0xA0
void IIC_Init(void)
{
I2C_DeInit();
I2C_Init(100, OWN_ADDRESS, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 1);
I2C_Cmd(ENABLE);
}
void EEPROM_WriteOnePage(u8 address, u8 Number, u8 *DataBuffer)
{
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); //等待空闲
I2C_GenerateSTART(ENABLE);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));//测试EV5,检测从器件返回一个应答值
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);//设置I2C从器件地址,I2C主设备写模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//测试EV6 ,检测从器件返回一个应答信号
I2C_SendData((u8)(address));
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING));// 测试EV8 ,检测从器件返回一个应答信号
while(Number--)//不断往从设备写数据
{
I2C_SendData(*DataBuffer);
DataBuffer++; //指针指向下一个地址
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));//测试EV6 ,检测从器件返回一个应答信号
I2C_AcknowledgeConfig(I2C_ACK_CURR);
}
I2C_GenerateSTOP(ENABLE); //发结束位
DataBuffer=0;
}
void EEPROM_ReadOnePageData(u8 *pBuffer, u8 address, u8 Number)
{
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); // 等待空闲
I2C_GenerateSTART(ENABLE); //发起始位
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));//测试EV5 ,检测从器件返回一个应答信号
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);//设置I2C 从器件地址,I2C 主设备为写模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//测试EV6 ,检测从器件返回一个应答信号
I2C_SendData(address);
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));// 测试EV8 ,检测从器件返回一个应答信号
I2C_GenerateSTART(ENABLE);// 发起始位
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));// 测试EV5 ,检测从器件返回一个应答信号
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_RX);//设置I2C 从器件地址,I2C 主设备为读模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));// 测试EV6 ,检测从器件返回一个应答信号
while(Number)//不断在从从设备读取数据
{
if(I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED))//测试EV6
{
I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);
*pBuffer = I2C_ReceiveData();//从EEPROM 读取一个字节
pBuffer++;//指针指向下个存放字节的地址
if(Number == 1)//读到最后一个字节
{
I2C_AcknowledgeConfig(I2C_ACK_NONE);//不需要应答
I2C_GenerateSTOP(ENABLE);// 发结束位
pBuffer=0;
}
else
{
I2C_AcknowledgeConfig(I2C_ACK_CURR);//不是最后一个字节向从设备发送应答信号
}
Number--;
}
}
}
u8 EEPROM_ReadOneData(u8 address)
{
u8 EEPRom_Read;
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); // 等待空闲
I2C_GenerateSTART(ENABLE); //发起始位
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));//测试EV5 ,检测从器件返回一个应答信号
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);//设置I2C 从器件地址,I2C 主设备为写模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//测试EV6 ,检测从器件返回一个应答信号
I2C_SendData(address);
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));// 测试EV8 ,检测从器件返回一个应答信号
I2C_GenerateSTART(ENABLE);// 发起始位
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));// 测试EV5 ,检测从器件返回一个应答信号
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_RX);//设置I2C 从器件地址,I2C 主设备为读模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));// 测试EV6 ,检测从器件返回一个应答信号
EEPRom_Read=I2C_ReceiveData();//从EEPROM 读取一个字节
I2C_AcknowledgeConfig(I2C_ACK_NONE);//不需要应答
I2C_GenerateSTOP(ENABLE);// 发结束位
return EEPRom_Read;
}
#define OWN_ADDRESS 0x00FE
#define EEPROM_ADDRESS 0xA0
void IIC_Init(void)
{
I2C_DeInit();
I2C_Init(100, OWN_ADDRESS, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 1);
I2C_Cmd(ENABLE);
}
void EEPROM_WriteOnePage(u8 address, u8 Number, u8 *DataBuffer)
{
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); //等待空闲
I2C_GenerateSTART(ENABLE);
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));//测试EV5,检测从器件返回一个应答值
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);//设置I2C从器件地址,I2C主设备写模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//测试EV6 ,检测从器件返回一个应答信号
I2C_SendData((u8)(address));
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTING));// 测试EV8 ,检测从器件返回一个应答信号
while(Number--)//不断往从设备写数据
{
I2C_SendData(*DataBuffer);
DataBuffer++; //指针指向下一个地址
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));//测试EV6 ,检测从器件返回一个应答信号
I2C_AcknowledgeConfig(I2C_ACK_CURR);
}
I2C_GenerateSTOP(ENABLE); //发结束位
DataBuffer=0;
}
void EEPROM_ReadOnePageData(u8 *pBuffer, u8 address, u8 Number)
{
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); // 等待空闲
I2C_GenerateSTART(ENABLE); //发起始位
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));//测试EV5 ,检测从器件返回一个应答信号
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);//设置I2C 从器件地址,I2C 主设备为写模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//测试EV6 ,检测从器件返回一个应答信号
I2C_SendData(address);
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));// 测试EV8 ,检测从器件返回一个应答信号
I2C_GenerateSTART(ENABLE);// 发起始位
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));// 测试EV5 ,检测从器件返回一个应答信号
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_RX);//设置I2C 从器件地址,I2C 主设备为读模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));// 测试EV6 ,检测从器件返回一个应答信号
while(Number)//不断在从从设备读取数据
{
if(I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_RECEIVED))//测试EV6
{
I2C_ClearFlag(I2C_FLAG_ADDRESSSENTMATCHED);
*pBuffer = I2C_ReceiveData();//从EEPROM 读取一个字节
pBuffer++;//指针指向下个存放字节的地址
if(Number == 1)//读到最后一个字节
{
I2C_AcknowledgeConfig(I2C_ACK_NONE);//不需要应答
I2C_GenerateSTOP(ENABLE);// 发结束位
pBuffer=0;
}
else
{
I2C_AcknowledgeConfig(I2C_ACK_CURR);//不是最后一个字节向从设备发送应答信号
}
Number--;
}
}
}
u8 EEPROM_ReadOneData(u8 address)
{
u8 EEPRom_Read;
while(I2C_GetFlagStatus(I2C_FLAG_BUSBUSY)); // 等待空闲
I2C_GenerateSTART(ENABLE); //发起始位
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));//测试EV5 ,检测从器件返回一个应答信号
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_TX);//设置I2C 从器件地址,I2C 主设备为写模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));//测试EV6 ,检测从器件返回一个应答信号
I2C_SendData(address);
while (!I2C_CheckEvent(I2C_EVENT_MASTER_BYTE_TRANSMITTED));// 测试EV8 ,检测从器件返回一个应答信号
I2C_GenerateSTART(ENABLE);// 发起始位
while(!I2C_CheckEvent(I2C_EVENT_MASTER_MODE_SELECT));// 测试EV5 ,检测从器件返回一个应答信号
I2C_Send7bitAddress(EEPROM_ADDRESS, I2C_DIRECTION_RX);//设置I2C 从器件地址,I2C 主设备为读模式
while(!I2C_CheckEvent(I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));// 测试EV6 ,检测从器件返回一个应答信号
EEPRom_Read=I2C_ReceiveData();//从EEPROM 读取一个字节
I2C_AcknowledgeConfig(I2C_ACK_NONE);//不需要应答
I2C_GenerateSTOP(ENABLE);// 发结束位
return EEPRom_Read;
}
大家都说STM32的IIC有点bug,所以很少人用其自带的IIC,一般都是用IO口模拟IIC,模拟很简单而且不会出错,你可以去网上搜下,如果搜不到我可以把代码发给你。
IIC是个很常用的通讯方式,用stm32自带设置会让你知其然不知其所以然,离开了STM32就不知道怎么办了,所以用IO模拟可以好好学习下IIC的通讯协议,也可以移植到其他任何单片机上
谢谢,我已经使用模拟I2C通讯实现了,只是有点不太明白,这个自带I2C到底是哪里有问题,是他这个stm8库问题,还是这个stm8硬件方面的问题?
我使用的是stm8,不是stm32
stm8没用过,但都是arm内核的产品,所以估计都存在一样的问题,网上说是硬件不稳定,可能是会出现通信不畅或卡死等,具体的去网上了解下。我们做的产品都不用stm硬件IIC,都是模拟IO,这样也方便移植