打印
[STM32H7]

STM32H743性能解析:DMA与UART的高效数据传输实现

[复制链接]
150|9
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Clyde011|  楼主 | 2024-11-24 07:46 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32H743是STMicroelectronics推出的一款高性能微控制器,采用Cortex-M7内核,主频高达480MHz,内置丰富的外设,适合高性能嵌入式应用。在本篇文章中,我们将使用STM32H743探索如何结合DMA(直接存储器访问)和UART实现高效的数据传输。

使用DMA与UART的优势通常情况下,UART数据传输需要由CPU处理发送和接收的数据,这会占用大量CPU资源。而DMA可以独立于CPU,将数据直接传输到指定存储器,极大提高传输效率。STM32H743提供多通道DMA控制器,可以支持多外设同时工作。

实验内容我们将通过以下步骤实现UART和DMA的结合:
  • 配置UART用于数据发送与接收;
  • 配置DMA,用于高效传输数据;
  • 编写代码实现UART与DMA的协同工作。

硬件与软件环境
  • 硬件

    • STM32H743 Nucleo开发板
    • USB转UART模块
    • PC,用于串口调试
  • 软件

    • STM32CubeMX:生成代码框架
    • STM32CubeIDE:编写和调试代码

DMA与UART代码实现以下是DMA和UART功能的具体实现代码:
#include "main.h"

// UART和DMA句柄定义
UART_HandleTypeDef huart3;
DMA_HandleTypeDef hdma_usart3_tx;
DMA_HandleTypeDef hdma_usart3_rx;

// 发送和接收缓冲区
uint8_t tx_buffer[] = "Hello, DMA with UART!\r\n";
uint8_t rx_buffer[100];

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

int main(void) {
    HAL_Init();
    SystemClock_Config();

    // 初始化外设
    MX_GPIO_Init();
    MX_DMA_Init();
    MX_USART3_UART_Init();

    // 使用DMA发送数据
    if (HAL_UART_Transmit_DMA(&huart3, tx_buffer, sizeof(tx_buffer) - 1) != HAL_OK) {
        Error_Handler();
    }

    // 启动DMA接收
    if (HAL_UART_Receive_DMA(&huart3, rx_buffer, sizeof(rx_buffer)) != HAL_OK) {
        Error_Handler();
    }

    while (1) {
        // 主循环中可以处理其他任务
    }
}

// USART3初始化函数
static void MX_USART3_UART_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;
    if (HAL_UART_Init(&huart3) != HAL_OK) {
        Error_Handler();
    }
}

// DMA初始化函数
static void MX_DMA_Init(void) {
    __HAL_RCC_DMA1_CLK_ENABLE();

    // 初始化DMA1_Channel2用于USART3_TX
    hdma_usart3_tx.Instance = DMA1_Channel2;
    hdma_usart3_tx.Init.Request = DMA_REQUEST_USART3_TX;
    hdma_usart3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
    hdma_usart3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart3_tx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart3_tx.Init.Mode = DMA_NORMAL;
    hdma_usart3_tx.Init.Priority = DMA_PRIORITY_LOW;
    if (HAL_DMA_Init(&hdma_usart3_tx) != HAL_OK) {
        Error_Handler();
    }
    __HAL_LINKDMA(&huart3, hdmatx, hdma_usart3_tx);

    // 初始化DMA1_Channel3用于USART3_RX
    hdma_usart3_rx.Instance = DMA1_Channel3;
    hdma_usart3_rx.Init.Request = DMA_REQUEST_USART3_RX;
    hdma_usart3_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_usart3_rx.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_usart3_rx.Init.MemInc = DMA_MINC_ENABLE;
    hdma_usart3_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
    hdma_usart3_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
    hdma_usart3_rx.Init.Mode = DMA_CIRCULAR;
    hdma_usart3_rx.Init.Priority = DMA_PRIORITY_HIGH;
    if (HAL_DMA_Init(&hdma_usart3_rx) != HAL_OK) {
        Error_Handler();
    }
    __HAL_LINKDMA(&huart3, hdmarx, hdma_usart3_rx);
}

// GPIO初始化函数
static void MX_GPIO_Init(void) {
    __HAL_RCC_GPIOB_CLK_ENABLE();
    // 可添加额外的GPIO配置代码
}
测试与验证
  • 将开发板与PC通过USB转UART模块连接。
  • 使用串口调试助手查看数据发送情况,并通过串口发送测试数据。
  • 观察是否正确接收到数据,同时检查DMA是否成功释放CPU资源。

总结本文基于STM32H743实现了DMA与UART的高效协同工作。通过结合DMA的高速传输能力与UART的串口通信功能,我们可以显著降低CPU占用率,为复杂嵌入式应用提供更多资源。如果你有更复杂的通信需求,可以进一步优化DMA与UART的配置,比如使用FIFO模式或设置优先级。

使用特权

评论回复
沙发
公羊子丹| | 2024-11-24 07:47 | 只看该作者
哇,这篇文章让我瞬间明白DMA的优势,真不错!

使用特权

评论回复
板凳
周半梅| | 2024-11-24 07:47 | 只看该作者
STM32H743性能真的强,这个代码能跑到别的STM32上吗?

使用特权

评论回复
地板
帛灿灿| | 2024-11-24 07:47 | 只看该作者
大佬讲解的很细,我要赶紧试试这个示例!

使用特权

评论回复
5
童雨竹| | 2024-11-24 07:48 | 只看该作者
我之前直接用HAL库写UART,没用DMA,效率确实差点。

使用特权

评论回复
6
万图| | 2024-11-24 07:48 | 只看该作者
Circular模式用在接收上很有用啊,学到了!

使用特权

评论回复
7
Wordsworth| | 2024-11-24 07:48 | 只看该作者
有没有可能支持多个串口同时用DMA传输?求代码!

使用特权

评论回复
8
Bblythe| | 2024-11-24 07:48 | 只看该作者
USART3的引脚能不能用其他的引脚复用?好像我用的板子没这个接口。

使用特权

评论回复
9
Pulitzer| | 2024-11-24 07:49 | 只看该作者
感觉STM32CubeMX生成代码方便多了,以前手写真的费劲。

使用特权

评论回复
10
Uriah| | 2024-11-24 07:49 | 只看该作者
如果数据量更大,比如几千字节,DMA还能保持高效吗?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

3390

帖子

0

粉丝