[APM32F1] APM32F103的USART DMA例程分享

[复制链接]
2097|13
 楼主| JunKook 发表于 2022-11-1 12:31 | 显示全部楼层 |阅读模式
本帖最后由 JunKook 于 2022-11-1 12:44 编辑

使用DMA传输可以连续获取或发送一段信息而不占用中断或延时,在通信频繁或有大段信息要传输时非常有用,今天给大家分享一篇APM32F103的USART数据发送使用DMA方式传输的例程,本例程使用USART1的PA9作为TX,PA10作为RX,USART1的初始化配置如下:
  1. void USART1_Init(uint32_t bound)
  2. {
  3.     GPIO_Config_T GPIO_ConfigStruct;
  4.     USART_Config_T USART_ConfigStruct;

  5.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_GPIOA); /* 使能GPIOA时钟 */
  6.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_USART1); /* 使能USART1时钟 */

  7.     /* USART1_TX --> PA9*/
  8.     GPIO_ConfigStruct.pin = GPIO_PIN_9;
  9.     GPIO_ConfigStruct.mode = GPIO_MODE_AF_PP;   //复用推挽输出
  10.     GPIO_ConfigStruct.speed = GPIO_SPEED_50MHz;
  11.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);     //初始化PA9
  12.     /* USART1_RX --> PA10*/
  13.     GPIO_ConfigStruct.pin = GPIO_PIN_10;
  14.     GPIO_ConfigStruct.mode = GPIO_MODE_IN_PU;   //上拉输入
  15.     GPIO_Config(GPIOA, &GPIO_ConfigStruct);     //初始化PA10

  16.     /* USART Configuration */
  17.     USART_ConfigStruct.baudRate = bound;//波特率
  18.     USART_ConfigStruct.hardwareFlow = USART_HARDWARE_FLOW_NONE;//无硬件数据流控制
  19.     USART_ConfigStruct.mode = USART_MODE_TX_RX;//收发模式
  20.     USART_ConfigStruct.parity = USART_PARITY_NONE; //无奇偶校验位
  21.     USART_ConfigStruct.stopBits = USART_STOP_BIT_1;//一个停止位
  22.     USART_ConfigStruct.wordLength = USART_WORD_LEN_8B;//字长为8位数据格式
  23.     USART_Config(USART1, &USART_ConfigStruct);

  24.     USART_EnableDMA(USART1, USART_DMA_TX);
  25.     USART_Enable(USART1);
  26. }
USART_EnableDMA(USART1, USART_DMA_TX)这个API函数即是使能USART1的发送数据使用DMA方式。

接下来是DMA的初始化配置,由于本例程是USART1的TX采用DMA方式传输,所以在配置DMA之前我们一定要先明确USART1的TX对应到DMA哪个通道?通过查询用户手册,我们知道USART1的TX对应到DMA1的通道4,如下图所示。
DMA.jpg

然后开始初始化配置,如下所示:
  1. void DMA_Init(void)
  2. {
  3.     DMA_Config_T    DMA_ConfigStruct;
  4.         
  5.     RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA1);     /* 使能DMA1时钟 */
  6.         
  7.     DMA_Reset(DMA1_Channel4); /* 复位DMA1通道1 */

  8.     DMA_ConfigStruct.peripheralBaseAddr = USART1_DR_Address;         /* DMA通道外设基地址 */
  9.     DMA_ConfigStruct.memoryBaseAddr = (uint32_t)UART_TX_Buff;   /* DMA通道数据存储器 */
  10.     DMA_ConfigStruct.dir = DMA_DIR_PERIPHERAL_DST;                 /* 指定外设为目的地址 */
  11.     DMA_ConfigStruct.bufferSize = DMA_DATA_LENGTH;                 /* DMA缓冲区大小*/
  12.     DMA_ConfigStruct.peripheralInc = DMA_PERIPHERAL_INC_DISABLE;   /* 当前外设寄存器地址不变(即不自增) */  
  13.     DMA_ConfigStruct.memoryInc = DMA_MEMORY_INC_ENABLE;            /* 当前存储器地址:Disable不变,Enable递增(用于多通道采集) */
  14.     DMA_ConfigStruct.peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_BYTE; /* 外设数据宽度8位 */
  15.     DMA_ConfigStruct.memoryDataSize = DMA_MEMORY_DATA_SIZE_BYTE;         /* 存储器数据宽度8位 */
  16.     DMA_ConfigStruct.loopMode = DMA_MODE_NORMAL; /* DMA通道操作模式位环形缓冲模式 */
  17.     DMA_ConfigStruct.priority = DMA_PRIORITY_HIGH; /* DMA通道优先级高 */
  18.     DMA_ConfigStruct.M2M = DMA_M2MEN_DISABLE;      /* 禁止DMA通道存储器到存储器传输 */
  19.     DMA_Config(DMA1_Channel4, &DMA_ConfigStruct);

  20. //NVIC_EnableIRQRequest(DMA1_Channel4_IRQn, 1, 1);
  21. //DMA_EnableInterrupt(DMA1_Channel4, DMA_INT_TC);
  22. }
这里是否要使能DMA传输完成中断,用户根据自身需求选择配置,本例使用while方式,等待传输完成。参数中USART1_DR_Address是USART1的数据寄存器地址,查阅手册为0x40013800+0x04,传输方向为DMA_DIR_PERIPHERAL_DST,即由内存到外设,外设地址为目的地址。

以上初始化配置完成之后,下面开始进行传输试验,代码如下:
  1. DMA_ConfigDataNumber(DMA1_Channel4, 10);
  2. DMA_Enable(DMA1_Channel4); //USART1_TX通道
  3. while(!DMA_ReadStatusFlag(DMA1_FLAG_TC4));//等待传输完成
  4. DMA_ClearStatusFlag(DMA1_FLAG_TC4);//清除传输完成标志
  5. DMA_Disable(DMA1_Channel4);
第一行:DMA_ConfigDataNumber(DMA1_Channel4, 10)是配置DMA通道要传输数据的数量的API函数,其中第一个参数是DMA通道,第二个参数是数据的数量;
第二行:DMA_Enable(DMA1_Channel4)是开启DMA,即可自动发送UART_TX_Buff中的数据到USART1的数据寄存器中,此时USART的发送数据也开始启动;
第三行:while(!DMA_ReadStatusFlag(DMA1_FLAG_TC4))是等待DMA1的通道4传输完成;
第四行:DMA_ClearStatusFlag(DMA1_FLAG_TC4)是清除传输完成标志;
第五行:DMA_Disable(DMA1_Channel4)是关闭DMA1的通道4,这一句比较关键,如果DMA1的通道4传输完成后不及时关闭,则USART的发送完成标志(或者中断)一直不会产生,以致于会影响用户判断USART是否已经发送完成。


以上就是APM32F103系列MCU的USART采用DMA方式进行数据传输的例程分享,供大家参考,如有疑问,请及时联系。

geraldbetty 发表于 2023-2-4 17:20 | 显示全部楼层
DMA是需要中断才能使用?              
wengh2016 发表于 2023-2-4 17:39 | 显示全部楼层
在DMA传输完成中断中是否不能重新启动DMA  
wilhelmina2 发表于 2023-2-4 19:51 | 显示全部楼层
USART+DMA+循环队列接收不定长数据   
benjaminka 发表于 2023-2-5 13:40 | 显示全部楼层
对实时性要求非常高的场合,可以用USART的DMA传输方式。
caigang13 发表于 2023-2-6 08:24 来自手机 | 显示全部楼层
DMA用好了,程序效率会提高很多
lihuami 发表于 2023-2-6 16:10 | 显示全部楼层
用FreeRTOS+DMA操纵usart发送数据为什么失败  
plsbackup 发表于 2023-2-6 16:29 | 显示全部楼层
usart中断标志位需要手动清除吗
adolphcocker 发表于 2023-2-7 21:57 | 显示全部楼层
如何用dma控制usart发送数据  
hudi008 发表于 2023-2-8 14:29 | 显示全部楼层
这个可以接受不定长数据的吗?              
maudlu 发表于 2023-2-8 17:29 | 显示全部楼层
DMA的外设地址如何确定                 
jonas222 发表于 2023-3-4 22:39 | 显示全部楼层
可以接受可变长度的数据吗?              
hearstnorman323 发表于 2023-3-10 13:33 | 显示全部楼层
可以接受可变长度的数据吗?              
claretttt 发表于 2023-3-10 14:25 | 显示全部楼层
USART的DMA传输模式可用于实时性要求非常高的场合。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:极海半导体
简介:珠海极海半导体有限公司是一家致力于开发工业级/车规级微控制器、模拟与混合信号IC及系统级芯片的集成电路设计型企业。极海团队拥有20年集成电路设计经验和嵌入式系统开发能力,可为客户提供核心可靠的芯片产品及方案,实现准确感应、安全传输和实时控制,助力客户在智慧家居、高端消费电子、工业控制、汽车电子、智慧能源以及通信设施等领域的拓展创新。

15

主题

55

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部