ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【具体讲解在STM32的UART通信中使用DMA机制】 [打印本页]

作者: 曹旭辉    时间: 7 天前
标题: 【具体讲解在STM32的UART通信中使用DMA机制】
具体讲解在STM32的UART通信中使用DMA机制


  
一、DMA机制概述

DMA(Direct Memory Access) 是一种硬件机制,答应外设不须要CPU干预的情况下直接访问内存。它可以或许明显提升数据传输的效率,尤其是在须要频繁数据传输的场景中。
二、DMA在UART中的作用

在STM32微控制器中, UART模块支持DMA传输,可以或许实现在CPU空闲的情况下,快速传输大量数据。具体来说,DMA可以将UART接收的数据直接传输到内存中的缓冲区,大概将内存中的数据缓冲区直接传输到UART发送缓冲区,从而降低CPU负载,提高系统效率。
三、DMA的配置步骤

  1. // 使能DMA1时钟(例如,对于DMA1的信道)
  2. RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
复制代码
  1. DMA_InitTypeDef DMA_InitStructure;
  2. DMA_InitStructure.DMA_Channel = DMA_Channel_0;  // 选择DMA通道
  3. DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; // UART数据寄存器地址
  4. DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)rxBuffer; // 接收缓冲区地址
  5. DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; // 设置传输方向,外设到内存
  6. DMA_InitStructure.DMA_BufferSize = RX_BUFFER_SIZE; // 接收缓冲区大小
  7. DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 外设地址不变
  8. DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; // 内存地址递增
  9. DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; // 数据宽度为字节
  10. DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  11. DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; // DMA正常模式
  12. DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 设置DMA优先级为高
  13. DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO模式关闭
  14. DMA_Init(DMA1_Channel0, &DMA_InitStructure); // 初始化DMA通道
复制代码
  1. DMA_Cmd(DMA1_Channel0, ENABLE);
复制代码
四、UART初始化与DMA联合

  1. // 配置USART1
  2. USART_InitTypeDef USART_InitStructure;
  3. USART_InitStructure.USART_BaudRate = 115200;
  4. USART_InitStructure.USART_WordLength = USART_WordLength_8b;
  5. USART_InitStructure.USART_StopBits = USART_StopBits_1;
  6. USART_InitStructure.USART_Parity = USART_Parity_No;
  7. USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
  8. USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
  9. USART_Init(USART1, &USART_InitStructure);
复制代码
  1. // 使能USART1的DMA接收功能
  2. USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
复制代码
五、DMA传输的中断处置惩罚

void DMA1_Channel0_IRQHandler(void) {
if (DMA_GetFlagStatus(DMA1_Channel0, DMA_FLAG_TCIF0)) {
// 扫除传输完成标记
DMA_ClearFlag(DMA1_Channel0, DMA_FLAG_TCIF0);
// 处置惩罚接收到的数据
processData(rxBuffer, RX_BUFFER_SIZE);
// 重新装载DMA缓冲区
DMA_SetCurrDataCounter(DMA1_Channel0, RX_BUFFER_SIZE);
}
}
六、DMA与中断的联合使用

1.DMA和中断的区别
• DMA :在不占用CPU的情况下,直接完成内存和外设之间的数据传输,适合大数据量的传输。
• 中断 :当外设须要CPU处置惩罚特定事件时,通过中断机制关照CPU。
2.在UART通信中DMA的上风
• 提高了数据传输的效率,减少了CPU的负载。
• 实用于须要大量数据传输的应用场景,如长时间的串口数据收罗。
3.什么时候最适合使用DMA
• 当须要实现高效的、大量数据的UART传输时。
• 当盼望降低CPU使用率,让CPU专注于其他使命处置惩罚时。
七、留意事项与常见题目

1.DMA传输中的内存配置 确保DMA传输的内存区域是一连的,避免因内存碎片导致传输错误。
2.缓冲区的大小和管理 公道设置DMA传输的缓冲区大小,避免由于缓冲区过小而导致频繁的DMA中断,或由于缓冲区过大而导致内存浪费。
3.DMA传输方向的设置 根据现实需求设置正确的传输方向(外设到内存或内存到外设),否则会导致数据传输错误。
4.DMA优先级的设置 根据系统的现实工作情况,公道设置DMA通道的优先级,以确保关键使命的优先执行。
5.传输完成后DMA的重装载 在DMA传输完成后,配置DMA为循环模式或手动重新装载模式,以包管持续的数据传输需求。
八、代码示例

以下是一个完备的示例代码,展示了如安在STM32中配置和使用DMA进行UART数据接收:
  1. #include "stm32f10x.h"#define RX_BUFFER_SIZE 256uint8_t rxBuffer[RX_BUFFER_SIZE];void DMA_Configuration(void) {    DMA_InitTypeDef DMA_InitStructure;    NVIC_InitTypeDef NVIC_InitStructure;    // 使能DMA1时钟    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);    // 配置DMA通道0    DMA_InitStructure.DMA_Channel = DMA_Channel_0;    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)rxBuffer;    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;    DMA_InitStructure.DMA_BufferSize = RX_BUFFER_SIZE;    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;    DMA_InitStructure.DMA_Priority = DMA_Priority_High;    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;    DMA_Init(DMA1_Channel0, &DMA_InitStructure);    // 使能DMA通道0    DMA_Cmd(DMA1_Channel0, ENABLE);
  2.     // 配置DMA中断优先级    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel0_IRQn;    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    NVIC_Init(&NVIC_InitStructure);    // 启用DMA传输完成中断    DMA_ITConfig(DMA1_Channel0, DMA_IT_TC, ENABLE);}void USART_Configuration(void) {USART_InitTypeDef USART_InitStructure;// 使能USART1外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 配置GPIOGPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; // TX和RX引脚GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 配置USARTUSART_InitStructure.USART_BaudRate = 115200;USART_InitStructure.USART_WordLength = USART_WordLength_8b;USART_InitStructure.USART_StopBits = USART_StopBits_1;USART_InitStructure.USART_Parity = USART_Parity_No;USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;USART_Init(USART1, &USART_InitStructure);// 使能USART接收DMAUSART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);// 启动USARTUSART_Cmd(USART1, ENABLE);}void USART_NVIC_Configuration(void) {NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);}void USART1_IRQHandler(void) {// 处置惩罚 USART 中断,如有须要//,...}void DMA1_Channel0_IRQHandler(void) {if (DMA_GetFlagStatus(DMA1_Channel0, DMA_FLAG_TCIF0)) {// 扫除 DMA 传输完成标记DMA_ClearFlag(DMA1_Channel0, DMA_FLAG_TCIF0);// 数据处置惩罚操纵processData(rxBuffer, RX_BUFFER_SIZE);// 重新装载 DMA 缓冲区DMA_SetCurrDataCounter(DMA1_Channel0, RX_BUFFER_SIZE);}}int main(void) {// 系统时钟配置(假设已经完成)// 配置DMADMA_Configuration();// 配置USART1USART_Configuration();// 配置USART中断USART_NVIC_Configuration();// 进入主循环while (1) {// 主循环可以执行其他使命}}
复制代码
九、总结

通过在STM32的UART通信中使用DMA机制,可以在不占用CPU的情况下实现高效的数据传输,明显提升系统的性能和相应速度。DMA的配置和使用须要细致明确其工作原理和具体的配置步骤,确保在现实应用中的正确性和稳定性。
在现实开发中,还应联合具体的应用场景和硬件配置,进行公道的参数设置和优化,以达到最佳的传输效率和稳定

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4