STM32
直播中

张玲

7年用户 1248经验值
私信 关注
[问答]

请问串口DMA+环形缓冲区如何实现不定长度的数据收发?

请问串口DMA+环形缓冲区如何实现不定长度的数据收发?

回帖(1)

白珊

2021-12-8 14:01:37
下面是串口DMA+环形缓冲区的实现,将读写接口抽象出来,实现不定长度的数据收发。


关于环形缓冲区参考:


http://blog.csdn.net/jieffantfyan/article/details/53572103


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


* 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


#include


#include


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


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


static void port_conf(void)


{
GPIO_InitTypeDef GPIO_InitStructure;


/*console串口引脚配置 ----------------------------------------------------*/


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);


GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_USART3);


GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_USART3);


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;


GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;


GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;


GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;


GPIO_Init(GPIOD, &GPIO_InitStructure);


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;


GPIO_Init(GPIOD, &GPIO_InitStructure);


}


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


* 函数名称:DMA_Conf


* 功能描述: 串口DMA配置(DMA1_Channel4_Stream1->USART3_RX,


*                       DMA1_Channel4_Stream3->USART3_TX)


* 输入参数:none


* 返 回 值:none


* 作    者:roger.luo


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


#if TTY_USE_DMA == 1


static void DMA_Conf(void)


{
DMA_InitTypeDef DMA_Structure;


NVIC_InitTypeDef NVIC_InitStructure;


/* Enable DMA clock */


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);


DMA_DeInit(DMA1_Stream1);


DMA_DeInit(DMA1_Stream3);


while (DMA_GetCmdStatus(DMA1_Stream1) != DISABLE){}


while (DMA_GetCmdStatus(DMA1_Stream3) != DISABLE){}


/*配置串口3接收流 */


DMA_Structure.DMA_Channel = DMA_Channel_4;                    /*DMA1通道4*/


DMA_Structure.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);


DMA_Structure.DMA_Memory0BaseAddr = (uint32_t)dma_rx_buf;


DMA_Structure.DMA_DIR = DMA_DIR_PeripheralToMemory;           /*外设到内存*/


DMA_Structure.DMA_BufferSize = sizeof(dma_rx_buf);


DMA_Structure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;


DMA_Structure.DMA_MemoryInc = DMA_MemoryInc_Enable;


DMA_Structure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;


DMA_Structure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;


DMA_Structure.DMA_Mode = DMA_Mode_Circular;                   /*循环模式*/


DMA_Structure.DMA_Priority = DMA_Priority_Low;


DMA_Structure.DMA_FIFOMode = DMA_FIFOMode_Disable;


DMA_Structure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;


DMA_Structure.DMA_MemoryBurst = DMA_MemoryBurst_Single;


DMA_Structure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;


DMA_Init(DMA1_Stream1, &DMA_Structure);


/*配置串口3发送流 */


DMA_Structure.DMA_PeripheralBaseAddr = (uint32_t)(&USART3->DR);


DMA_Structure.DMA_Memory0BaseAddr = (uint32_t)dma_tx_buf;


DMA_Structure.DMA_DIR = DMA_DIR_MemoryToPeripheral;            /*内存到外设*/


DMA_Structure.DMA_BufferSize = sizeof(dma_tx_buf);


DMA_Structure.DMA_Mode = DMA_Mode_Normal;                      /*正常模式 -*/


DMA_Init(DMA1_Stream3, &DMA_Structure);


/* Enable DMA Stream Transfer Complete interrupt */


DMA_ITConfig(DMA1_Stream1, DMA_IT_TC, ENABLE);


//DMA_ITConfig(DMA1_Stream3, DMA_IT_TC, ENABLE);


/* DMA Stream enable */


DMA_Cmd(DMA1_Stream1, ENABLE);                                 /*使能接收流*/


/* Enable the DMA Stream IRQ Channel */


NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream1_IRQn;


NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;


NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;


NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;


NVIC_Init(&NVIC_InitStructure);


NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;


NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream3_IRQn;


NVIC_Init(&NVIC_InitStructure);


}


#endif


/*******************************************************************************
举报

更多回帖

发帖
×
20
完善资料,
赚取积分