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

发布者:dswecd最新更新时间:2016-06-02 来源: eefocus关键字:STM32  串口  DMA方式  接收数据 手机看文章 扫描二维码
随时随地手机看文章
环境:

主机:WINXP

开发环境:MDK4.23

MCU:STM32F103CBT6

 

说明:

串口可以配置成用DMA的方式接收数据,不过DMA需要定长才能产生接收中断,如何接收可变长度的数据呢?

方法有以下3种:

1.将RX脚与一路时钟外部引脚相连,当串口一帧发完,即可利用此定时器产生超时中断.这个实时性较高,可以做到1个字节实时监测.

2.不改变硬件,开启一个定时器监控DMA接收,如果超时则产生中断.这个实时性不高,因为超时时间必须要大于需要接收帧的时间,精度不好控制.

3.STM32单片机有的串口可以监测总线是否处于空闲,如果空闲则产生中断.可以用它来监测DMA接收是否完毕.这种方式实时性很高.

本文采用第3种方式.在波特率576000下大数据包冲击证明可行.

 

源代码:

 

//串口接收DMA缓存
#define UART_RX_LEN		128
extern uint8_t Uart_Rx[UART_RX_LEN];

//串口接收DMA缓存
uint8_t Uart_Rx[UART_RX_LEN] = {0};

//---------------------串口功能配置---------------------
	//打开串口对应的外设时钟  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 , ENABLE); 
	//串口发DMA配置  
	//启动DMA时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	//DMA发送中断设置
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	//DMA1通道4配置
	DMA_DeInit(DMA1_Channel4);
	//外设地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
	//内存地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Send_Buffer;
	//dma传输方向单向
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
	//设置DMA在传输时缓冲区的长度
	DMA_InitStructure.DMA_BufferSize = 100;
	//设置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;
	//设置DMA的2个memory中的变量互相访问
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel4,&DMA_InitStructure);
	DMA_ITConfig(DMA1_Channel4,DMA_IT_TC,ENABLE);
	
	//使能通道4
	//DMA_Cmd(DMA1_Channel4, ENABLE);

	//串口收DMA配置  
	//启动DMA时钟
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
	//DMA1通道5配置
	DMA_DeInit(DMA1_Channel5);
	//外设地址
	DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&USART1->DR);
	//内存地址
	DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)Uart_Rx;
	//dma传输方向单向
	DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
	//设置DMA在传输时缓冲区的长度
	DMA_InitStructure.DMA_BufferSize = UART_RX_LEN;
	//设置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;
	//设置DMA的2个memory中的变量互相访问
	DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
	DMA_Init(DMA1_Channel5,&DMA_InitStructure);

	//使能通道5
	DMA_Cmd(DMA1_Channel5,ENABLE);
	
	  
    //初始化参数  
    //USART_InitStructure.USART_BaudRate = DEFAULT_BAUD;  
    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; 
	//初始化串口 
    USART_Init(USART1,&USART_InitStructure);  
    //TXE发送中断,TC传输完成中断,RXNE接收中断,PE奇偶错误中断,可以是多个   
    //USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
	//中断配置
	USART_ITConfig(USART1,USART_IT_TC,DISABLE);
	USART_ITConfig(USART1,USART_IT_RXNE,DISABLE);
	USART_ITConfig(USART1,USART_IT_IDLE,ENABLE);  

	//配置UART1中断  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;               //通道设置为串口1中断  
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;       //中断占先等级0  
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;              //中断响应优先级0  
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                 //打开中断  
    NVIC_Init(&NVIC_InitStructure);   
        
	//采用DMA方式发送
	USART_DMACmd(USART1,USART_DMAReq_Tx,ENABLE);
	//采用DMA方式接收
	USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);
    //启动串口  
    USART_Cmd(USART1, ENABLE); 

 

 

//串口1接收中断   
void USART1_IRQHandler(void)                               
{   
	uint32_t temp = 0;
	uint16_t i = 0;
	
	if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)
    {
    	//USART_ClearFlag(USART1,USART_IT_IDLE);
    	temp = USART1->SR;
    	temp = USART1->DR; //清USART_IT_IDLE标志
    	DMA_Cmd(DMA1_Channel5,DISABLE);

		temp = UART_RX_LEN - DMA_GetCurrDataCounter(DMA1_Channel5);
		for (i = 0;i < temp;i++)
		{
			Data_Receive_Usart = Uart_Rx[i];
		  	//启动串口状态机
			usart_state_run(); 
		}

		//设置传输数据长度
		DMA_SetCurrDataCounter(DMA1_Channel5,UART_RX_LEN);
    	//打开DMA
		DMA_Cmd(DMA1_Channel5,ENABLE);
    } 
	
	__nop(); 
} 

测试结果:

条件:单片机运行于72M,与PC通信速率为460800.PC每隔100ms发送一个9个字节的包:c5 5c 6 0 6F 10 5 4e f7.

测试:单片机每次收到此包,一个IO作电平跳转,然后处理返回一包.

示波器显示:

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

放大显示:

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

 

关键字:STM32  串口  DMA方式  接收数据 引用地址:STM32的串口采用DMA方式接收数据测试

上一篇:STM32 RCC基本原理和配置流程
下一篇:STM32的SPI采用DMA方式传输测试

推荐阅读最新更新时间:2024-03-16 14:55

关于STM32的GPIO配置不同输出速度会有什么影响
今天有人问:GPIO配置不同输出速度会有什么影响?你知道答案吗? 1写在前面 这个问题看起来比较简单,我相信很多人都能说出答案。 但是,很多人都只是停留在表面,至于深层次的含义,估计很少有人思考。 需要更深理解其中含义,可能需要结合特定场景来说,我自己也是在项目中才深刻体会其中含义。 2GPIO输出速度 不管标准外设库,还是STM32CubeMX配置GPIO输出引脚,都会有速度GPIO_InitStruct.Speed这个选项。 类似如下: GPIO_InitStruct.Pin = GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStru
[单片机]
关于<font color='red'>STM32</font>的GPIO配置不同输出速度会有什么影响
3-STM32F1串口通信-查询方式
STM32F1的串口有好几组,STM32的串口还有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持 LIN、 支持调制解调器操作、 智能卡协议和 IrDA SIR ENDEC 规范、具有 DMA等。 虽然有这么多功能,但是这里为了总结串口的原理,采用最简单的查询的方式和电脑进行通信。 其实原子哥的《STM32F1开发指南-库函数版本》已经解释的非常详细了,这里只是按照我自己的风格叙述一遍而已。 使用串口的步骤 1,打开IO时钟 2,配置串口IO口模式,具体方式查看《STM32中文参考手册》8.1.11章节,接收引脚和发送引脚模式不一样的,所以要分别配置。 5,打开串口时钟 6,配置前最好复位下串口,这是个好习
[单片机]
STM32的GPIO口使用
STM32的GPIO类似于51单片机的IO口。只不过STM32的IO口使用时要配置输入/输出模式、速度、而且时钟使能后才能使用。 配置相关代码: GPIO_InitTypeDef GPIO_InitStructure;//定义初始化类型结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打开GPIOA时钟 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;//引脚 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//速度 GPIO_InitStructure.GPIO_M
[单片机]
<font color='red'>STM32</font>的GPIO口使用
安全启动 - STM32安全技术RDP与MPU
检查安全配置 & 构造安全执行环境 同一般的 MCU 启动比较,STM32 安全启动多了一些步骤。首先,安全启动检查相关的安全静态配置是否已经设置完毕,例如 RDP 的级别,PCROP,WRP。如果首次启动则需要配置这些选项字节。然后,安全启动会去设置那些每次运行都需要重新设置的硬件配置 Firewall,MPU,IWDG 的配置。用户可参考下图图示理解安全启动的过程。最后,是对下一级固件进行验证。这个安全的执行环境保证了启动的顺序不会被改变,以及启动代码的保密性。 防外部攻击 此处谈及的外部攻击不是把芯片剖开,使用光学显微镜进行拍照,从而进行逆向工程;或者使用激光对芯片线路进行切割或者连接。这种攻击的成本非常高,需要
[单片机]
安全启动 - <font color='red'>STM32</font>安全技术RDP与MPU
STM32学习笔记:通用定时器基本定时功能
1.STM32的Timer简介 STM32中一共有11个定时器,其中2个高级控制定时器,4个普通定时器和2个基本定时器,以及2个看门狗定时器和1个系统嘀嗒时钟。今天主要是学习8个定时器。  定时器其中TIM1和TIM8是能够产生3对PWM互补输出的高级定时器,常用于三相电机的驱动,时钟由APB2的输出产生。TIM2-TIM5是普通定时器,TIM6和TIM7是基本定时器,其时钟由APB1输出产生。由于STM32的TIMER功能太复杂了,所以只能一点一点的学习。因此今天就从最简单的开始学习起,也就是TIM2-TIM5普通定时器的定时功能。 2.普通定时器TIM2-TIM5 2.1 时钟来源 计数器时钟可以由下列时钟源提供: 内部
[单片机]
<font color='red'>STM32</font>学习笔记:通用定时器基本定时功能
STM32实现任意角度移相全桥PWM
MCU:STM32F334C8T6 最近因某些原因,需要用到任意角度移相的PWM波形来驱动全桥电路,本文记录实现过程。 类似于全桥整流器,将四个二极管换成开关器件,就是全桥逆变器,两个桥臂,需要用四路,两组互补的PWM波形来驱动,但此次的要求中,两组互补PWM波形不是完全相同的,而是有一定的相位差,而且此相位差可能是任意值。 关于互补PWM波的产生,比较简单,上一篇文章中讲了使用通用定时器的方法,本文使用高级定时器或者具有互补输出功能的通用定时器的TIMx_CHy和TIMx_CHyN通道产生,两个定时器分别产生两组互补PWM,并且占空比和频率都可以调节 (参见上一篇文章: 如何利用STM32通用定时器实现输出两路占空比和频率可调的
[单片机]
<font color='red'>STM32</font>实现任意角度移相全桥PWM
STM32新建工程步骤
1、 新建工程,然后选择芯片型号。 选定芯片后添加启动文件.s文件。 2、 将文件添加组进行分类: 其中包含ASM组、USR组、FWlib组合CMSYS组。 l ASM组为.s启动文件; l USR组为用户程序文件组,一般至少需要有main.c,如需要使用中断,将stm32fxxx_it.c也放在该组中; l FWlib组为ST公司提供的官方库文件,如下图所示, 将SRC中的.c文件进行有选择的选入,只选择需要的,免得编译过程太费时,inc文件夹中文.h头文件,可在Target Options中设置包含头文件的路径,将在Target Options设置中具体说明。SRC资源如下所示。 CMSYS组由系统内核文件以及芯片
[单片机]
嵌入式系统中串口通信帧的同步方法
引 言 串口通信是日前单片机和DSP等嵌入式系统之间,以及嵌入式系统与PC机或无线模块之间的一种非常重要且普遍使用的通信方式。在嵌入式系统的硬件结构中,通常只有一个8位或16位的CPU,不仅要完成主流程的工作,同时还要处理随时发生的各种中断,因而嵌入式系统中的串口通信程序设计与PC机有很大的不同。若嵌入式系统中.中断服务子程序在系统运行过程中占用了较多的时间,就有可能在中断眼务子程序正运行时,又产生一个同类型或其他类型的中断,从而造成主程序得不到执行或后续中断数据丢失。所以,嵌入式系统中的串口通信虽然看似简单,但其中仍有许多问题值得研究,例如串口通信过程中的帧同步问题。本文针对该问题给出了逐次比较、基于FIFO队列和基于状态机的
[应用]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

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