总结一下首次使用HAL库STM32f030硬件IIC从机中断收发

您所在的位置:网站首页 i2c从机接收数据 总结一下首次使用HAL库STM32f030硬件IIC从机中断收发

总结一下首次使用HAL库STM32f030硬件IIC从机中断收发

2023-11-17 14:45| 来源: 网络整理| 查看: 265

首先IIC的概念就略过了。这个网上写的很详细。 从CUBEMX配置完代码开始吧。

手上的项目是一主机,七个从机,从机使用中段收发。 关于地址是一个大坑,后续的读写中断也是个坑。

从机地址: 硬件为I2C_ADDRESSINGMODE_7BIT时的从机地址时,从机的地址需要左移一位,最低为表示读或者写。比如从机地址I2COwnAddr = 0x0A,左移一位配置为: hi2c1.Init.OwnAddress1 = I2COwnAddr Error_Handler(); } /** Configure Analogue filter */ if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) { Error_Handler(); } /** Configure Digital filter */ if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN I2C1_Init 2 */ #ifndef MASTER // HAL_I2C_Slave_Receive_IT(&hi2c1, I2CBuf_RxData, sizeof(I2CBuf_RxData)); // 启动中断接收 HAL_I2C_Slave_Transmit_IT(&hi2c1, I2CBuf_TxData, sizeof(I2CBuf_TxData)); // 启动中断发送 // HAL_I2C_EnableListen_IT(&hi2c1); #endif /* USER CODE END I2C1_Init 2 */ }

然后主机的地址可以忽略,在主机中读取从机的数据,地址需要时从机地址左移一位与上1: //查询读取从机6个字节数据,从机地址为0X0A HAL_I2C_Master_Receive(&hi2c1,(0X0A if(hi2c->Instance == I2C1) { //PROGRESS READ DATA//SET Static Value if(I2CBuf_RxData[0] == I2CBuf_RxData[1]) { //处理数据 } memset(I2CBuf_RxData,0,sizeof(I2CBuf_RxData)); HAL_I2C_Slave_Receive_IT(hi2c, I2CBuf_RxData, sizeof(I2CBuf_RxData)); } }

当然终端还需要一个错误处理函数。总线很容易锁定。

void HAL_I2C_ErrorCallback(I2C_HandleTypeDef *hi2c) { if(hi2c->Instance == I2C1) { ResetFlag = 1; memset(I2CBuf_RxData,0,sizeof(I2CBuf_RxData)); HAL_I2C_DeInit(hi2c); MX_I2C1_Init(); // HAL_I2C_Slave_Receive_IT(hi2c, I2CBuf_RxData, sizeof(I2CBuf_RxData)); HAL_I2C_Slave_Transmit_IT(&hi2c1, I2CBuf_TxData, sizeof(I2CBuf_TxData)); // 启动中断发送 } }

锁定之后需要总线复位,这里参考网上的改了一点,效果不错。

void HAL_I2C_MspInit(I2C_HandleTypeDef* i2cHandle) { GPIO_InitTypeDef GPIO_InitStruct = {0}; if(i2cHandle->Instance==I2C1) { /* USER CODE BEGIN I2C1_MspInit 0 */ /* USER CODE END I2C1_MspInit 0 */ /* I2C1 clock enable */ __HAL_RCC_I2C1_CLK_ENABLE();//放到了前面 __HAL_RCC_GPIOB_CLK_ENABLE(); //初始化引脚拉高拉低,复位IIC GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6|GPIO_PIN_7, GPIO_PIN_SET); i2cHandle->Instance->CR1 = I2C_CR1_SWRST; //复位I2C i2cHandle->Instance->CR1 = 0; //解除复位 /**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_HIGH; GPIO_InitStruct.Alternate = GPIO_AF1_I2C1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* I2C1 interrupt Init */ HAL_NVIC_SetPriority(I2C1_IRQn, 0, 0); HAL_NVIC_EnableIRQ(I2C1_IRQn); /* USER CODE BEGIN I2C1_MspInit 1 */ /* USER CODE END I2C1_MspInit 1 */ } }

应该没有了吧,调了这么多天,总结一下做个笔记,希望能帮到你。

对了,还看到使用地址中断,在地址回调函数里面判断收发,在调用对应函数的,可以同时中断收发,地址在下面,写的很详细

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) { } } } ———————————————— 版权声明:本文为CSDN博主「@残梦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_36561846/article/details/117474070


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3