先上代码:
#define COMM_COM USART2
#define COMM_COM_CLK RCC_APB1Periph_USART2
#define COMM_COM_TX_GPIO_CLK RCC_AHB1Periph_GPIOD //UART TX
#define COMM_COM_TX_PIN GPIO_Pin_5
#define COMM_COM_TX_GPIO_PORT GPIOD
#define COMM_COM_TX_SOURCE GPIO_PinSource5
#define COMM_COM_TX_AF GPIO_AF_USART2
#define COMM_COM_RX_GPIO_CLK RCC_AHB1Periph_GPIOD //UART RX
#define COMM_COM_RX_PIN GPIO_Pin_6
#define COMM_COM_RX_GPIO_PORT GPIOD
#define COMM_COM_RX_SOURCE GPIO_PinSource6
#define COMM_COM_RX_AF GPIO_AF_USART2
#define COMM_COM_IRQn USART2_IRQn
#define COMM_COM_Priority 9 //优先级
#define COMM_COM_BaudRate 115200 //波特率
#define COMM_COM_IRQHandler USART2_IRQHandler //中断函数接口(见stm32f4xx_it.c)
USART配置:
/************************************************
函数名称 :USART_COMM_Configuration
功 能 :通信串口配置
参 数 :无
返 回 值 :无
作 者 :strongerHuang
*************************************************/
void USART_COMM_Configuration(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* 时钟配置 */
RCC_AHB1PeriphClockCmd(COMM_COM_TX_GPIO_CLK | COMM_COM_RX_GPIO_CLK, ENABLE);
if((USART1 == COMM_COM) || (USART6 == COMM_COM))
RCC_APB2PeriphClockCmd(COMM_COM_CLK, ENABLE);
else
RCC_APB1PeriphClockCmd(COMM_COM_CLK, ENABLE);
/* 复用配置 */
GPIO_PinAFConfig(COMM_COM_TX_GPIO_PORT, COMM_COM_TX_SOURCE, COMM_COM_TX_AF);
GPIO_PinAFConfig(COMM_COM_RX_GPIO_PORT, COMM_COM_RX_SOURCE, COMM_COM_RX_AF);
/* 引脚配置 */
GPIO_InitStructure.GPIO_Pin = COMM_COM_TX_PIN; //USART Tx
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用模式
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(COMM_COM_TX_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = COMM_COM_RX_PIN; //USART Rx
GPIO_Init(COMM_COM_RX_GPIO_PORT, &GPIO_InitStructure);
/* NVIC配置 */
NVIC_InitStructure.NVIC_IRQChannel = COMM_COM_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = COMM_COM_Priority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* USART配置 */
USART_InitStructure.USART_BaudRate = COMM_COM_BaudRate; //波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //传输位数
USART_InitStructure.USART_StopBits = USART_StopBits_1; //停止位
USART_InitStructure.USART_Parity = USART_Parity_No ; //校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发功能
USART_Init(COMM_COM, &USART_InitStructure);
USART_ClearFlag(COMM_COM, USART_FLAG_RXNE | USART_FLAG_TC);
USART_ITConfig(COMM_COM, USART_IT_RXNE, ENABLE); //接收中断
USART_DMACmd(COMM_COM, USART_DMAReq_Tx, ENABLE); //使能DMA
USART_Cmd(COMM_COM, ENABLE); //使能USART
}
DMA配置中的宏定义:
#define COMM_DR_ADDRESS ((uint32_t)USART2 + 0x04)
#define COMM_DMA DMA1
#define COMM_DMA_CLK RCC_AHB1Periph_DMA1
#define COMM_TX_DMA_CHANNEL DMA_Channel_4
#define COMM_TX_DMA_STREAM DMA1_Stream6
#define COMM_TX_DMA_FLAG_TCIF DMA_FLAG_TCIF6
#define COMM_TX_DMA_IRQn DMA1_Stream6_IRQn
#define COMM_TX_DMA_Priority 8 //优先级
#define COMM_TX_DMA_IRQHandler DMA1_Stream6_IRQHandler //中断函数接口(见stm32f4xx_it.c)
#define COMM_TX_DMA_IT_TCIF DMA_IT_TCIF6
通讯串口的配置
/************************************************
函数名称 :USART_COMM_DMA_Configuration
功 能 :通信串口的DMA配置
参 数 :无
返 回 值 :无
作 者 :strongerHuang
*************************************************/
void USART_COMM_DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* 使能时钟 */
RCC_AHB1PeriphClockCmd(COMM_DMA_CLK, ENABLE);
/* NVIC配置 */
NVIC_InitStructure.NVIC_IRQChannel = COMM_TX_DMA_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = COMM_TX_DMA_Priority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* DMA配置 */
DMA_DeInit(COMM_TX_DMA_STREAM);
DMA_InitStructure.DMA_Channel = COMM_TX_DMA_CHANNEL; //DMA通道
DMA_InitStructure.DMA_PeripheralBaseAddr = COMM_DR_ADDRESS; //外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; //内存地址(待传入参数)
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; //传输方向
DMA_InitStructure.DMA_BufferSize = 0; //传输长度(待传入参数)
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_Medium; //优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(COMM_TX_DMA_STREAM, &DMA_InitStructure);
DMA_ClearFlag(COMM_TX_DMA_STREAM, COMM_TX_DMA_FLAG_TCIF);
DMA_ITConfig(COMM_TX_DMA_STREAM, DMA_IT_TC, ENABLE); //使能DMA传输完成中断
DMA_Cmd(COMM_TX_DMA_STREAM, DISABLE); //初始化禁止
}
j接下来实现数据发送与接收
/************************************************
函数名称 :COMM_SendBufByDMA
功 能 :通信串口通过DMA发送数据
参 数 :Buf ------ 数据(地址)
Length --- 数据长度(字节)
返 回 值 :无
作 者 :strongerHuang
*************************************************/
void COMM_SendBufByDMA(uint8_t *Buf, uint16_t Length)
{
DMA_Cmd(COMM_TX_DMA_STREAM, DISABLE); //关闭DMA
//内存地址
DMA_MemoryTargetConfig(COMM_TX_DMA_STREAM, (uint32_t)Buf, DMA_Memory_0);
DMA_SetCurrDataCounter(COMM_TX_DMA_STREAM, Length); //设置DMA传输长度
DMA_Cmd(COMM_TX_DMA_STREAM, ENABLE); //使能DMA
}
DMA是一种在嵌入式实时任务处理中常用的功能。
而UART发送数据包,使用DMA方式能大量减轻CPU处理的时间,使其CPU资源不被大量浪费,尤其在UART收发大量数据包(如高频率收发指令)时具有明显优势。
审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。
举报投诉
-
单片机
+关注
关注
6034文章
44552浏览量
634450 -
STM32
+关注
关注
2270文章
10893浏览量
355675 -
串口
+关注
关注
14文章
1551浏览量
76408 -
dma
+关注
关注
3文章
560浏览量
100538
发布评论请先 登录
相关推荐
基于单片机虚拟串口驱动LCD1602的电路仿真
基于M ult isim 10 仿真软件, 设计单片机的虚拟串口驱动LCD1602 液晶电路。实现了虚拟串口扩展并行输出的功能。该设计适用单片机
发表于 08-16 17:28
•116次下载
单片机控制系统中labVIEW与单片机实现串口通信的设计过程
首先利用单片机STC89C54通过串口发送“你好,LabVIEW”,LabVIEW将单片机发送到数据进行显示。通过这个实例来了解LabVIEW的串口通信设计。
发表于 07-25 09:30
•2.7w次阅读
单片机的串口实验 串口介绍 串口原理
文章目录1 串口的硬件初步认识2 中间桥梁芯片硬件电路3 电脑如何识别 中间桥梁芯片4 串口调试助手5 为什么需要CH340模块6 CH340模块可以换成别的吗7 单片机开发版设计理念18 单
发表于 11-10 20:20
•16次下载
C语言条件编译语句and单片机DMA的介绍
C语言条件编译语句and单片机DMA的介绍C语言条件编译:这里面介绍的很详细,也有历程。DMA的介绍:介绍了单片机中为什么要使用DMA,以及
发表于 11-29 10:36
•3次下载
STM32单片机串口空闲中断+DMA接收不定长数据
在上一篇文章STM32单片机串口空闲中断接收不定长数据中介绍了利用串口空闲中断接收不定长数据,这种方式有一个问题就是串口每接收到一个字节就会进入一次中断,如果发送的数据比较频繁,那么
发表于 12-27 19:24
•18次下载
STM32单片机实现DMA+ADC+UART功能
。于是想到了ADC采样的数据用DMA功能存储,并通过串口打印。但是串口打印依然要占用单片机时间,那能不能串口数据的输出也采用
发表于 12-28 19:25
•34次下载
单片机接收不定长的数据,最优解是DMA+串口空闲中断
如果单片机不支持串口空闲中断和DMA,可以参考之前写的,串口只用接收中断,完成不定长的分包。这里以stm32L4的单片机举例,思路可拓展到G
发表于 12-28 19:26
•25次下载
评论