STM32CubeMX USART--dma数据接收【1】--帧同步


前言

STM32CubeMX USART–dma数据接收【1】


一、CUBEMX配置

在这里插入图片描述
不用勾选usart的全局中断。

二、代码

1.main.c

进行dma的初始化

	HAL_UART_Receive_DMA(&huart4, rx_buffer_usart4, 6);//打开串口接收中断用于接收和发送陀螺仪的数据

2.接收函数

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) 
{

	if(huart->Instance == UART4)
	{
		
    // 检查帧头和帧尾
    if (rx_buffer_usart4[0] == 0xAA && rx_buffer_usart4[5] == 0xCC) 
		{
      uint32_t float_data_as_int = (rx_buffer_usart4[1] << 24) | (rx_buffer_usart4[2] << 16) | (rx_buffer_usart4[3] << 8) | rx_buffer_usart4[4];
      float data;
      memcpy(&data, &float_data_as_int, sizeof(float));
      // 在这里处理解析得到的 float 数据
      Yaw_angle = data;
    } 
		else 
		{
      // 如果帧头和帧尾不匹配,可以在这里添加错误处理逻辑
    }
    // 重新启动 DMA 接收
    HAL_UART_Receive_DMA(&huart4, rx_buffer_usart4, 6);//由于开启的是循环模式所以这个可以写
  }		
}

DMA额外讲解

DMA(Direct Memory Access)是一种硬件机制,允许外设(如 USART)直接与内存之间传输数据,而无需 CPU的干预。这样可以减轻 CPU 负担,提高数据传输的效率。
在使用 DMA 的情况下,当 USART 收到数据时,数据会自动通过 DMA 传输到内存缓冲区。在配置 DMA时,您可以选择数据传输的模式:普通模式和循环模式。
普通模式:当 DMA 接收到指定数量的数据后,DMA 传输会停止。在这种模式下,一旦 DMA 缓冲区被填满,DMA传输会自动停止,并触发中断。在回调函数中,您需要手动重新启动 DMA 接收。
循环模式:在循环模式下,DMA 在传输指定数量的数据后,会自动从头开始接收新的数据。当 DMA 缓冲区被填满时,将触发中断,但 DMA会自动继续接收新数据。
在您提供的代码中,由于您使用了循环模式(DMA_CIRCULAR),所以每次缓冲区满(接收到指定数量的数据)时,DMA 会触发中断并自动继续接收。在 HAL_UART_RxCpltCallback 函数中,您可以处理接收到的数据,然后重新启动 DMA 接收(在循环模式下,实际上不需要重新启动,因为 DMA 已经自动继续接收了)。
总之,使用 DMA 循环模式时,每次接收到指定数量的数据时,都会触发中断,并在回调函数中处理接收到的数据。

1示例:

在使用 DMA 循环模式时,有可能出现您提到的这种情况。如果数据流中发生了丢失或错误,导致帧头和帧尾不再与预期的缓冲区索引对齐,那么就会发生这种情况。为了解决这个问题,您可以在回调函数中实现一个简单的帧同步机制,以确保始终正确地处理帧头和帧尾。

uint8_t frame_sync = 0;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
  if (huart->Instance == USART2) {
    for (uint8_t i = 0; i < RX_BUFFER_SIZE_USART2 - 1; i++) {
      if (rx_buffer_usart2[i] == 0xAA && rx_buffer_usart2[i + 5] == 0xCC) {
        frame_sync = 1;
        uint32_t float_data_as_int = (rx_buffer_usart2[i + 1] << 24) | (rx_buffer_usart2[i + 2] << 16) | (rx_buffer_usart2[i + 3] << 8) | rx_buffer_usart2[i + 4];
        float data;
        memcpy(&data, &float_data_as_int, sizeof(float));
        // 在这里处理解析得到的 float 数据
        Yaw_angle = data;
        break;
      }
    }
    if (!frame_sync) {
      // 如果没有找到帧头和帧尾,可以在这里添加错误处理逻辑
    } else {
      frame_sync = 0;
    }
    // 重新启动 DMA 接收
    HAL_UART_Receive_DMA(&huart2, rx_buffer_usart2, RX_BUFFER_SIZE_USART2);
  }
}

在这个示例中,我们遍历整个缓冲区,寻找帧头和帧尾的正确位置。一旦找到正确的帧头和帧尾,我们就会解析其中的数据,并在下次回调中重置 frame_sync 标志。这样,即使数据不完全对齐,我们仍然可以找到正确的帧头和帧尾并处理数据。

需要注意的是,这个方法可能会降低性能,因为我们需要遍历整个缓冲区。但是,对于低速数据传输和较小的缓冲区来说,这种方法通常是可行的。您可以根据实际应用场景进行优化。

2示例:

确实有一种更优的方法来解决这个问题,那就是使用 DMA 的"半传输完成"(Half-Transfer Complete)中断。这样,当 DMA 完成一半的传输时,即缓冲区的前一半已经填充完毕,就会触发一个中断。然后,当 DMA 完成整个传输时,即缓冲区的后一半已经填充完毕,又会触发一个中断。这样,我们可以在每次中断中处理一半的缓冲区,从而保证不会丢失数据。

下面是如何使用 “半传输完成” 中断的示例:

  1. 首先,将缓冲区大小加倍(以便为半传输完成中断留出空间):
#define RX_BUFFER_SIZE_USART2 12
uint8_t rx_buffer_usart2[RX_BUFFER_SIZE_USART2];
  1. 在初始化 DMA 时,启用半传输完成中断:
// 启用半传输完成中断
__HAL_DMA_ENABLE_IT(&hdma_usart2_rx, DMA_IT_HT);
  1. 修改回调函数以处理半传输完成中断:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
  if (huart->Instance == USART2) {
    process_usart2_buffer(rx_buffer_usart2, 6);
  }
}

void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) {
  if (huart->Instance == USART2) {
    process_usart2_buffer(rx_buffer_usart2 + 6, 6);
  }
}

void process_usart2_buffer(uint8_t *buffer, uint16_t size) {
  // 检查帧头和帧尾
  if (buffer[0] == 0xAA && buffer[5] == 0xCC) {
    uint32_t float_data_as_int = (buffer[1] << 24) | (buffer[2] << 16) | (buffer[3] << 8) | buffer[4];
    float data;
    memcpy(&data, &float_data_as_int, sizeof(float));
    // 在这里处理解析得到的 float 数据
    Yaw_angle = data;
  } else {
    // 如果帧头和帧尾不匹配,可以在这里添加错误处理逻辑
    uint8_t found_header = 0;
    for (int i = 1; i < size; ++i) {
      if (buffer[i] == 0xAA) {
        found_header = 1;
        memmove(buffer, buffer + i, size - i);
        break;
      }
    }

    if (found_header) {
      // 重新启动 DMA 接收,但缩短接收数据的长度
      HAL_UART_AbortReceive(&huart2);
      HAL_UART_Receive_DMA(&huart2, buffer + (size - 1), 1);
    } else {
      // 帧头未找到,可以记录错误或执行其他操作
    }
  }
}

这个 process_usart2_buffer 函数会检查给定缓冲区的帧头和帧尾,如果找到,则处理数据。如果帧头和帧尾不匹配,它将尝试在缓冲区中找到下一个帧头,并调整 DMA 接收以适应新的帧头位置。这样,即使发生帧丢失,你的代码也可以尽快恢复到正确的帧同步状态。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: STM32CubeMX是一款用于STM32微控制器的图形化配置工具,可以方便地配置USART串口通信的中断接收功能。 要使用USART中断接收功能,需要先在STM32CubeMX中配置USART的相关参数,包括波特率、数据位、停止位、校验位等。然后,在代码中开启USART中断接收功能,并编写中断服务函数来处理接收到的数据。 在中断服务函数中,可以使用HAL库提供的函数来读取接收缓冲区中的数据,并进行相应的处理。例如,可以将接收到的数据存储到一个缓冲区中,或者根据接收到的数据执行相应的操作。 需要注意的是,在使用USART中断接收功能时,需要确保接收缓冲区的大小足够大,以避免数据丢失。同时,还需要注意处理接收错误和溢出等异常情况,以保证通信的可靠性。 ### 回答2: stm32cubemx是一款功能强大的工具,可帮助用户为STM32系列微控制器生成初始化代码和配置工程。在进行工程配置的时候,我们常常会使用USART通信。而USART中断接收功能非常常用,因此我们需要学会在stm32cubemx中配置USART中断接收。下面将详细介绍如何在stm32cubemx中使用USART中断接收。 1.配置USART 首先,在stm32cubemx中配置USART,需要选中串口接口,然后设置波特率、数据位、停止位、奇偶校验等参数。在配置中断接收之前,需要先完成这个步骤。 2.配置NVIC 通过stm32cubemx配置NVIC中断控制器,需要在“Configuration”选项卡中打开“NVIC Settings”,并选择需要开启的中断,即“USARTx_IRQn”。 3.配置中断 首先,我们需要在“Code Generation”选项卡中打开“USART1 Global Interrupt”和“USART1 Interrupts”按钮,然后在“USART1_IRQn”中的“User Code”中选择“Interrupts”选项卡。接着,我们在IRQn_Type类型定义下方输入“void USART1_IRQHandler(void) {“,这就表示我们要开始编写中断服务程序。 在编写中断服务程序时,我们需要首先检测接收中断是不是因为接收到了一个字符。如果是,我们可以将这个字符存入一个缓冲区,以便后续使用。同时,要及时清除所有的中断标志位,来避免反复触发中断,例如USART_SR_RXNE标志位。 4.处理接收数据 最后,在中断中完成全部的处理过程后,我们可以从缓冲区中取出接收到的字符,并对其进行相应的处理。例如,我们可以在主循环中不断地轮询缓冲区,读取缓冲区中的数据并进行分析。 总之,在stm32cubemx中使用USART中断接收需要分别配置USART、NVIC和中断服务程序,且要保证程序在中断处理完后及时清除所有的中断标志位,来避免反复触发中断。只有这样,在大规模的数据传输和处理中,才能保证程序的正常运行。 ### 回答3: STM32CubeMX是一款功能强大的软件工具,用于帮助开发者对STMicroelectronics公司的微控制器和微处理器进行配置。对于USART中断接收,下面是一些关键的步骤: 1. 选择正确的USART模块和引脚 在STM32CubeMX中,首先需要选择正确的USART模块和引脚,并将其配置为接收模式。在“Pinout & Configuration”面板中,通过“USART”选项卡可以找到相应的设置。选择正确的通道(例如USART1或USART2),并为其分配正确的引脚。接下来,选择“Mode”选项卡,并将“Peripheral mode”设置为“Receiver”。 2. 配置相应的中断 在“NVIC Settings”选项卡中,可以对USART接收中断进行配置。首先需要启用中断,然后选择“USARTx global interrupt”(其中x是相应的USART通道号)。在中断控制器(NVIC)中,可以设置优先级和子优先级。确保将优先级设置为正确的级别,以确保正确的中断处理。 3. 编写中断服务程序 在C代码中,需要编写一个中断服务程序(ISR),以处理USART接收中断。该ISR应该包含相应的处理代码,以从接收缓冲区中读取数据。一般情况下,ISR中应该包含以下操作: - 从USART接收缓冲区读取接收到的数据; - 进行相应的错误检查(例如,数据完整性检查); -将数据存储到适当的缓冲区。 4. 启用USART接收中断 最后,在USART驱动程序中启用接收中断。这通常涉及到在USART初始化代码中启用相应的“接收中断(RXNEIE)”标志位。 综上所述,要使用STM32CubeMX进行USART中断接收,您需要选择正确的USART模块和引脚,并将其设置为接收模式。接下来,您需要配置相应的中断,并编写相应的中断服务程序。最后,您需要在USART驱动程序中启用接收中断。正确地配置和编写这些代码,将可以实现USART接收中断。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值