您的位置:首页 > 财经 > 产业 > stm32 IIC总线busy解决方法

stm32 IIC总线busy解决方法

2024/12/23 12:02:34 来源:https://blog.csdn.net/yrx020307/article/details/142170068  浏览:    关键词:stm32 IIC总线busy解决方法

参考博客:
https://blog.csdn.net/PP_hui/article/details/112229696

1------这是IIC的初始化代码:

#include "i2c.h"/* USER CODE BEGIN 0 */
// #define __HAL_AFIO_REMAP_I2C1_ENABLE()  AFIO_REMAP_ENABLE(AFIO_MAPR_I2C1_REMAP)
/* USER CODE END 0 */I2C_HandleTypeDef hi2c1;/* I2C1 init function */
void MX_I2C1_Init(void)
{hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 100000;hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;// hi2c1.Init.OwnAddress1 = 0;hi2c1.Init.OwnAddress1 = 0xA0;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();}}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 */__HAL_RCC_GPIOB_CLK_ENABLE();/**I2C1 GPIO ConfigurationPB8     ------> I2C1_SCLPB9     ------> I2C1_SDA*/GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;GPIO_InitStruct.Pull = GPIO_PULLUP;/GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);// __HAL_AFIO_REMAP_I2C1_ENABLE();/* I2C1 clock enable */__HAL_RCC_I2C1_CLK_ENABLE();/* USER CODE BEGIN I2C1_MspInit 1 */__I2C1_FORCE_RESET();                                   //通过总复位模块对I2C一次复位操作__I2C1_RELEASE_RESET();/* USER CODE END I2C1_MspInit 1 */}
}void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{if(i2cHandle->Instance==I2C1){/* USER CODE BEGIN I2C1_MspDeInit 0 *//* USER CODE END I2C1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_I2C1_CLK_DISABLE();/**I2C1 GPIO ConfigurationPB8     ------> I2C1_SCLPB9     ------> I2C1_SDA*/HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);/* USER CODE BEGIN I2C1_MspDeInit 1 *//* USER CODE END I2C1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */

我根据参考的博客在 HAL_I2C_MspInit() 中添加了2行代码;
目的是进行一次IIC 总线的复位操作;
在这里插入图片描述

2---------除此之外还定义了一个接口:
作用:判断IIC总线是否busy,如果busy,则重新初始化IIC;
在这里插入图片描述

void I2C_Busy_C(void)
{SET_BIT(hi2c1.Instance->CR1,I2C_CR1_SWRST);          CLEAR_BIT(hi2c1.Instance->CR1,I2C_CR1_SWRST);HAL_I2C_MspInit(&hi2c1);                      //自定义函数HAL_I2C_Init(&hi2c1);}

3----在HAL_I2C_Mem_Write()时会busy,
解决方案:
调用HAL_I2C_Mem_Write()之前,先判断是否busy,如果busy则重新初始化,初始化结束后,再HAL_I2C_Mem_Write();
在这里插入图片描述

EEPROM_RES EEProm_Write(uint8_t addr,uint8_t* data,uint8_t size)
{int ret = 0;if(READ_BIT(hi2c1.Instance->SR2,I2C_SR2_BUSY) || READ_BIT(hi2c1.Instance->CR1,I2C_CR1_PE) == 0){I2C_Busy_C();}ret = HAL_I2C_Mem_Write(&hi2c1,EEPROM_ADDR,addr,I2C_MEMADD_SIZE_8BIT,data,size,1000);if(HAL_OK == ret){HAL_UART_Transmit(&huart3,"EEPROM_OK\r\n", strlen("EEPROM_OK\r\n"),100);return EEPROM_OK;}else if(HAL_ERROR == ret){HAL_UART_Transmit(&huart3,"EEPROM_ERROR\r\n", strlen("EEPROM_ERROR\r\n"),100);return EEPROM_ERROR;}else if(HAL_BUSY == ret){HAL_UART_Transmit(&huart3,"HAL_BUSY\r\n", strlen("HAL_BUSY\r\n"),100);return HAL_BUSY;}else if(HAL_TIMEOUT == ret){HAL_UART_Transmit(&huart3,"HAL_TIMEOUT\r\n", strlen("HAL_TIMEOUT\r\n"),100);return HAL_TIMEOUT;}}

总结:
1)修改MX_I2C1_Init();
2)创建重新初始化的接口I2C_Busy_C();
3) 在HAL_I2C_Mem_Write()之前,先判断是否busy,如果busy就调用I2C_Busy_C();复位总线;-------------->再调用HAL_I2C_Mem_Write();
没了;

下面的代码是AT24C02的所有相关代码:
1)iic初始化

#include "i2c.h"/* USER CODE BEGIN 0 */
// #define __HAL_AFIO_REMAP_I2C1_ENABLE()  AFIO_REMAP_ENABLE(AFIO_MAPR_I2C1_REMAP)
/* USER CODE END 0 */I2C_HandleTypeDef hi2c1;/* I2C1 init function */
void MX_I2C1_Init(void)
{hi2c1.Instance = I2C1;hi2c1.Init.ClockSpeed = 100000;hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;// hi2c1.Init.OwnAddress1 = 0;hi2c1.Init.OwnAddress1 = 0xA0;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();}}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 */__HAL_RCC_GPIOB_CLK_ENABLE();/**I2C1 GPIO ConfigurationPB8     ------> I2C1_SCLPB9     ------> I2C1_SDA*/GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;GPIO_InitStruct.Pull = GPIO_PULLUP;/GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);// __HAL_AFIO_REMAP_I2C1_ENABLE();/* I2C1 clock enable */__HAL_RCC_I2C1_CLK_ENABLE();/* USER CODE BEGIN I2C1_MspInit 1 */__I2C1_FORCE_RESET();                                   //通过总复位模块对I2C一次复位操作__I2C1_RELEASE_RESET();/* USER CODE END I2C1_MspInit 1 */}
}void HAL_I2C_MspDeInit(I2C_HandleTypeDef* i2cHandle)
{if(i2cHandle->Instance==I2C1){/* USER CODE BEGIN I2C1_MspDeInit 0 *//* USER CODE END I2C1_MspDeInit 0 *//* Peripheral clock disable */__HAL_RCC_I2C1_CLK_DISABLE();/**I2C1 GPIO ConfigurationPB8     ------> I2C1_SCLPB9     ------> I2C1_SDA*/HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);/* USER CODE BEGIN I2C1_MspDeInit 1 *//* USER CODE END I2C1_MspDeInit 1 */}
}/* USER CODE BEGIN 1 */

2)main函数调用MX_I2C1_Init();
在这里插入图片描述
3)at24c02.h

#ifndef AT24C02_H
#define AT24C02_H
#include "stm32f4xx_hal.h"
#include "usart.h"typedef enum{EEPROM_OK,EEPROM_ERROR
}EEPROM_RES;extern I2C_HandleTypeDef hi2c1;//AT24C02一共32页,每页8字节,共256字节;
//不能跨页写数据[比如:1个2字节的数据占用0x07和0x08两个地址,可能导致数据错乱]//第一页地址:0x00-0x07
//第二页地址:0x08-0x0F
//第三页地址:0x10-0x17
//第四页地址:0x18-0x1F
//第五页地址:0x20-0x27
//第六页地址:0x28-0x2F
//第七页地址:0x30-0x37
//第八页地址:0x38-0x3F
//第九页地址:0x40-0x47
//第十页地址:0x48-0x4F
//第十一页地址:0x50-0x57
//第十二页地址:0x58-0x5F
//第十三页地址:0x60-0x67
//第十四页地址:0x68-0x6F
//第十五页地址:0x70-0x77
//第十六页地址:0x78-0x7F
//第十七页地址:0x80-0x87
//第十八页地址:0x88-0x8F
//第十九页地址:0x90-0x97
//第二十页地址:0x98-0x9F
//第二十一页地址:0xA0-0xA7
//第二十二页地址:0xA8-0xAF
//第二十三页地址:0xB0-0xB7
//第二十四页地址:0xB8-0xBF
//第二十五页地址:0xC0-0xC7
//第二十六页地址:0xC8-0xCF
//第二十七页地址:0xD0-0xD7
//第二十八页地址:0xD8-0xDF
//第二十九页地址:0xE0-0xE7
//第三十页地址:0xE8-0xEF
//第三十一页地址:0xF0-0xF7
//第三十二页地址:0xF8-0xFF//由于各个参数的实际大小是不确定的,领导每明确要求;所以统一把长度设置为4字节
typedef enum{E2ADDR_X_STEP=0x00,//X轴步进【0x00-0x03】E2ADDR_Y_STEP=0x04,//Y轴步进【0x04-0x07】E2ADDR_Z_STEP=0x08,//Z轴步进【0x08-0x0B】E2ADDR_X_POS=0x0C,//X轴位置【0x0C-0x0F】E2ADDR_Y_POS=0x10,//Y轴位置【0x10-0x13】E2ADDR_Z_POS=0x14,//Z轴位置【0x14-0x17】E2ADDR_X_SPEED=0x18,//X轴运行速度【0x18-0x1B】E2ADDR_Y_SPEED=0x1C,//Y轴运行速度【0x1C-0x1F】E2ADDR_Z_SPEED=0x20,//Z轴运行速度【0x20-0x23】E2ADDR_X_ACC=0x24,//X轴运行加速度【0x24-0x27】E2ADDR_Y_ACC=0x28,//Y轴运行加速度【0x28-0x2B】E2ADDR_Z_ACC=0x2C,//Z轴运行加速度【0x2C-0x2F】E2ADDR_X_CHECKSELF_SPEED = 0x30,//X轴自检速度【0x30-0x33】E2ADDR_Y_CHECKSELF_SPEED = 	0x34,//Y轴自检速度【0x34-0x37】E2ADDR_Z_CHECKSELF_SPEED = 	0x38,//Z轴自检速度【0x38-0x3B】E2ADDR_X_CHECKSELF_ACC = 0x3C,//X轴自检加速度【0x3C-0x3F】E2ADDR_Y_CHECKSELF_ACC = 	0x40,//Y轴自检加速度【0x40-0x43】E2ADDR_Z_CHECKSELF_ACC = 	0x44,//Z轴自检加速度【0x44-0x47】
}AT24C02_APP_ADDR;#define PARAMNULL		0xFFFFFFFF
#define USER_PARAM_NULL(TYPE,PARAM,VALUE)   ((TYPE)PARAMNULL == PARAM)?(PARAM = VALUE):(PARAM);
#define EE_SIZE 256//bytes
#define EEPROM_ADDR		0xa0
struct Device_Param{int32_t step;int32_t pos;int32_t speed;int32_t acc;int32_t check_speed;int32_t check_acc;
};void AT24C02_Read_Test(void);
void AT24C02_Write_Test(void);
void I2c_EraseChip(void);
#endif

4)at24c02.c

#include "AT24C02.h"
void I2C_Busy_C(void)
{SET_BIT(hi2c1.Instance->CR1,I2C_CR1_SWRST);          CLEAR_BIT(hi2c1.Instance->CR1,I2C_CR1_SWRST);HAL_I2C_MspInit(&hi2c1);                      //自定义函数HAL_I2C_Init(&hi2c1);}// ————————————————//                             版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。// 原文链接:https://blog.csdn.net/PP_hui/article/details/112229696EEPROM_RES EEProm_Write(uint8_t addr,uint8_t* data,uint8_t size)
{int ret = 0;if(READ_BIT(hi2c1.Instance->SR2,I2C_SR2_BUSY) || READ_BIT(hi2c1.Instance->CR1,I2C_CR1_PE) == 0){I2C_Busy_C();}ret = HAL_I2C_Mem_Write(&hi2c1,EEPROM_ADDR,addr,I2C_MEMADD_SIZE_8BIT,data,size,1000);if(HAL_OK == ret){HAL_UART_Transmit(&huart3,"EEPROM_OK\r\n", strlen("EEPROM_OK\r\n"),100);return EEPROM_OK;}else if(HAL_ERROR == ret){HAL_UART_Transmit(&huart3,"EEPROM_ERROR\r\n", strlen("EEPROM_ERROR\r\n"),100);return EEPROM_ERROR;}else if(HAL_BUSY == ret){HAL_UART_Transmit(&huart3,"HAL_BUSY\r\n", strlen("HAL_BUSY\r\n"),100);return HAL_BUSY;}else if(HAL_TIMEOUT == ret){HAL_UART_Transmit(&huart3,"HAL_TIMEOUT\r\n", strlen("HAL_TIMEOUT\r\n"),100);return HAL_TIMEOUT;}}
EEPROM_RES EEProm_Read(uint8_t addr,uint8_t *buf,uint16_t size)
{if(HAL_OK != HAL_I2C_Mem_Read(&hi2c1,EEPROM_ADDR,addr,I2C_MEMADD_SIZE_8BIT,buf,size,1000)){HAL_UART_Transmit(&huart3,"EEPROM_ERROR\r\n", strlen("EEPROM_ERROR\r\n"),100);return EEPROM_ERROR;}HAL_Delay(10);HAL_UART_Transmit(&huart3,"EEPROM_OK\r\n", strlen("EEPROM_OK\r\n"),100);return EEPROM_OK;
}void I2c_EraseChip(void)
{uint16_t i=0;uint8_t erase[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};HAL_UART_Transmit(&huart3,"will erase chip\r\n", strlen("will erase chip\r\n"),100);for( i=0; i<(EE_SIZE/8); i++){if(HAL_OK != HAL_I2C_Mem_Write(&hi2c1, EEPROM_ADDR, i*8,I2C_MEMADD_SIZE_8BIT, erase, 8, 1000)){Error_Handler();HAL_UART_Transmit(&huart3,"EEPROM_ERROR\r\n", strlen("EEPROM_ERROR\r\n"),100);}else{HAL_UART_Transmit(&huart3,"EEPROM_OK\r\n", strlen("EEPROM_OK\r\n"),100);}HAL_Delay(10);}
}// void Platform_Init(void)
// {
//     //读取EEPROM存储的数据
//     EEProm_Read(E2_JPB_LEFT,(uint8_t*)at24c02_data_4byte,4);
//     EEProm_Read(E2_JPB_RIGHT,(uint8_t*)at24c02_data_4byte,4);
//     EEProm_Read(E2_LIGHTSWITCH,(uint8_t*)&at24c02_data_1byte,1);
//     EEProm_Read(E2_LIGHTBRIGHTNESS,(uint8_t*)&at24c02_data_1byte,1);
//     EEProm_Read(E2_LIGHTBOOTVALUE,(uint8_t*)&at24c02_data_1byte,1);//     EEProm_Read(E2_ZOOM_POSLIMIT,(uint8_t*)&at24c02_data_4byte,4);
//     EEProm_Read(E2_ZOOM_POSZERO,(uint8_t*)&at24c02_data_4byte,4);
//     EEProm_Read(E2_ZOOM_SPEEDSELFTEST,(uint8_t*)&at24c02_data_2byte,2);
//     EEProm_Read(E2_ZOOM_SPEEDRUN,(uint8_t*)&at24c02_data_2byte,2);
//     EEProm_Read(E2_ZOOM_STEP,(uint8_t*)&at24c02_data_2byte,2);//     EEProm_Read(E2_Z_POSLIMIT,(uint8_t*)&at24c02_data_4byte,4);
//     EEProm_Read(E2_Z_POSZERO,(uint8_t*)&at24c02_data_4byte,4);
//     EEProm_Read(E2_Z_SPEEDSELFTEST,(uint8_t*)&at24c02_data_2byte,2);
//     EEProm_Read(E2_Z_SPEEDRUN,(uint8_t*)&at24c02_data_2byte,2);
//     EEProm_Read(E2_Z_STEP,(uint8_t*)&at24c02_data_2byte,2);// }int32_t XPosition = 0;
void param_init(void)
{USER_PARAM_NULL(int32_t,XPosition,0);
}struct Device_Param Device_XMotor = {.step = 0,.pos = 0,.speed = 0,.acc = 0,.check_speed = 0,.check_acc = 0};
void AT24C02_Write_Test(void)
{///E2ADDR_X_STEPint32_t ret=0;uint8_t debugData[30] = 0;Device_XMotor.step = 4;ret = EEProm_Write(E2ADDR_X_STEP,(uint8_t*)&Device_XMotor.step,4);sprintf(debugData,"\r\nSET E2ADDR_X_STEP=%d\r\n\r\n",ret);HAL_UART_Transmit(&huart3,debugData, strlen(debugData),100);
}void AT24C02_Read_Test(void)
{int32_t ret=0;uint8_t debugData[30] = 0;EEProm_Read(E2ADDR_X_STEP,(uint8_t*)&ret,4);sprintf(debugData,"\r\nE2ADDR_X_STEP=%d\r\n\r\n",ret);HAL_UART_Transmit(&huart3,debugData, strlen(debugData),100);
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com