嵌入式C语言教程:使用DMA控制的UART通信

在许多嵌入式系统中,UART(通用异步接收/发送)是一种常见的通信协议,用于低速串行数据传输。

通过DMA(直接内存访问)控制UART通信,可以有效地释放CPU资源,使其能够处理其他计算任务。

本文将介绍如何在STM32微控制器上实现DMA控制的UART通信。

⬇帮大家整理了单片机的资料

包括stm32的项目合集【源码+开发文档】

点击下方蓝字即可领取,感谢支持!⬇

点击领取更多嵌入式详细资料

问题讨论,stm32的资料领取可以私信!

一、开发环境准备

硬件要求

  • 微控制器:STM32F407VGT6,具备高性能处理能力和丰富的外设支持。
  • 开发板:STM32F4 Discovery,提供必要的调试和开发接口,包括UART接口。
  • 外部设备:PC或其他UART兼容设备,用于接收和发送数据。

软件要求

  • 集成开发环境(IDE):STM32CubeIDE,支持代码开发、编译及调试。
  • 固件库:STM32CubeMX,用于配置微控制器的外设,包括UART接口和DMA通道。

安装和配置

  1. 安装STM32CubeIDE:从ST官网下载并安装。
  2. 使用STM32CubeMX创建项目:选择STM32F407VGT6芯片,配置UART接口和相应的DMA通道,生成初始化代码。

二、应用场景:高效UART数据传输

设计目标

创建一个系统,能够通过UART接口高效地接收和发送大量数据,使用DMA来自动处理数据传输,适用于例如日志记录、远程命令解析等场景。

代码实现

#include "stm32f4xx_hal.h"

UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_uart3_rx;
DMA_HandleTypeDef hdma_uart3_tx;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_UART3_Init(void);

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_UART3_Init();

  uint8_t txData[] = "Hello UART DMA!";
  uint8_t rxData[100] = {0};  // 更大的接收缓冲区

  // 启动DMA接收
  HAL_UART_Receive_DMA(&huart3, rxData, sizeof(rxData));
  // 启动DMA发送
  HAL_UART_Transmit_DMA(&huart3, txData, sizeof(txData));

  while (1)
  {
    // 主循环中不需要执行任何操作,DMA控制器处理所有UART数据传输
  }
}

void MX_DMA_Init(void)
{
  __HAL_RCC_DMA1_CLK_ENABLE();
  // 配置UART3 RX DMA
  hdma_uart3_rx.Instance = DMA1_Stream1;
  hdma_uart3_rx.Init.Channel = DMA_CHANNEL_4;
  hdma_uart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
  hdma_uart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_uart3_rx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_uart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_uart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_uart3_rx.Init.Mode = DMA_CIRCULAR;
  hdma_uart3_rx.Init.Priority = DMA_PRIORITY_HIGH;
  HAL_DMA_Init(&hdma_uart3_rx);
  __HAL_LINKDMA(&huart3, hdmarx, hdma_uart3_rx);

  // 配置UART3 TX DMA
  hdma_uart3_tx.Instance = DMA1_Stream3;
  hdma_uart3_tx.Init.Channel = DMA_CHANNEL_4;
  hdma_uart3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
  hdma_uart3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
  hdma_uart3_tx.Init.MemInc = DMA_MINC_ENABLE;
  hdma_uart3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  hdma_uart3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  hdma_uart3_tx.Init.Mode = DMA_NORMAL;
  hdma_uart3_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
  HAL_DMA_Init(&hdma_uart3_tx);
  __HAL_LINKDMA(&huart3, hdmatx, hdma_uart3_tx);
}

void MX_UART3_Init(void)
{
    huart3.Instance = USART3;
    huart3.Init.BaudRate = 115200;
    huart3.Init.WordLength = UART_WORDLENGTH_8B;
    huart3.Init.StopBits = UART_STOPBITS_1;
    huart3.Init.Parity = UART_PARITY_NONE;
    huart3.Init.Mode = UART_MODE_TX_RX;
    huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
    huart3.Init.OverSampling = UART_OVERSAMPLING_16;
    HAL_UART_Init(&huart3);
}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    // 当DMA完成UART数据发送时调用此回调函数
    if(huart->Instance == USART3)
    {
        // 发送完成后的操作
    }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    // 当DMA完成UART数据接收时调用此回调函数
    if(huart->Instance == USART3)
    {
        // 接收完成后的操作,例如处理接收到的数据
    }
}

void Error_Handler(void)
{
    // 用户可以在此处添加错误处理代码
    __disable_irq();
    while (1)
    {
    }
}

问题解决方案

  • DMA通道冲突:确保为UART接收和发送选择不同的DMA通道或流,以避免资源冲突。
  • 数据对齐问题:在初始化DMA时,设置正确的数据对齐选项以确保数据的正确传输。
  • 缓冲管理:使用合适的缓冲策略管理DMA缓冲,确保数据在处理前不被覆盖,同时优化内存使用。

通过本教程,开发者可以了解如何在STM32平台上实现基于DMA的UART数据传输,这对于需要高效通信的嵌入式应用非常有益。

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值