定义的变量:
#define USART_DMA_USING 1
#define USART_DMA_IDLE 0 //空闲标志
#define USART6_RX_BUF_MAX 1024
#define USART6_TX_BUF_MAX 1024
#define UART_QUEUE_BUF_MAX 1024
#define UART_UPPER_QUEUE_MAX 20 //队列长度
u8 Usart6RxBuf[USART6_RX_BUF_MAX];
u8 Usart6TxBuf[USART6_TX_BUF_MAX];
u16 Usart6RxNum;
u16 Usart6TxLen;
u16 Usart6RxNum;
u8 SendingFlagUart;
typedef enum
{
kUART_QUEUE_IDLE = 0, //没有要处理的数据
kUART_QUEUE_FLAG, //有要处理的数据
}UART_QUEUE_CMD;
typedef struct _usartQueueBuffer
{
u8 uartQueueBuf[UART_QUEUE_BUF_MAX]; //发送BUF
u16 uartQueueLen; //发送数据长度
UART_QUEUE_CMD uartQueueCmdFlag; //是否要处理
}UsartQueueBuffer;
UsartQueueBuffer UsartUpperRxBuf[UART_UPPER_QUEUE_MAX]; //发送数据队列
UsartQueueBuffer UsartUpperTxBuf[UART_UPPER_QUEUE_MAX]; //接收数据队列
u8 UsartTxQueueOrder;
u8 UsartRxQueueOrder;
u8 ComUpperRxDataBufRcv[UART_QUEUE_BUF_MAX]; //接收数据BUFfalo
1.初始化串口
void UsartInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
// NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE); //使能GPIOC时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART6,ENABLE); //使能USART6时钟
//串口6对应引脚复用映射
GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_USART6); //GPIOC6复用为USART6
GPIO_PinAFConfig(GPIOC,GPIO_PinSource7,GPIO_AF_USART6); //GPIOC7复用为USART6
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; //GPIOC6与GPIOC7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOC,&GPIO_InitStructure); //初始化PC6,PC7
/* 配置串口硬件参数 */
USART_InitStructure.USART_BaudRate = 115200; //波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式
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_Init(USART6, &USART_InitStructure); //初始化串口6
// USART_ClearFlag(USART6, USART_FLAG_RXNE);
// USART_ClearFlag(USART6, USART_FLAG_TC);
// USART_ITConfig(USART6, USART_IT_RXNE, ENABLE); // 使能接收中断
//用于判断是否接收完一包数据.
USART_ITConfig(USART6, USART_IT_IDLE, ENABLE); // 使能串口空闲中断
USART_Cmd(USART6, ENABLE); // 串口使能
// 初始化相应串口接收和发送缓存
DriveUartBuffClearInit(Usart6RxBuf,USART6_RX_BUF_MAX);
DriveUartBuffClearInit(Usart6TxBuf,USART6_TX_BUF_MAX);
NVIC_EnableIRQ(USART6_IRQn); // 使能串口中断
USART_DMACmd(USART6,USART_DMAReq_Tx,ENABLE); //使能串口1的DMA发送
USART_DMACmd(USART6,USART_DMAReq_Rx,ENABLE); //使能串口1的DMA接收
// 串口DMA初始化
dma2_Stream2_init();
dma2_Stream6_init();
}
2.初始化发送DMA
void dma2_Stream6_init(void)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2时钟使能
while (DMA_GetCmdStatus(DMA2_Stream6) != DISABLE)
{
;
}//等待DMA2_Stream6可配置
DMA_DeInit(DMA2_Stream6);
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_5; //通道4
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART6->DR; //DMA 对应的外设USART4->DR地址
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)Usart6TxBuf; // 内存存储基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;//存储器到外设模式
DMA_InitStructure.DMA_BufferSize = USART6_TX_BUF_MAX;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度 8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//中等优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //FIFO模式不开启
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_Init(DMA2_Stream6, &DMA_InitStructure);//初始化DMA Stream
// DMA_Cmd(DMA2_Stream6, ENABLE); /* DMA2_Stream6 enable */ // 在发送的时候才开启DMA
//DMA NVIC
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA2_Stream6,DMA_IT_TC,ENABLE);
}
3.初始化接收DMA
void dma2_Stream2_init(void)
{
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA1时钟使能
while (DMA_GetCmdStatus(DMA2_Stream2) != DISABLE)
{
;
}//等待DMA2_Stream2可配置
DMA_DeInit(DMA2_Stream2);
/* 配置 DMA Stream */
DMA_InitStructure.DMA_Channel = DMA_Channel_5; //通道4
DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART6->DR; //DMA 对应的外设USART1->DR地址
DMA_InitStructure.DMA_Memory0BaseAddr = (u32)Usart6RxBuf; // 内存存储基地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory ;//外设到存储器模式
DMA_InitStructure.DMA_BufferSize = USART6_RX_BUF_MAX;//数据传输量
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//外设非增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//存储器增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//外设数据长度:8位
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//存储器数据长度 8位
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;// 循环模式
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//高优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //FIFO模式不开启
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//存储器突发单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//外设突发单次传输
DMA_Init(DMA2_Stream2, &DMA_InitStructure);//初始化DMA Stream
DMA_Cmd(DMA2_Stream2, ENABLE); /* DMA2_Stream2 enable */
//DMA NVIC
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA2_Stream2,DMA_IT_TC,ENABLE);
}
4.中断处理
//串口6 中断函数
void USART6_IRQHandler(void)
{
u8 clear;
//用于判断是否接收完一包数据.
if (USART_GetITStatus(USART6, USART_IT_IDLE)==SET)
{
USART_ClearITPendingBit(USART6, USART_IT_IDLE);
clear = USART6->SR;
clear = USART6->DR;
clear = clear;//无任何作用 去除编译告警
DMA_Cmd(DMA2_Stream2, DISABLE); //关闭DMA,防止处理期间有数据
Usart6RxNum = USART6_RX_BUF_MAX - DMA_GetCurrDataCounter(DMA2_Stream2);
UsartUpperRxBuf[UsartRxQueueOrder].uartQueueLen = Usart6RxNum;
DriveUsartGetRecvData(UsartUpperRxBuf[UsartRxQueueOrder].uartQueueBuf,Usart6RxNum);
UsartUpperRxBuf[UsartRxQueueOrder].uartQueueCmdFlag = USART_DMA_USING;
UsartRxQueueOrder++;
if(UsartRxQueueOrder >= UART_UPPER_QUEUE_MAX)
{
UsartRxQueueOrder = 0;
}
DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TCIF2 | DMA_FLAG_FEIF2 | DMA_FLAG_DMEIF2 | DMA_FLAG_TEIF2 | DMA_FLAG_HTIF2);//清除DMA1_Steam0传输完成标志
DMA_Cmd(DMA2_Stream2, ENABLE); //打开DMA,
}
if(USART_GetFlagStatus(USART6,USART_FLAG_ORE) == SET) //溢出
{
USART_ClearFlag(USART6,USART_FLAG_ORE); //读SR
USART_ReceiveData(USART6); //读DR
}
}
void DMA2_Stream2_IRQHandler(void)
{
//清除标志
if(DMA_GetFlagStatus(DMA2_Stream2,DMA_FLAG_TCIF2)!=RESET)//等待DMA2_Steam2传输完成
{
DMA_Cmd(DMA2_Stream2, DISABLE); //关闭DMA,防止处理期间有数据
Usart6RxNum = 0;
DMA_ClearFlag(DMA2_Stream2,DMA_FLAG_TCIF2 | DMA_FLAG_FEIF2 | DMA_FLAG_DMEIF2 | DMA_FLAG_TEIF2 | DMA_FLAG_HTIF2);//清除DMA1_Steam1传输完成标志
DMA_SetCurrDataCounter(DMA2_Stream2, USART6_RX_BUF_MAX);
DMA_Cmd(DMA2_Stream2, ENABLE); //打开DMA,
}
}
//串口6发送完成中断
void DMA2_Stream6_IRQHandler(void)
{
//清除标志
if(DMA_GetFlagStatus(DMA2_Stream6,DMA_FLAG_TCIF6)!=RESET)//等待DMA1_Steam3传输完成
{
SendingFlagUart = USART_DMA_IDLE;
DMA_ClearFlag(DMA2_Stream6,DMA_FLAG_TCIF6);//清除DMA1_Steam3传输完成标志
}
}
5.接收数据处理
void ComUpperRxDataHandle(void)
{
static u8 rxUpperOrder = 0;
if(UsartRxQueueOrder != rxUpperOrder)//接受一包数据中断标志位
{
memcpy(ComUpperRxDataBufRcv,UsartUpperRxBuf[rxUpperOrder].uartQueueBuf,UsartUpperRxBuf[rxUpperOrder].uartQueueLen);
memset(UsartUpperRxBuf[rxUpperOrder].uartQueueBuf, 0, UsartUpperRxBuf[rxUpperOrder].uartQueueLen);
UsartUpperRxBuf[rxUpperOrder].uartQueueLen = 0;
UsartUpperRxBuf[rxUpperOrder].uartQueueCmdFlag = USART_DMA_IDLE;
rxUpperOrder++;
if(rxUpperOrder >= UART_UPPER_QUEUE_MAX)
{
rxUpperOrder = 0;
}
//在这里对ComUpperRxDataBufRcv进行解析
if((ComUpperRxDataBufRcv[0] == 0xAA) && (ComUpperRxDataBufRcv[0] == 0x55))
{
}
}
}
6.main函数
int main(void)
{
u8 i;
UsartInit();
//测试发送数据,发送10包数据,每包数据从0~19
for(i = 0; i < 20; i++)
{
sendTest[i] = i;
}
for(i = 0 ; i < 10 ; i++)
{
UsartSendData(sendTest,20);
}
while(1)
{
Usart6_SendData();
ComUpperRxDataHandle();
}
}
7.源程序下载地址