STM32 HAL库 硬件IIC 从机一些问题整理

一、从机双地址,在回调函数中获取主机访问的地址:

void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
    uint16_t slaveaddrcode     = I2C_GET_ADDR_MATCH(I2cHandle);
    printf("R:%d\r\n",slaveaddrcode);
}

二、如果用地址回调函数HAL_I2C_AddrCallback(),这个回调函数触发后,会关闭中断,需要再次开启中断,才能继续监听。需要特别注意开启监听中断的位置,有人在这个回调函数里直接开启,我测试了一下,不行,开启失败;还有人,把开启监听放在主循环里,一直不断轮询去开启,大力出奇迹,这样确实可以用,但是经过测试发现有时候会丢失,不能触发回调函数。直到看到这篇文章,在HAL_I2C_ListenCpltCallback()函数中开启,才是最优解。

void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
  if(TransferDirection == I2C_DIRECTION_TRANSMIT)
  {

	// if(HAL_I2C_Slave_Seq_Receive_IT(&hi2c1, i2c.RxData, sizeof(i2c.RxData), I2C_FIRST_FRAME) != HAL_OK)
	// {

	// }	  
	  
  }
  else if(TransferDirection == I2C_DIRECTION_RECEIVE)
  {
	// if(HAL_I2C_Slave_Seq_Transmit_IT(&hi2c1, i2c.TxData, sizeof(i2c.TxData), I2C_LAST_FRAME)!= HAL_OK)
	// {
		
	// }  
  }
  //HAL_I2C_EnableListen_IT(hi2c);//在这里启动监听会失败,没有用
  
}
// 侦听完成回调函数(完成一次完整的i2c通信以后会进入该函数)
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
  // 完成一次通信,清除状态
//   first_byte_state = 1;
//   offset = 0;
  HAL_I2C_EnableListen_IT(hi2c); // slave is ready again
}

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32 HAL库可以用于实现I2C从机功能。以下是使用STM32 HAL库实现I2C从机的步骤: 1. 初始化I2C外设和GPIO引脚,配置I2C从机地址和中断(如果需要)。 2. 在I2C的回调函数中实现从机接收和发送数据的逻辑。可以使用HAL_I2C_Slave_Receive和HAL_I2C_Slave_Transmit函数来接收和发送数据。 3. 在主函数中调用HAL_I2C_EnableListen_IT函数以启用I2C从机监听模式,等待主机发起读写操作。 4. 在I2C从机接收到数据时,可以使用HAL_I2C_AddrCallback函数处理主机发送过来的地址,并根据需要选择执行相应的操作。 5. 在I2C从机发送数据时,可以使用HAL_I2C_SlaveTxCpltCallback函数处理发送完成事件。 下面是一个简单的示例代码,演示了如何使用STM32 HAL库实现I2C从机: ```c #include "stm32f4xx_hal.h" #define SLAVE_ADDRESS 0x50 I2C_HandleTypeDef hi2c1; void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(i2cHandle->Instance==I2C1) { /* GPIO clock enable */ __HAL_RCC_GPIOB_CLK_ENABLE(); /* I2C clock enable */ __HAL_RCC_I2C1_CLK_ENABLE(); /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL PB7 ------> I2C1_SDA */ GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_OD; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF4_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* I2C1 interrupt Init */ HAL_NVIC_SetPriority(I2C1_EV_IRQn, 0, 0); HAL_NVIC_EnableIRQ(I2C1_EV_IRQn); } } void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle) { if(i2cHandle->Instance==I2C1) { /* Peripheral clock disable */ __HAL_RCC_I2C1_CLK_DISABLE(); /**I2C1 GPIO Configuration PB6 ------> I2C1_SCL PB7 ------> I2C1_SDA */ HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7); /* I2C1 interrupt Deinit */ HAL_NVIC_DisableIRQ(I2C1_EV_IRQn); } } void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode) { if (TransferDirection == I2C_DIRECTION_RECEIVE) { // Receive data from master uint8_t data[2]; HAL_I2C_Slave_Receive(&hi2c1, data, 2, HAL_MAX_DELAY); // Process received data // ... } else if (TransferDirection == I2C_DIRECTION_TRANSMIT) { // Send data to master uint8_t data[2] = {0x01, 0x02}; HAL_I2C_Slave_Transmit(&hi2c1, data, 2, HAL_MAX_DELAY); } } void HAL_I2C_SlaveTxCpltCallback(I2C_HandleTypeDef *hi2c) { // Data has been transmitted successfully } int main(void) { HAL_Init(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 400000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = SLAVE_ADDRESS << 1; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } HAL_I2C_EnableListen_IT(&hi2c1); while (1) { // Wait for interrupt __WFI(); } } void I2C1_EV_IRQHandler(void) { HAL_I2C_EV_IRQHandler(&hi2c1); } ``` 该代码实现了一个I2C从机,监听地址为0x50。在I2C_AddrCallback函数中,从机会接收主机发送过来的数据,并根据需要执行相应的操作。在I2C_SlaveTxCpltCallback函数中,从机会发送数据给主机。 在主函数中,首先初始化I2C外设和GPIO引脚,并启用I2C从机监听模式。然后等待中断触发,等待主机发起读写操作。在中断中处理从机接收和发送数据的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值