STM32F407VET6串口6+DMA发送队列和DMA接收队列

定义的变量:

#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.源程序下载地址

源代码程序https://download.csdn.net/download/u011671172/31499254icon-default.png?t=L892https://download.csdn.net/download/u011671172/31499254

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值