关于STM32F4 HAL库操作外部EEPROM的疑惑
关于STM32F4 HAL库操作外部EEPROM的疑惑最近在搞24C16存储器,用的是STM32F429,工程使用CUBEMX工具生成的,因此使用的是HAL库,
但是发现HAL库提供存储器的函数就两个HAL_I2C_Mem_Write和HAL_I2C_Mem_Read,HAL库已经没有了原来DSP库的那么多函数了
我的代码如下,
static void I2Cx_Init(void)
{
if(HAL_I2C_GetState(&heval_I2c) == HAL_I2C_STATE_RESET)
{
heval_I2c.Instance = I2C2; //I2C1
heval_I2c.Init.ClockSpeed = I2C_SPEED;
heval_I2c.Init.DutyCycle = I2C_DUTYCYCLE_2;
heval_I2c.Init.OwnAddress1 = 0;
heval_I2c.Init.AddressingMode= I2C_ADDRESSINGMODE_7BIT;
heval_I2c.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;
heval_I2c.Init.OwnAddress2 = 0;
heval_I2c.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED;
heval_I2c.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED;
/* Init the I2C */
I2Cx_MspInit();
HAL_I2C_Init(&heval_I2c);
}
}
void Delayiic()
{
unsigned int i;
for(i=0;i<500000;i++);
}
void EEPROM_WriteByte(uint16_t addr,uint8_t dat)
{
HAL_I2C_Mem_Write(&heval_I2c,0xA0,addr,I2C_MEMADD_SIZE_8BIT,&dat,1,1000);
Delayiic();
}
uint8_t EEPROM_ReadByte(uint16_t addr)
{
uint8_t dat;
HAL_I2C_Mem_Read(&heval_I2c, 0xA0, addr, I2C_MEMADD_SIZE_8BIT, &dat, 1,1000);
Delayiic();
return dat;
}
void TestIIC(void)
{
unsigned int i=0;
tmp12= HAL_I2C_IsDeviceReady(&heval_I2c,0xA0,3000,1000);//检查器件准备好
for(i=0;i<100;i++)
EEPROM_WriteByte(i,0x77);
for(i=0;i<100;i++)
{
IIC_DAT=EEPROM_ReadByte(i);
if(IIC_DAT!=0x77)
err++;
}
while(1);
}
经过测试,读写极不稳定,有时候对,有时候不对。
坛子里有用HAL库IIC的吗,或者版主来一下,帮忙解决一下
本帖最后由 yyblike-263448 于 2015-5-14 08:58 编辑
看了大家在写的时候是一个字节一个字节的写,按照EEPROM的写要求,写数据需要5ms的延时,那么我写200个字节的硬件延时就1s了,我的方法是这样的,能正常写数据。初始化和读直接调用的库。每次跨页的时候才有一个5ms的写周期延时。
void I2C2_WriteBuff16(uint8_t deviceAddr,uint16_t writeAddr,uint8_t *pData,uint8_t size)
{
uint8_t temp;
if (HAL_I2C_Mem_Write(&hi2c2,deviceAddr,writeAddr,I2C_MEMADD_SIZE_16BIT,pData,size,I2C_TIMEOUT)!= HAL_OK)
{}
while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY);
}
/* EEPROM写数据 */
void EE_WriteBuff(uint8_t deviceAddr,uint16_t writeAddr,uint8_t *pData,uint8_t size)
{
uint8_t index;
uint8_t temp1,temp2,temp3;
uint16_t addrTemp = writeAddr;
temp1 = EE_PAGE_SIZE - writeAddr % EE_PAGE_SIZE;
if(size > temp1) //写数据超过当前页能写数据
{
temp2 = (size-temp1) / EE_PAGE_SIZE; //整页数
temp3 = (size-temp1) % EE_PAGE_SIZE; //最后页写字节数
}
else //写数据不跨页
{
temp1 = size; //单页
temp2 = 0;
temp3 = 0;
}
if(temp1) //写开始页
{
I2C2_WriteBuff16(deviceAddr,addrTemp,pData,temp1);
pData = pData+temp1; //数据指针偏移
addrTemp += temp1;
DelayMs(8); //必须,5ms写周期,否则写出错
}
if(temp2) //写整数页
{
for(index = 0;index<temp2;index++)
{
I2C2_WriteBuff16(deviceAddr,addrTemp,pData,EE_PAGE_SIZE);
pData = pData+EE_PAGE_SIZE;
addrTemp += EE_PAGE_SIZE;
DelayMs(8);
}
}
if(temp3) //写最后剩余数据
{
I2C2_WriteBuff16(deviceAddr,addrTemp,pData,temp3);
DelayMs(8);
}
}
我写正常,就是读多字节的时候不太正常:L 楼上的能否分享一下你的代码,我只需要一个一个读出来就可以, 写的时候只能一个个字节写,每写完一个延时一下,请懂的指正
for(i=0;i<10;i++)
{
USART6_RXD_Buffer=0x01+i;
HAL_I2C_Mem_Write(&hi2c1,0xa0,100+i,I2C_MEMADD_SIZE_8BIT,&USART6_RXD_Buffer,1,100);
HAL_Delay(4);
}
:L:Q我也正在调试 是的,我发现,延时很重要,不延时的时候一次都不对
,高手进来解释一下 再次顶起,看是否有人弄好的,难道HAL库没解决以前IIC硬件上总线占用的问题吗 解决了
HAL_StatusTypeDef EEPROM_WriteData(uint16_t MemAddress, uint8_t *pData, uint16_t Size)
{
uint16_t i;
HAL_StatusTypeDef sta;
for(i=0;i<Size;i++)
{
MemAddress+=i;
sta=HAL_I2C_Mem_Write(&hi2c1, 0xa0, MemAddress,I2C_MEMADD_SIZE_8BIT, &pData, 1, 200);
if(sta!=HAL_OK)return sta;
Delay(5000);
}
return sta;
}
HAL_StatusTypeDef EEPROM_ReadData(uint16_t MemAddress, uint8_t *pData, uint16_t Size)
{
uint16_t i;
HAL_StatusTypeDef sta;
for(i=0;i<Size;i++)
{
MemAddress+=i;
sta=HAL_I2C_Mem_Read(&hi2c1, 0xa0, MemAddress,I2C_MEMADD_SIZE_8BIT, &pData, 1, 200);
if(sta!=HAL_OK)return sta;
Delay(4000);
}
return sta;
}
还是那样,读与写必须一个一个字节地来,不知道这个CubeMX神马意思,还是咱位理解有误。
另外延时很重要,自带的HAL_Delay的延时函数一定要慎用,用不好会死机,只能自编一个延时函数了,会用HAL_Delay告诉一声,因为我发现只要在主程序初始化的时候调用HAL_Delay会死机,应该是什么东西没准备好 要启动SysTick后才可以使用HAL_Delay,HAL_Delay带有一个全局变量去计时就在systick 里面 最近也打算玩玩硬件IIC,谢谢楼主分享 学习中!:)