下面是串口DMA+环形缓冲区的实现,数据收发是异步的,不需要死等。
关于环形缓冲区参考:
http://blog.youkuaiyun.com/jieffantfyan/article/details/53572103
实现原理
程序是在串口中断收发方式的基础上设计的,应用层通过环形缓冲区进行串口数据读取,环形缓冲区作为一级缓存,增加DMA作为二级缓存。相对中断方式这种设计可以减少串口进入中断的次数,尤其是在高速波特率的情况下。由于使用DMA收发数据时,必须预设好发送/接收地址、长度等信息,软件内为DMA开辟了16个字节数组作为缓冲区。当发送环形缓存区内有数据需要发送时,程序将前16字节(如果不足则复制实际长度并重新设置DMA发送长度)复制到DMA发送缓冲区内并启动发送,数据发送完成之后将余下的数据按同样的方法复制到DMA发送缓冲区直至数据发送完成。而对于接收来说,处理比发送麻烦一些,需要两个中断服务程序配合,当DMA接收完成16字节之后,软件将这些数据写入到接收环形缓冲区内,以便应用程序读取。因为软件中将DMA接收缓存长度设置为16字节,即DMA必须连续接收到16字节才会进入中断服务程序,但多数情况下接收到的数据长度不可能全是16字节的倍数,比如MCU只收到10字节之后的一段时间内再也收不到数据了。对于这种情况可以使用定时器配合检测,一旦发现长时间收不到串口的数据则将DMA接收缓冲区的数据全部提取出来。由于STM32单片机提供了空闲中断,我们可以利用这个机制解决上述问题,当产生空闲中断时,意味着已经没有数据接收了,这时候则将DMA接收缓冲内的数据提取出来。
外部接口声明
下面将串口的初始化、读、写接口抽象出来。
/******************************************************************************
* Copyright (C) 2016, roger
* All rights reserved.
*
* 文件名称: tty.h
* 摘 要:控制台驱动
*
* 当前版本: 3.0
* 作 者: roger
* 完成日期: 2016-09-24
*
* 取代版本: 2.0
* 原作者 : roger
* 完成日期: 2015-07-08
******************************************************************************/
#ifndef _TTY_H_
#define _TTY_H_
#define TTY_BAUDRATE 115200 /*波特率 ------------*/
#define TTY_TXBUF_SIZE 256 /*发送缓冲区长度 -----*/
#define TTY_RXBUF_SIZE 256 /*接收缓冲区长度 -----*/
#define TTY_DMA_TX_LEN 10 /*DMA 发送缓冲区 ----*/
#define TTY_DMA_RX_LEN 10 /*DMA 接收缓冲区 ----*/
#define TTY_USE_DMA 1 /*启用DMA -----------*/
/* Exported Structs ---------------------------------------------------------*/
typedef struct
{
void (*init)(void); /*初始化 --------*/
unsigned int (*write)(void *buf, unsigned int len); /*数据写 --------*/
unsigned int (*read) (void *buf, unsigned int len); /*读数据 --------*/
void (*puts)(const char *str); /*输入一个字符串 */
void (*clr)(void); /*清除接收缓冲区 */
unsigned int (*buflen)(void); /*接收缓冲区的长度*/
void (*printf)(const char *format, ...); /*格式化打印 ----*/
}tty_t;
/* Exported variables ------------------------------------------------------- */
extern const tty_t tty;
#endif
接口实现 ##‘
/******************************************************************************
* Copyright (C) 2016, roger
* All rights reserved.
*
* 文件名称: tty.c
* 摘 要:打印串口驱动
*
* 当前版本: 3.0
* 作 者: roger
* 完成日期: 2016-09-24
*
* 取代版本: 2.0
* 原作者 : roger
* 完成日期: 2015-07-08
******************************************************************************/
/* Includes ------------------------------------------------------------------*/
#include "tty.h"
#include "ringbuffer.h"
#include "stm32f4xx.h"
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
static unsigned char rxbuf[TTY_TXBUF_SIZE]; /*接收缓冲区 ------------*/
static unsigned char txbuf[TTY_RXBUF_SIZE]; /*发送缓冲区 ------------*/
static ring_buf_t ringbuf_send, ringbuf_recv; /*收发缓冲区管理 ---------*/
#if TTY_USE_DMA == 1
static unsigned char dma_tx_buf[TTY_DMA_TX_LEN];/*DMA发送缓冲区 ---------*/
static unsigned char dma_rx_buf[TTY_DMA_RX_LEN];/*DMA接收缓冲区 ---------*/
#endif
/*******************************************************************************
* 函数名称:port_conf
* 功能描述:打印串口配置(PD8->USART3_TX, PD9->USART3_RX)
* 输入参数:none
* 返 回 值:none
* 作 者:roger.luo
*****