|
初学单片机时候用的EEPROM就是AT24C02,51模拟I2C,也就这样用了很久。
前段时间用到KE,MKE06Z128 有自带的FLASH模拟EEPROM存储,但为了有更多选择保证系统,还是加入外设I2C读写EEPRM。开始也没考虑太多,直接用自带库编写程序读写都不能成功。最后找到问题所在。
第一点:多次读写C02时出错
摘录原版代码:
uint8_t I2C_Start(I2C_Type *pI2Cx){ uint32_t u32Timeout; uint8_t u8ErrorStatus; u32Timeout = 0; u8ErrorStatus = 0x00; I2C_TxEnable(pI2Cx); pI2Cx->C1 |= I2C_C1_MST_MASK; while( (!I2C_IsBusy(pI2Cx)) && ( u32Timeout < I2C_WAIT_STATUS_TIMEOUT)) { u32Timeout ++; } if( u32Timeout == I2C_WAIT_STATUS_TIMEOUT ) { u8ErrorStatus |= I2C_ERROR_START_NO_BUSY_FLAG; } return u8ErrorStatus;}
I2C_TxEnable(pI2Cx);
pI2Cx->C1 |= I2C_C1_MST_MASK; 这两行代码如果在检测I2C忙标志位前运行,会出现多次读写C02时出错。
改到总线忙检测后不会出现这种错误。
第二点:指定址码后的开始信号
读取C02指定地址数据时,需在写入地址码后再次发送开始信号,但数据始终是错误的。后加入示波器观察波形发现开始信号没有正常发送(这里就不贴图了,请原谅)。在开始信号前加入停止信号,和修改第一点的代码后读写C02正常。
uint8_t EEP_ReadOneByte(uint16_t WordAddress, uint8_t *pRdBuff, uint32_t u32Length){ uint32_t i; uint8_t u8ErrorStatus, temp[1]; // send start signals to bus u8ErrorStatus = I2C_Start(I2C0); //Device Address - WRITE u8ErrorStatus = I2C_WriteOneByte(I2C0, 0xa0 | I2C_WRITE); //Word Address (n) u8ErrorStatus = I2C_WriteOneByte(I2C0, WordAddress); //Device Address - READ u8ErrorStatus = I2C_Stop(I2C0); u8ErrorStatus = I2C_Start(I2C0); u8ErrorStatus = I2C_WriteOneByte(I2C0, 0xa0 | I2C_READ); // dummy read one byte to switch to Rx mode I2C_ReadOneByte(I2C0, &temp[0], I2C_SEND_ACK); if(I2C_ERROR_NULL == u8ErrorStatus) { for(i = 0; i<(u32Length-1); i++) { u8ErrorStatus = I2C_ReadOneByte(I2C0, &pRdBuff, I2C_SEND_ACK); if(I2C_ERROR_NULL != u8ErrorStatus) { break; } } I2C_ReadOneByte(I2C0, &pRdBuff, I2C_SEND_NACK); } u8ErrorStatus = I2C_Stop(I2C0); return u8ErrorStatus;}当时时间并不富裕,如以上有本人理解错误地方还请大家指正。 |
|