从入门STM32就听说硬件IIC为了规避NXP的专利啥啥的设计的很难用,然后又说有BUG,就一直用的软件模拟的IIC,但是总是delay看了不顺眼,就想试试硬件iic到底有哪些问题;
通过一顿操作,调通了,不过网上说速率高就会出问题,然后被中断打断会出问题,会锁死在等event里等等,这里附上我的程序;
首先是初始化配置:
在main里面开了时钟然后调用
void moduleI2cInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
I2C_InitTypeDef I2C_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C ;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_ClockSpeed = 10000;
I2C_Init(I2C1, &I2C_InitStructure);
I2C_Cmd (I2C1,ENABLE);
}
接下来就是读写操作了,我这里是参照AT24C32写的,
uint8_t moduleI2cWrite(u16 addr,u8 dataValue)
{
uint32_t delay = 0;
I2C_GenerateSTART(I2C1,ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_SendData(I2C1,addr>>8);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_SendData(I2C1,addr&0xFF);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_SendData(I2C1,dataValue);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_GenerateSTOP(I2C1,ENABLE);
return SUCCESS;
}
uint8_t moduleI2cWritePage(u16 addr,u8 *dataValue,u8 num)
{
uint32_t delay = 0;
I2C_GenerateSTART(I2C1,ENABLE);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Transmitter);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_SendData(I2C1,addr>>8);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_SendData(I2C1,addr&0xFF);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
for(u8 i = 0;i < num;i++)
{
I2C_SendData(I2C1,dataValue[i]);
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
}
I2C_GenerateSTOP(I2C1,ENABLE);
return SUCCESS;
}
uint8_t moduleI2cRead(u8 *dataValue,u16 addr)
{
uint32_t delay = 0;
I2C_GenerateSTART(I2C1,ENABLE);//起始信号
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Transmitter);//发送设备地址+写信号
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_SendData(I2C1,addr>>8);//发送存储单元地址,从0开始
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_SendData(I2C1,addr&0xFF);//发送存储单元地址,从0开始
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_TRANSMITTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_GenerateSTART(I2C1,ENABLE);//起始信号
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_MODE_SELECT))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_Send7bitAddress(I2C1,HMC_ADDR,I2C_Direction_Receiver);//发送设备地址+读信号
while(!I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_AcknowledgeConfig(I2C1,DISABLE);
while(!(I2C_CheckEvent(I2C1,I2C_EVENT_MASTER_BYTE_RECEIVED)))
{
if(delay > 0x10000)
return ERROR;
delay++;
}
delay = 0;
I2C_GenerateSTOP(I2C1,ENABLE);
*dataValue = I2C_ReceiveData(I2C1);//读出寄存器数据
return SUCCESS;
}
总结起来一共四个API:
void moduleI2cInit(void);
u8 moduleI2cWrite(u16 addr,u8 dataValue);
u8 moduleI2cRead(u8 *dataValue,u16 addr);
u8 moduleI2cWritePage(u16 addr,u8 *dataValue,u8 num);
主要注意事项:读写之间需要短暂延时,估计是线没释放掉之类的原因吧。
放在桌子上自己跑了24小时以上没出啥问题。
跑得demo程序附在下面,接了串口1,通过助手1ms发数据(调试助手PC的1ms可能不准),不过也挺频繁的了,没有发现中断导致读写程序失败;
https://download.csdn.net/download/weixin_39081050/13977036,有兴趣可以看一下