STM32F407的串口采用DMA收发数据

发布者:朱颜素韵最新更新时间:2020-09-24 来源: eefocus关键字:STM32F407  串口  DMA  收发数据 手机看文章 扫描二维码
随时随地手机看文章

环境:


主机:WIN8


开发环境:MDK5.13


mcu: stm32f407VGT6




说明:


之前用STM32F103实现DMA收发串口数据,现在项目中采用STM32F407,所以将此机制移植到F4上。


STM32F103上用DMA收发串口数据文章:


STM32的串口采用DMA方式发送数据测试


STM32的串口采用DMA方式接收数据测试




源代码:


串口初始化代码:


/*********************************************************************

* 初始化串口

**********************************************************************/

 

static void init_uart(void)

{

//定义中断结构体

NVIC_InitTypeDef NVIC_InitStructure ;

//定义IO初始化结构体

  GPIO_InitTypeDef GPIO_InitStructure;

//定义串口结构体  

USART_InitTypeDef USART_InitStructure;

//定义DMA结构体

DMA_InitTypeDef DMA_InitStructure;

 

//打开串口对应的外设时钟  

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

 

//串口发DMA配置  

//启动DMA时钟

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

//DMA发送中断设置

NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream6_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);

//DMA通道配置

DMA_DeInit(DMA1_Stream6);

DMA_InitStructure.DMA_Channel = DMA_Channel_4; 

//外设地址

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);

//内存地址

DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Tx_Buf_Gsm;

//dma传输方向

DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;

//设置DMA在传输时缓冲区的长度

DMA_InitStructure.DMA_BufferSize = TX_LEN_GSM;

//设置DMA的外设递增模式,一个外设

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

//设置DMA的内存递增模式

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

//外设数据字长

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

//内存数据字长

DMA_InitStructure.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;

//设置DMA的传输模式

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

//设置DMA的优先级别

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

//指定如果FIFO模式或直接模式将用于指定的流 : 不使能FIFO模式  

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;    

//指定了FIFO阈值水平

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;        

//指定的Burst转移配置内存传输 

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;       

//指定的Burst转移配置外围转移 */  

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 

 

//配置DMA1的通道         

DMA_Init(DMA1_Stream6, &DMA_InitStructure);  

//使能中断

DMA_ITConfig(DMA1_Stream6,DMA_IT_TC,ENABLE);   

 

//串口收DMA配置  

//启动DMA时钟

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);

//DMA通道配置

DMA_DeInit(DMA1_Stream5);

DMA_InitStructure.DMA_Channel = DMA_Channel_4;

//外设地址

DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&USART2->DR);

//内存地址

DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Rx_Buf_Gsm;

//dma传输方向

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

//设置DMA在传输时缓冲区的长度

DMA_InitStructure.DMA_BufferSize = RX_LEN_GSM;

//设置DMA的外设递增模式,一个外设

DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

//设置DMA的内存递增模式

DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

//外设数据字长

DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

//内存数据字长

DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

//设置DMA的传输模式

DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

//设置DMA的优先级别

DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;

//指定如果FIFO模式或直接模式将用于指定的流 : 不使能FIFO模式  

DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;    

//指定了FIFO阈值水平

DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;        

//指定的Burst转移配置内存传输 

DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;       

//指定的Burst转移配置外围转移 */  

DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; 

//配置DMA1的通道         

DMA_Init(DMA1_Stream5, &DMA_InitStructure);  

//使能通道

DMA_Cmd(DMA1_Stream5,ENABLE);

    //初始化串口参数  

    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_InitStructure.USART_BaudRate = DEFAULT_BAUD_GSM; 

//初始化串口 

    USART_Init(USART2,&USART_InitStructure);  

//中断配置

USART_ITConfig(USART2,USART_IT_TC,DISABLE);

USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);

USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);  

 

//配置中断  

//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);

    NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;               //通道设置为串口中断  

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;       //中断占先等级

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;              //中断响应优先级 

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //打开中断  

    NVIC_Init(&NVIC_InitStructure);   

        

//采用DMA方式发送

USART_DMACmd(USART2,USART_DMAReq_Tx,ENABLE);

//采用DMA方式接收

USART_DMACmd(USART2,USART_DMAReq_Rx,ENABLE);

 

//中断配置

USART_ITConfig(USART2,USART_IT_TC,DISABLE);

USART_ITConfig(USART2,USART_IT_RXNE,DISABLE);

USART_ITConfig(USART2,USART_IT_TXE,DISABLE);

USART_ITConfig(USART2,USART_IT_IDLE,ENABLE);  

    //启动串口  

    USART_Cmd(USART2, ENABLE);    

 

    //设置IO口时钟      

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); 

GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2);  

GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2);

 

    //管脚模式:输出口

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    //类型:推挽模式

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    //上拉下拉设置

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

//IO口速度

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

    //管脚指定

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;

    //初始化

GPIO_Init(GPIOA, &GPIO_InitStructure);

    //管脚模式:输入口

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    //上拉下拉设置

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    //管脚指定

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;

    //初始化

GPIO_Init(GPIOA, &GPIO_InitStructure);      

}



发送数据:


/*********************************************************************

* 接口函数:向gsm模块发送数据

*参数:data:发送数据存放地址

*   size:发送数据字节数

**********************************************************************/

 

void drv_gsm_tx(uint8_t *data,uint16_t size)

{

//等待空闲

while (Flag_Tx_Gsm_Busy);

Flag_Tx_Gsm_Busy = 1;

//复制数据

memcpy(Tx_Buf_Gsm,data,size);

//设置传输数据长度

DMA_SetCurrDataCounter(DMA1_Stream6,size);

//打开DMA,开始发送

  DMA_Cmd(DMA1_Stream6,ENABLE);

}




中断处理函数:


/*********************************************************************

* 接口函数:DMA发送中断处理函数

**********************************************************************/

 

void drv_gsm_deal_irq_dma_tx(void)

{

if(DMA_GetITStatus(DMA1_Stream6,DMA_IT_TCIF6) != RESET) 

{

//清除标志位

DMA_ClearFlag(DMA1_Stream6,DMA_FLAG_TCIF6);

//关闭DMA

DMA_Cmd(DMA1_Stream6,DISABLE);

//打开发送完成中断,发送最后两个字节

USART_ITConfig(USART2,USART_IT_TC,ENABLE);

}

}

 

/*********************************************************************

* 处理发送完成中断

*返回:0:未产生,1:已经产生

**********************************************************************/

 

uint8_t drv_gsm_deal_irq_tx_end(void)

{

if(USART_GetITStatus(USART2, USART_IT_TC) != RESET)

    {

//关闭发送完成中断

USART_ITConfig(USART2,USART_IT_TC,DISABLE);

//发送完成

        Flag_Tx_Gsm_Busy = 0;

return 1;

    } 

return 0;

}

 

/*********************************************************************

* 处理接收完成中断

*参数:buf:接收的数据

*     len:接收的数据长度

*返回:0:未产生,其他:已经产生,此值为接收的数据长度

**********************************************************************/

 

uint8_t drv_gsm_deal_irq_rx_end(uint8_t *buf)

{

uint16_t len = 0;

//接收完成中断

if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)

    {

    USART2->SR;

    USART2->DR; //清USART_IT_IDLE标志

//关闭DMA

    DMA_Cmd(DMA1_Stream5,DISABLE);

//清除标志位

DMA_ClearFlag(DMA1_Stream5,DMA_FLAG_TCIF5);

//获得接收帧帧长

len = RX_LEN_GSM - DMA_GetCurrDataCounter(DMA1_Stream5);

memcpy(buf,Rx_Buf_Gsm,len);

//设置传输数据长度

DMA_SetCurrDataCounter(DMA1_Stream5,RX_LEN_GSM);

    //打开DMA

DMA_Cmd(DMA1_Stream5,ENABLE);

 

return len;

    } 

return 0;

}



中断函数:


/*********************************************************************

* GSM模块:DMA发送中断处理函数

**********************************************************************/

 

void DMA1_Stream6_IRQHandler(void)

{

    gsm_dma_tx_irq_handler();

}

   

/*********************************************************************

* GSM模块:串口中断处理函数

**********************************************************************/

 

void USART2_IRQHandler(void) 

{

gsm_irq_handler();

}

注意:


接收完成中断中必须要清除标志位


//清除标志位

DMA_ClearFlag(DMA1_Stream5,DMA_FLAG_TCIF5);

并且必须在关闭DMA之后,这个语句在F103中并非必须的


中断处理函数:


/*********************************************************************

* 接口函数:DMA发送中断处理函数

**********************************************************************/

 

void gsm_dma_tx_irq_handler(void)

{

inf_gsm_deal_irq_dma_tx();

}

   

/*********************************************************************

* 接口函数:串口中断处理函数

*参数:data:接收数据存放地址

*返回:接收数据长度

**********************************************************************/

[1] [2]
关键字:STM32F407  串口  DMA  收发数据 引用地址:STM32F407的串口采用DMA收发数据

上一篇:stm32F4各个库文件的作用分析
下一篇:STM32F407上移植emwin

推荐阅读最新更新时间:2024-11-07 11:51

51单片机学习:串口通信实验
实验名称:串口通信实验 接线说明: 实验现象:下载程序后,当串口助手发送数据给单片机,单片机原封不动转发给串口助手显示 注意事项:使用黄色跳线帽将CH340旁的P5端子的UTX和P30短接,URX和P31短接,出厂默认已短接好 ***************************************************************************************/ #include reg52.h typedef unsigned int u16; //对系统默认数据类型进行重定义 typedef unsigned char u8; /***************************
[单片机]
基于CPLD/FPGA的多串口设计与实现
摘要:在工业控制中如何提高一对多的串口通讯可靠性和系统的集成性成为研究热点。本文利用嵌入式技术,提出基于CPLD/FPGA的多串口扩展设计方案。实现并行口到多个全双工异步通讯口之间的转换,并根据嵌入式系统实时性的需要,在每个UART接收器中开辟了8个接收缓冲单元,实现高速嵌入式CPU与RS232通讯设备之间的速度匹配,同时,串行口波特率等参数可根据需要进行设置。通过实践证明,本文设计的基于CPLD/FPGA的多串口完全符合工业控制中一对多串口通讯的要求。 关键词:CPLD/FPGA;多串口扩展;全双工;异步通信;嵌入式系统 在工业控制中,设备的通讯与控制主要采用简洁高效的串口方式进行。工控机通过PCI扩展卡方式进行串口的
[嵌入式]
基于CPLD/FPGA的多<font color='red'>串口</font>设计与实现
LabVIEW串口通信详解
很早就想做一个类似的东西了,正好这学期学了LabVIEW,作业就交了这个,基于LabVIEW的 串口示波器 上位机。 1.程序界面: 功能介绍:左边上方串口接收区,下方为串口字符发送区。右方为一个波形图表,在程序内部每次将串口发送过来的数据,以f%格式化,显示在波形图表上。 按钮介绍:从左至右依次,发送按钮;清除计数按钮;打开/关闭串口按钮;清除接收区数据;清除波形图表;保存波形;退出程序。 2.主程序框图: 主程序框图介绍:主程序框图主要由3个状态组成:程序的初始化,程序事件的响应,程序的退出。 状态Init:程序初始化,主要把OpenCom等按钮,串口状态,串口接收字符串,波形图标,TX/RX计数等控件,
[测试测量]
LabVIEW<font color='red'>串口</font>通信详解
40.DMA基本原理与配置
一。DMA简介 如果没有DMA,我们要把一个数据从一个空间复制到另外一个空间,需要先把数据读进CPU,然后再写到另外一个空间。当用了DMA后就不再需要CPU,DMA控制器可以开启一个传输通道,直接把数据从一个空间传到另外一个空间。 二。DMA框图 DMA1有7个通道,DMA2有5个通道。仲裁器用来处理优先级。 DMA请求来自于外设,经过仲裁器连接到相应的通道,通过DMA总线去访问存储器。 DMA可以把外设某个寄存器的数据通过DMA开辟一个通道直接传输到存储器,或者从存储器传输到外设。 三。STM32的DMA的特性 注: 每个通道对应不同的外设,使用的时候要根据外设选择相对应的通道。 四。DMA
[单片机]
40.<font color='red'>DMA</font>基本原理与配置
STM32+按键调控PWM输出+串口输出占空比
GPIO.c #include STM32Lib\stm32f10x.h #include hal.h /******************************************************************************* * Function Name : GPIO_Configuration * 设置PD3,PD4,PD5,PD6为键盘输入 * 设置PB0,5,8,9; PC5,7; PD7 ;PA8 为输出LED灯 *******************************************************************************/ v
[单片机]
STM32基于固件库学习笔记(6)使用DMA实现USART1发送数据
DMA简介 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。换而言之就是当外设有数据发送给mcu,此时可以使用DMA接收到用户定义空间(不占用cpu),接收完成在产生中断发给mcu(才占用CPU)反正一样。 当CPU和DMA同时访问相同的目标(RAM或外设)时,DMA请求会暂停CPU访问系统总线达若干个周期,总线仲裁器执行循环调度,以保证CPU至少可以得到一半的系统总线(存储器或外设)带宽。 两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设
[单片机]
STM32基于固件库学习笔记(6)使用<font color='red'>DMA</font>实现USART1发送<font color='red'>数据</font>
基于MSComm控件的GPS接收机数据终端接口设计
1 引 言 全球定位系统(GPS)是20世纪70年代由美国陆海空三军联合研制的空间卫星导航定位系统,其目的是为美国军方提供实时精确的定位、导航和授时等服务。通常GPS系统由3个部份组成:空间部分:包括24颗GPS卫星;地面控制部分:对GPS卫星实施监控;用户部分:接收来自GPS卫星的定位等信息,通常包括天线和接收机等设备。GPS系统在进行定位时,必须要确定用户所在的位置(包括x,y,z三个坐标),同时还要考虑到卫星时钟与接收机时钟之间的误差t,要解算4个未知量必须建立4个方程,通常可以通过测量卫星与-用户之间的伪距,来建立相应的方程,因此需要同时观测4颗卫星,才能实现精确定位。随着时代发展,GPS系统不再局限于美国军方,已被广泛
[应用]
基于STM32介绍DMA的双缓冲模式
目前STM32家族中有些系列支持DMA的双缓冲模式,比如STM32F2/STM32F4/STM32F7等系列。尤其随着人们对STM32F4/F7系列应用不断拓宽和加深,在设计中运用到DMA双缓冲的场合也越来越多。STM32芯片中的DMA又可分为两大类,一类是通用DMA,一类是专用DMA,比如用于USB,TFT LCD,ETHERNET等外设应用上的DMA。这里要谈的是基于通用DMA的话题,不妨以STM32F4系列芯片为例。 关于STM32F4的DMA双缓冲传输在STM32F4系列的参考手册里做了简单描述。因为它是基于介绍了单缓冲模式的DMA介绍之后接着介绍的,稍显言简意赅。 相比单缓冲的数据流,双缓冲多了一个DMA存储区和
[单片机]
基于STM32介绍<font color='red'>DMA</font>的双缓冲模式
热门资源推荐
热门放大器推荐
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved