打印
[APM32F1]

APM32F103的USART DMA例程分享

[复制链接]
1034|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 JunKook 于 2022-11-1 12:44 编辑

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

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

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

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

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

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


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

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

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

以上初始化配置完成之后,下面开始进行传输试验,代码如下:
DMA_ConfigDataNumber(DMA1_Channel4, 10);
DMA_Enable(DMA1_Channel4); //USART1_TX通道
while(!DMA_ReadStatusFlag(DMA1_FLAG_TC4));//等待传输完成
DMA_ClearStatusFlag(DMA1_FLAG_TC4);//清除传输完成标志
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+循环队列接收不定长数据   

使用特权

评论回复
5
benjaminka| | 2023-2-5 13:40 | 只看该作者
对实时性要求非常高的场合,可以用USART的DMA传输方式。

使用特权

评论回复
6
caigang13| | 2023-2-6 08:24 | 只看该作者
DMA用好了,程序效率会提高很多

使用特权

评论回复
7
lihuami| | 2023-2-6 16:10 | 只看该作者
用FreeRTOS+DMA操纵usart发送数据为什么失败  

使用特权

评论回复
8
plsbackup| | 2023-2-6 16:29 | 只看该作者
usart中断标志位需要手动清除吗

使用特权

评论回复
9
adolphcocker| | 2023-2-7 21:57 | 只看该作者
如何用dma控制usart发送数据  

使用特权

评论回复
10
hudi008| | 2023-2-8 14:29 | 只看该作者
这个可以接受不定长数据的吗?              

使用特权

评论回复
11
maudlu| | 2023-2-8 17:29 | 只看该作者
DMA的外设地址如何确定                 

使用特权

评论回复
12
jonas222| | 2023-3-4 22:39 | 只看该作者
可以接受可变长度的数据吗?              

使用特权

评论回复
13
hearstnorman323| | 2023-3-10 13:33 | 只看该作者
可以接受可变长度的数据吗?              

使用特权

评论回复
14
claretttt| | 2023-3-10 14:25 | 只看该作者
USART的DMA传输模式可用于实时性要求非常高的场合。

使用特权

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

本版积分规则

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

15

主题

55

帖子

1

粉丝