STM32之HAL开发——DMA转运串口数据

DMA功能框图(F1系列)

如果外设要想通过 DMA 来传输数据,必须先给 DMA 控制器发送 DMA 请求, DMA 收到请求信号之后,控制器会给外设一个应答信号,当外设应答后且 DMA 控制器收到应答信号之后,就会启动 DMA 的传输,直到传输完毕

DMA映像表(F1系列)

DMA1通道请求映像

DMA2通道请求映像

注意:DMA 具有 12 个独立可编程的通道,其中 DMA1 有 7 个通道, DMA2 有 5 个通道,每个通道对应不同的外设的 DMA 请求。虽然每个通道可以接收多个外设的请求,但是同一时间只能接收一个,不能同时接收多个。

DMA_InitTypeDef 初始化结构体

typedef struct {
uint32_t Direction; //传输方向
uint32_t PeriphInc; //外设递增
uint32_t MemInc; //存储器递增
uint32_t PeriphDataAlignment; //外设数据宽度
uint32_t MemDataAlignment; //存储器数据宽度
uint32_t Mode; //模式选择
uint32_t Priority; //优先级
} DMA_InitTypeDef;
  1. Direction:传输方向选择,可选外设到存储器、存储器到外设以及存储器到存储器。它设定DMA_SxCR 寄存器的 DIR[1:0] 位的值。 ADC 采集显然使用外设到存储器模式。
  2. PeripheralInc:如果配置为 DMA_PINC_ENABLE,使能外设地址自动递增功能,它设定DMA_CCR 寄存器的 PINC 位的值;一般外设都是只有一个数据寄存器,所以一般不会使能该位。
  3. MemoryInc:如果配置为 DMA_MINC_ENABLE,使能存储器地址自动递增功能,它设定DMA_CCR 寄存器的 MINC 位的值;我们自定义的存储区一般都是存放多个数据的,所以要使能存储器地址自动递增功能。
  4. PeriphDataAlignment:外设数据宽度,可选字节 (8 位)、半字 (16 位) 和字 (32 位),它设定DMA_SxCR 寄存器的 PSIZE[1:0] 位的值。 ADC 数据寄存器只有低 16 位数据有效,使用半字数据宽度。
  5. Mode: DMA 传输模式选择,可选一次传输或者循环传输,它设定 DMA_SxCR 寄存器的 CIRC位的值。我们希望 ADC 采集是持续循环进行的,所以使用循环传输模式。
  6. 软件设置数据流的优先级,有 4 个可选优先级分别为非常高、高、中和低,它设定 DMA_SxCR寄存器的 PL[1:0] 位的值。 DMA 优先级只有在多个 DMA 数据流同时使用时才有意义,这里我们设置为非常高优先级就可以了。

DMA存储器到外设实验

void Debug_USART_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;
      
  __HAL_RCC_GPIOA_CLK_ENABLE();
  /* 使能 UART 时钟 */
  __HAL_RCC_USART1_CLK_ENABLE();  
   /* 配置Tx引脚为复用功能  */
  GPIO_InitStruct.Pin = DEBUG_USART_TX_PIN;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

  HAL_GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStruct);
  
  /* 配置Rx引脚为复用功能 */
  GPIO_InitStruct.Pin = DEBUG_USART_RX_PIN;
    GPIO_InitStruct.Mode=GPIO_MODE_AF_INPUT;	//模式要设置为复用输入模式!	
  HAL_GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStruct);
  
  
  UartHandle.Instance          = DEBUG_USART;
  UartHandle.Init.BaudRate     = DEBUG_USART_BAUDRATE;
  UartHandle.Init.WordLength   = UART_WORDLENGTH_8B;
  UartHandle.Init.StopBits     = UART_STOPBITS_1;
  UartHandle.Init.Parity       = UART_PARITY_NONE;
  UartHandle.Init.HwFlowCtl    = UART_HWCONTROL_NONE;
  UartHandle.Init.Mode         = UART_MODE_TX_RX;
  
  HAL_UART_Init(&UartHandle); 
}

void USART_DMA_Config(void)
{
  DEBUG_USART_DMA_CLK_ENABLE();  
     
  DMA_Handle.Instance=DEBUG_USART_DMA_STREAM;                 //数据流选择
                             
  DMA_Handle.Init.Direction=DMA_MEMORY_TO_PERIPH;             //存储器到外设HAL_DMA_Init(&DMA_Handle);
  DMA_Handle.Init.PeriphInc=DMA_PINC_DISABLE;                 //外设非增量模式/* Associate the DMA handle */
  DMA_Handle.Init.MemInc=DMA_MINC_ENABLE;                     //存储器增量模式__HAL_LINKDMA(&UartHandle, hdmatx, DMA_Handle); 
  DMA_Handle.Init.PeriphDataAlignment=DMA_PDATAALIGN_BYTE;    //外设数据长度:8位
  DMA_Handle.Init.MemDataAlignment=DMA_MDATAALIGN_BYTE;       //存储器数据长度:8位
  DMA_Handle.Init.Mode=DMA_NORMAL;                            //外设普通模式
  DMA_Handle.Init.Priority=DMA_PRIORITY_MEDIUM;               //中等优先级
  
  HAL_DMA_Init(&DMA_Handle);
  /* Associate the DMA handle */
  __HAL_LINKDMA(&UartHandle, hdmatx, DMA_Handle); 
  
}

  HAL_UART_Transmit_DMA(&UartHandle, (uint8_t *)SendBuff ,SENDBUFF_SIZE);

F4/F7系列DMA框图

在F4/F7系列中升级了FIFO功能,使得搬运的数据源和目标之间的存储器可以不用考虑数据大小一致问题,例如将一个字节的数据传输到一个字的存储器中去。FIFO在这之间起一个缓冲区的作用,可以将传输过来的数据,先攒一攒再一起发送。

H7系列DMA框图

在H7系列中新增了一个新的外设,DMAMyx(DMA请求中转调度器):建立DMA请求和DMA通道之间的映射关系,类似于路由的功能。无DMAMUX的MCU,DMA请求和DMA通道的映射关系是固定的,不能由软件修改。有了DMAMUX可以将DMA请求和DMA通道由软件联系起来,实现自定义链接。

复制代码
相关推荐
MARIN_shen18 分钟前
Marin说PCB之POC电路layout设计仿真案例---06
网络·单片机·嵌入式硬件·硬件工程·pcb工艺
Asa31935 分钟前
STM32-按键扫描配置
stm32·单片机·嵌入式硬件
南城花随雪。1 小时前
单片机:实现驱动超声波(附带源码)
单片机·嵌入式硬件
嵌入式科普1 小时前
十三、从0开始卷出一个新项目之瑞萨RZN2L串口DMA接收不定长
c语言·stm32·瑞萨·e2studio·rzn2l
yutian06069 小时前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
析木不会编程12 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉16 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名67716 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普17 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣17 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp