**串口传输大量数据时 总线空闲中断+DMA传输 为CPU减负**

来源:互联网 发布:apache ab post json 编辑:程序博客网 时间:2024/06/17 01:51

串口传输大量数据时 总线空闲中断+DMA传输 为CPU减负
在使用串口接受数据时,如果用while在主函数等待,或者用if在主函数判断,传输少量的标志位可以,程序效率很低,如果用DMA+单字节串口接受中断,这样效率高了,但是当我们需要不间断传输大量数据时,单片机频繁进入中断,有时会影响main()函数的运行,如果采用串口总线空闲触发中断+DMA传输,可以完美的解决这两个问题。
USART_SR寄存器的IDLE位该位的作用时当检测到总线空闲时触发中断,用此标志位我们可以在传输完一帧数据时进入一次中断,这样进入中断次数缩减,main()效率增加
代码如下:

/********************************************************************************  * @file    LSYY_Usart_Api.c  * @author  绿水颖颖  * @version V1.0  * @date    2017.7.26  * @brief   传输大量数据时  空闲中断+DMA传输 为CPU减负  ******************************************************************************  * @attention   *  * ********************************************************************************/#include "LSYY_Usart_Api.h"#include "LSYY_usart.h"#include "LSYY_led.h"/*内存池*/uint8_t DMA_Rece_Buf[USART_RX_BUFF_SIZE];/* *函数名`  : void USURT1_Config(void) *描述        :配置USART1 *输入        :无 *输出        :无 */void USART_Config(void){    GPIO_InitTypeDef GPIO_InitStructure ;    USART_InitTypeDef USART_InitStructure ;    //开启串口的时钟    DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK ,ENABLE);    //开启GPIO的时钟    DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK,ENABLE);    //配置串口1的寄存器    //配置串口1所对应的GPIO口        //配置模式 复用推挽输出模式    GPIO_InitStructure.GPIO_Pin=DEBUG_USART_TX_GPIO_PIN;    GPIO_InitStructure.GPIO_Mode =GPIO_Mode_AF_PP ;    //配置输出速率    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;    //初始化GPIO口    GPIO_Init(DEBUG_USART_TX_GPIO_PORT,&GPIO_InitStructure);    //配置串口1GPIO口的模式    //GPIOA10    //GPIO_InitStructure.GPIO_Pin=DEBUG_USART_RX_GPIO_PORT_PIN;    GPIO_InitStructure.GPIO_Pin=DEBUG_USART_RX_GPIO_PIN;    //配置串口模式    GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING ;    //初始化GPIOA    GPIO_Init(DEBUG_USART_RX_GPIO_PORT,&GPIO_InitStructure);    //配置串口    //设置波特率    USART_InitStructure.USART_BaudRate =DEBUG_USART_BAUDRATE ;    //设置传输字节    USART_InitStructure.USART_WordLength=USART_WordLength_8b;    //设置停止标志位    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 ;    //初始化串口1    USART_Init(DEBUG_USARTx  ,&USART_InitStructure);    /****************************************************注意**************************************************/    /*开启空闲中断*/    USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);    /*开启DMA传输数据*/    USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);       //使能串口    USART_Cmd(DEBUG_USARTx  ,ENABLE);    USART_ClearFlag(USART1, USART_FLAG_TC);         }/**  * @brief  串口空闲中断(IDLE)无  * @param  无  * @retval 无 **/void USART_IDLE_NVIC_Configuration(void){    NVIC_InitTypeDef NVIC_InitStructure;    /* 配置中断源:IDLE */    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;    /* 配置抢占优先级 */    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;    /* 配置子优先级 */    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;    /* 使能中断通道 */    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;    //初始化    NVIC_Init(&NVIC_InitStructure);}/**  * @brief  USART1  DMA配置  * @param  无  * @retval 无 **/void USART_DMA_Config(void){    DMA_InitTypeDef DMA_InitStructure;    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA传输    //相应的DMA配置    DMA_DeInit(DMA1_Channel5);   //将DMA的通道5寄存器重设为缺省值  串口1对应的是DMA通道5    //DMA外设ADC基地址    DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)&USART1->DR;      //DMA内存基地址    DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DMA_Rece_Buf;      //数据传输方向,从外设读取发送到内存    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;     //DMA通道的DMA缓存的大小    DMA_InitStructure.DMA_BufferSize = USART_RX_BUFF_SIZE;      //外设地址寄存器不变    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;     //内存地址寄存器递增    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;     //数据宽度为8位    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;      //数据宽度为8位    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;    //工作在正常缓存模式    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;      //DMA通道 x拥有中优先级     DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;     //DMA通道x没有设置为内存到内存传输    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;     //根据DMA_InitStruct中指定的参数初始化DMA的通道USART1_Tx_DMA_Channel所标识的寄存器    DMA_Init(DMA1_Channel5, &DMA_InitStructure);      //正式驱动DMA传输    DMA_Cmd(DMA1_Channel5, ENABLE); }/**  * @brief  串口DMA配置复位函数  恢复DMA指针  * @param  无  * @retval 无 **/void DeInit_USART_DMA(DMA_Channel_TypeDef*DMA_CHx){    //串口DMA失能    DMA_Cmd(DMA_CHx,DISABLE);    /*DMA传输数值重装*/    DMA_SetCurrDataCounter(DMA_CHx,USART_RX_BUFF_SIZE);    //串口DMA使能    DMA_Cmd(DMA_CHx,ENABLE);}/**  * @brief  串口发送一个数组、字符串  * @param  buf 字符串数组地址 len 数组字符串长度  * @retval 无 **/void Usart1_Send(u8 *buf,u8 len){    u8 t;    //循环发送数据    for(t=0;t<len;t++)          {                  while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);           USART_SendData(USART1,buf[t]);    }        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);     }/**  * @brief  串口中断  * @param  无  * @retval 无 **//*用于计算不同长度数据的长度*/uint32_t DMA_Buf_Cnt;void USART1_IRQHandler(void){    /*串口空闲标志位置1*/    if(USART_GetITStatus(USART1,USART_IT_IDLE)==SET)    {        /* 必须得写,不然IDLE位清除不了 */        USART_ReceiveData(USART1);        /*计算出本帧数据长度*/        DMA_Buf_Cnt=USART_RX_BUFF_SIZE-DMA_GetCurrDataCounter(DMA1_Channel5);        /*测试程序*/        printf("Length:%d\r\n",DMA_Buf_Cnt);        printf("Data:\r\n");        Usart1_Send((uint8_t *)DMA_Rece_Buf,DMA_Buf_Cnt);        printf("\r\n \r\n");        //清除中断标志位        USART_ClearITPendingBit(USART1,USART_IT_IDLE);        /*DMA使能*/        DeInit_USART_DMA(DMA1_Channel5);    }}/**  * @brief  测试函数  * @param  无  * @retval 无 **/void USART_DMA_Test(void){    USART_IDLE_NVIC_Configuration();    USART_DMA_Config();}/**  * @brief  主函数  * @param  无  * @retval 无 **/int main(){    All_Init();    USART_DMA_Test();    while(1)    {        /*所有要处理任务*///      TaskProcess();    }}

串口上位机截图
串口上位机截图

注意内容:
!IDLE位清零必须进行一个读USART_SR寄存器操作,接着进行一个读取USART_DR寄存器操作

本人菜鸟,正在学习中,有问题还请多多交流指正1558194318@qq.com,如有侵权立即删除。

原创粉丝点击