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的配置步骤
使能DMA时钟
在使用DMA之前,须要先使能DMA外设的时钟。差别的 DMA 通道对应差别的时钟配置。
// 使能DMA1时钟(例如,对于DMA1的信道)
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
复制代码
设置DMA Channel和DMA Mode 配置DMA通道和传输模式(比如正常模式、循环模式等)。
DMA_InitTypeDef DMA_InitStructure;
DMA_InitStructure.DMA_Channel = DMA_Channel_0; // 选择DMA通道
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR; // UART数据寄存器地址
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正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High; // 设置DMA优先级为高
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO模式关闭
DMA_Init(DMA1_Channel0, &DMA_InitStructure); // 初始化DMA通道
复制代码
使能DMA传输 完成配置后,使能DMA通道。
DMA_Cmd(DMA1_Channel0, ENABLE);
复制代码
四、UART初始化与DMA联合
UART初始化配置 配置UART的基本参数,如波特率、数据格式、校验位等。
// 配置USART1
USART_InitTypeDef USART_InitStructure;
USART_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);
复制代码
配置UART的DMA传输 使能 UART的DMA传输功能,通常在UART的中断配置中完成。
// 使能USART1的DMA接收功能
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
复制代码
五、DMA传输的中断处置惩罚
配置DMA传输完成中断 配置DMA传输完成后触发中断,以便进行后续处置惩罚。
// 配置DMA中断
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 2; // 中断优先级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
编写DMA中断服务函数 在中断服务函数中进行数据处置惩罚和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数据接收:
#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);
// 配置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