最近经常看见坛友在论坛上问串口接收的问题,我之前刚好由于项目需要用到PLC的PPI协议,需要不停地利用串口接收数据,一开始的时候采用单字节中断的方式接收判断。但是用来做通信的时候需要不停的产生串口接收中断,会严重影响主程序的运行。后来采用DMA接收的方式,但是一般情况下配置的DMA都是接定长的串口数据,对于未知长度的串口数据接收并不适用。后来在网上发现了一种方法可以利用串口的
空闲中断+DMA接收
的方法完美解决此类问题,特别适用于不需要每个就收字节都判断的串口数据接收,下面说一下事实现思路和程序。
实现思路: 采用STM32F103的串口1,并配置成空闲中断模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。那么初始化完成之后,当外部给单片机发送数据的时候,假设这帧数据长度是100个字节,那么在单片机接收到一个字节的时候并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区里面。当整帧数据发送完毕之后串口才会产生一次中断,此时可以利用 DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。
应用对象:适用于各种串口相关的通信协议,如:MODBUS,PPI ;还有类似于GPS数据接收解析,串口WIFI的数据接收等,都是很好的应用对象。
关键代码分析:
usart.H
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
#define DMA_Rec_Len 200 //定义一个长度为200个字节的数据缓冲区。(建议定义的长度比你可能接收到的最长单帧数据长度长!)
void uart_init(u32 bound);
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);
#endif
usart.C
实现思路: 采用STM32F103的串口1,并配置成空闲中断模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。那么初始化完成之后,当外部给单片机发送数据的时候,假设这帧数据长度是100个字节,那么在单片机接收到一个字节的时候并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区里面。当整帧数据发送完毕之后串口才会产生一次中断,此时可以利用 DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。
应用对象:适用于各种串口相关的通信协议,如:MODBUS,PPI ;还有类似于GPS数据接收解析,串口WIFI的数据接收等,都是很好的应用对象。
关键代码分析:
usart.H
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
#define DMA_Rec_Len 200 //定义一个长度为200个字节的数据缓冲区。(建议定义的长度比你可能接收到的最长单帧数据长度长!)
void uart_init(u32 bound);
void MYDMA_Enable(DMA_Channel_TypeDef*DMA_CHx);
#endif