1、概述

上一篇文章《STM32使用DMA接收串口数据》讲解了如何使用DMA接收数据,使用DMA外设和串口外设,使用的中断是串口空闲中断。本篇文章主要讲解使用DMA发送数据,不会讲解基础的串口和DMA知识,直接上代码,如果有同学对DMA和串口都不熟悉,建议看一下上篇文章《STM32使用DMA接收串口数据》。

使用DMA发送数据,首先我们要确认使用的串口有没有DMA。

我们使用USART1串口外设,从数据手册中可以查到,USART1的发送和接收都是支持DMA的,使用的是DMA2.

接下来就是撸代码的时刻了

02、代码

DMA串口发送的代码是在上一篇文章DMA串口接收的基础上修改的。

void UART_Init(void)
{
USART_InitTypeDef USART_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure; /* Enable GPIO clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Enable UART1 clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* Connect PXx to USARTx_Tx*/
GPIO_PinAFConfig(GPIOA, 9, GPIO_AF_USART1); /* Connect PXx to USARTx_Rx*/
GPIO_PinAFConfig(GPIOA, 10, GPIO_AF_USART1); /* Configure USART Tx as alternate function */
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USART Rx as alternate function */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOA, &GPIO_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_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; /* USART configuration */
USART_Init(USART1, &USART_InitStructure); USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); /* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure); /*使能串口DMA接收*/
USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
/*使能串口DMA发送*/
USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE); /* Enable USART */
USART_Cmd(USART1, ENABLE);
}

在这里除了常规的串口配置,我们需要配置串口的DMA发送,和串口DMA接收一样的API函数,参数修改为USART_DMAReq_Tx即可。

串口DMA发送配置

void Uart_Send_DMA_Config(void)
{
DMA_InitTypeDef DMA_InitStructure; /* Enable DMA clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); /* Reset DMA Stream registers (for debug purpose) */
DMA_DeInit(DMA2_Stream7); /* Check if the DMA Stream is disabled before enabling it.
Note that this step is useful when the same Stream is used multiple times:
enabled, then disabled then re-enabled... In this case, the DMA Stream disable
will be effective only at the end of the ongoing data transfer and it will
not be possible to re-configure it before making sure that the Enable bit
has been cleared by hardware. If the Stream is used only once, this step might
be bypassed. */
while (DMA_GetCmdStatus(DMA2_Stream7) != DISABLE)
{
} /* Configure DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_4; //DMA请求发出通道
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&USART1->DR;//配置外设地址
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)UART_Buffer;//配置存储器地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//传输方向配置
DMA_InitStructure.DMA_BufferSize = (uint32_t)UART_RX_LEN;//传输大小
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设地址不变
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//memory地址自增
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设地址数据单位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//memory地址数据单位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;//DMA模式:正常模式
DMA_InitStructure.DMA_Priority = DMA_Priority_High;//优先级:高
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;//FIFO 模式不使能.
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;// FIFO 阈值选择
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发模式选择,可选单次模式、 4 节拍的增量突发模式、 8 节拍的增量突发模式或 16 节拍的增量突发模式。
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发模式选择,可选单次模式、 4 节拍的增量突发模式、 8 节拍的增量突发模式或 16 节拍的增量突发模式。
DMA_Init(DMA2_Stream7, &DMA_InitStructure); /* DMA Stream enable */
// DMA_Cmd(DMA2_Stream7, ENABLE);
}

这里也是常规的DMA配置流程,不明白的同学请看文章《STM32DMA详解》,这里值得注意的是,配置完成并没有使能DMA2_Stream7,使能了就会立即将UART_Buffer的数据发送出去。

其他代码处理

void USART1_IRQHandler(void)
{
uint8_t temp;
if(USART_GetFlagStatus(USART1, USART_FLAG_IDLE) == SET)
{
DealWith_UartData();
// USART_ClearFlag(USART1, USART_FLAG_IDLE);
temp = USART1->SR;
temp = USART1->DR; //清USART_IT_IDLE标志
}
} void DealWith_UartData()
{
DMA_Cmd(DMA2_Stream2, DISABLE);
UART_Receive_flg = 1;
UART_Receive_len = UART_RX_LEN - DMA_GetCurrDataCounter(DMA2_Stream2);
UART_Buffer[UART_Receive_len] = 0;
DMA_SetCurrDataCounter(DMA2_Stream2,UART_RX_LEN);
DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_TCIF2);
DMA_Cmd(DMA2_Stream2, ENABLE);
} int main(void)
{
UART_Receive_flg = 0; Uart_Reveice_DMA_Config();
Uart_Send_DMA_Config();
UART_Init(); while (1)
{
if(UART_Receive_flg)
{
UART_Receive_flg = 0;
Uart_Send_DMA_Start();
}
}
}

上面3个函数,简单逻辑就是,当串口使用DMA接收了一定量的数据,就会通过串口DMA发送出去,串口DMA发送的代码如下:

void Uart_Send_DMA_Start(void)
{
DMA_SetCurrDataCounter(DMA2_Stream7,UART_Receive_len);
DMA_ClearFlag(DMA2_Stream7, DMA_FLAG_TCIF7);
/* DMA Stream enable */
DMA_Cmd(DMA2_Stream7, ENABLE);
}

03、后记

这一篇很简单,就是DMA使用的一个延伸,上面说了这么多,也贴了很多代码,不可能将所有代码全部贴出来,作为软件工程师,还是在IDE里看代码方便,如果感兴趣的话,可以到下面github链接下载代码,Keil和IAR的工程文件都有。

PCB和工程代码开源地址:

https://github.com/strongercjd/STM32F207VCT6

点击查看本文所在的专辑,STM32F207教程

STM32使用DMA发送串口数据的更多相关文章

  1. STM32 UART DMA实现未知数据长度接收

    串口通信是经常使用到的功能,在STM32中UART具有DMA功能,并且收发都可以使用DMA,使用DMA发送基本上大家不会遇到什么问题,因为发送的时候会告知DMA发送的数据长度,DMA按照发送的长度直接 ...

  2. STM32—无需中断来实现使用DMA接收串口数据

    本节目标: 通过DMA,无需中断,接收不定时长的串口数据 描述:当在串口多数据传输下,CPU会产生多次中断来接收串口数据,这样会大大地降低CPU效率,同时又需要CPU去做其它更重要的事情,我们应该如何 ...

  3. 使用DMA方式发送串口数据

    一.初始化部分代码 //串口接收DMA缓存 uint8_t Uart_Rx[UART_RX_LEN] = {}; uint32_t Uart_Send_Buffer[] = {}; void USAR ...

  4. STM32 串口USART DMA方式发送接收数据

    硬件:stm32f103cbt6 软件:STM32F10x_StdPeriph_Lib_V3.5.0 文章目录 头文件 USART3_DR的地址 DMA的通道 DMA的中断 USART接收回调函数 头 ...

  5. STM32 使用 printf 发送数据配置方法 -- 串口 UART, JTAG SWO, JLINK RTT

    STM32串口通信中使用printf发送数据配置方法(开发环境 Keil RVMDK) http://home.eeworld.com.cn/my/space-uid-338727-blogid-47 ...

  6. 为何串口dma发送数据可能不完整

    串口dma数据发送不完整, 1. 通过打印log说明数据合成,送给dma buff都是正常的. 2. 数据通过硬件串口直接配置,是正常的 3. 数据通过单片机dma转发后数据异常,通过检查发现 dma ...

  7. stm32_DMA采集一个AD数据_并通过DMA向串口发送

    这是以前学32的时候写的,那时候学了32之后感觉32真是太强大了,比51强的没影.关于dma网上有许多的资料,关于dma采集ad网上也有很多.亲们搜搜,这里只贴代码了,其实我也想详详细细地叙述一番,但 ...

  8. STM32移植RT-Thread的串口只能接收一个字节数据的问题

    打开设备的函数参数要与注册设备函数参数要一致, 注册设备的函数及其参数如下: /* register UART1 device */ rt_hw_serial_register(&serial ...

  9. 换晶振导致stm32串口数据飞码的解决办法

    一般来说,stm32f107都是用标配的晶振,比如8MHz. 但是,如果用别的晶振,比如13.56M的晶振,那串口接收还正常吗? 根据试验结果,很可能会飞码.比如说用串口助手发送的是0x35,但是在串 ...

随机推荐

  1. C++处理char*,char[],string三种类型间的转换

    前言 在C和C++中,有一个相当重要的部分,就是字符串的编程描述.在学C的时候,很多人习惯了char[],char*表示法,直到遇见了C++后,出现了第三者:string.这时候,很多初学者就会在这三 ...

  2. 手动绕过百度加固Debug.isDebuggerConnected反调试的方法

    本文博客地址:http://blog.csdn.net/qq1084283172/article/details/78237571 1.调用Debug.isDebuggerConnected函数这种反 ...

  3. CVE-2011-0104:Microsoft Office Excel 中的栈溢出漏洞调试分析

    0x01 前言 CVE-2011-0104 是 Microsoft Office 中的 Excel(没有打补丁的情况下)表格程序在处理 TOOLBARDEF 中的 Record 字节时没有对 Len ...

  4. 【Git】5. 远程库(GitHub)相关操作

    之前也提到了,在整个协作的过程中,必不可少的就是远程库了.Github作为一个全球最大的同性交友网站,同样也是一个非常强大的远程库. 现在希望将本地的hello.txt文件也推到github上去,那首 ...

  5. idea插件手动安装

    更多精彩: 例如安装Grep Console 插件  把刚才解压的文件放到  plugins   重启idea   自定义设计

  6. 免费JS甘特图组件dhtmlxgantt

    安装 参考:https://docs.dhtmlx.com/gantt/desktop__install_with_bower.html 可使用NuGet.Bower.npm包管理器安装(应用在asp ...

  7. Python自动扫描出微信不是好友名单

    前言 最近找几个老友准备聊天发现几个已经被删除好友名单,做为潜水党多年的我已经不知道成为多少人的黑名单,但是好友列表却依然有不是好友的名单,面对庞大的好友数量想要清除谈何容易.虽然可以发消息给所有人, ...

  8. UVA OJ 623 500!

    500!  In these days you can more and more often happen to see programs which perform some useful cal ...

  9. Spring Cloud Gateway 之获取请求体(Request Body)的几种方式

    Spring Cloud Gateway 获取请求体 一.直接在全局拦截器中获取,伪代码如下 private String resolveBodyFromRequest(ServerHttpReque ...

  10. jQuery清空元素和克隆元素

    1.清空 $(function () { $('#btn').click(function () { $('#ul1').html('') $('#ul1').empty() $('#ul1').re ...