stm32f103的硬件IIC探究总结了下

从入门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,有兴趣可以看一下

  • 5
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F103是一款基于ARM Cortex-M3内核的微控制器,具备硬件IIC(Inter-Integrated Circuit)功能,可以实现主从设备之间的通信。 硬件IIC通信是一种串行通信协议,通常用于短距离的设备之间的通信。它需要两根信号线:SDA(数据线)和SCL(时钟线)。在IIC通信中,一个设备充当主设备,控制整个通信的进行,而其他设备则充当从设备,等待主设备的命令。 在STM32F103中,可以通过配置相关寄存器和使用相应的库函数来实现IIC通信。作为主设备,我们需要首先初始化IIC总线,并设置相应的通信速率。然后,我们可以通过发送起始信号、选择从设备地址和读写操作来与从设备进行通信。通信过程中,主设备可以通过发送或接收数据来完成数据的传输。 作为从设备,我们首先需要等待主设备选择我们的地址。当地址匹配时,我们可以通过拉低SDA线来发送应答信号,表示已经准备好进行通信。在收到数据后,我们可以发送应答信号,告知主设备数据已经接收完毕。 硬件IIC通信是一种简单、高效的通信方式,适用于需要短距离、低速率的设备之间的通信。在使用STM32F103进行硬件IIC主从通信时,我们需要合理配置主设备和从设备的相关参数,并遵循IIC通信的协议来进行通信。 总之,STM32F103通过硬件IIC功能,可以实现主从设备之间的通信。通过合适的配置和使用相应的库函数,我们可以轻松地实现IIC通信,并实现数据的传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值