STM32
直播中

吕钢格

8年用户 994经验值
私信 关注
[问答]

基于HAL库在FreeRTOS调度器启动后I2C1不能正常读取的原因?怎么解决?

已经实验过,不开启调度器,I2C1能正常读取数据,一开启就返回错误HAL_ERROR!在线等帮忙,很急。I2C1配置如下:
void MX_I2C1_Init(void)
{

  hi2c1.Instance = I2C1;
  hi2c1.Init.timing = 0x00501E6C;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init( hi2c1) != HAL_OK)
  {
    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();
  }
}

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 clock enable */
    __HAL_RCC_I2C1_CLK_ENABLE();
    /**I2C1 GPIO Configuration   
    PB8     ------> I2C1_SCL
    PB9     ------> 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_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOB,  GPIO_InitStruct);


  /* USER CODE BEGIN I2C1_MspInit 1 */

  /* 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 Configuration   
    PB8     ------> I2C1_SCL
    PB9     ------> I2C1_SDA
    */
    HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8|GPIO_PIN_9);

  /* USER CODE BEGIN I2C1_MspDeInit 1 */

  /* USER CODE END I2C1_MspDeInit 1 */
  }
}


回帖(2)

江皎

2024-4-7 16:43:34
楼主可以看一次是不是systicks中断没有对hal用到的计数器进行增加操作。
举报

孙成红

2024-4-7 16:59:32
在FreeRTOS启动后,I2C1无法正常读取的原因可能是调度器的任务优先级或任务间的竞争条件导致I2C1资源无法正常访问。

为了解决这个问题,可以尝试下列方法:

1. 在FreeRTOS任务中禁用/启用调度器:在访问I2C1之前禁用调度器,完成I2C1操作后再启用调度器。这样可以确保I2C1在操作期间不被其他任务打断。

2. 调整任务优先级:如果I2C1操作被其他优先级较高的任务打断,可以调整任务的优先级,确保I2C1任务具有更高的优先级。

3. 使用信号量或互斥量:使用FreeRTOS的信号量或互斥量机制,确保只有一个任务能够访问I2C1资源,其他任务需要等待资源可用时再访问。

下面是一个示例代码,演示如何在读取I2C1之前禁用/启用调度器:

```
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"

SemaphoreHandle_t i2cSemaphore;

void I2C1_Read_Task(void *pvParameters) {
  while (1) {
    // 等待I2C1资源可用
    if (xSemaphoreTake(i2cSemaphore, portMAX_DELAY) == pdTRUE) {
      // 禁用调度器
      vTaskSuspendAll();

      // 执行I2C1读操作

      // 启用调度器
      xTaskResumeAll();

      // 释放I2C1资源
      xSemaphoreGive(i2cSemaphore);
    }

    vTaskDelay(pdMS_TO_TICKS(100));
  }
}

void HAL_I2C1_ErrorCallback(I2C_HandleTypeDef *hi2c) {
  // 处理I2C1错误
}

int main(void) {
  // 初始化信号量
  i2cSemaphore = xSemaphoreCreateMutex();

  // 创建I2C1读取任务
  xTaskCreate(I2C1_Read_Task, "I2C1_Read_Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL);

  // 启动FreeRTOS调度器
  vTaskStartScheduler();

  while (1) {
    // 不能到达这里
  }

  return 0;
}
```

在上述示例中,`I2C1_Read_Task`是一个任务,它通过获取`i2cSemaphore`来请求I2C1资源的访问。在访问I2C1之前,调度器被禁用,以确保I2C1的操作不会被其他任务打断。完成I2C1操作后,调度器被重新启用,并释放I2C1资源,以便其他任务可以访问。

请注意,示例代码中的`HAL_I2C1_ErrorCallback`函数用于处理I2C1的错误。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分