F407板子 DMA接收串口数据问题

2019-07-20 01:44发布

我的板子是探索者F407,前几天看到使用串口1配合DMA接收不定长数据,大大减轻CPU载荷这篇帖子,觉得不错,想拿来做实验,结果出问题了,代码反复看了,总是找不出问题,拜托各位大神帮帮忙,我菜鸟一只!!!使用串口1配合DMA接收不定长数据,大大减轻CPU载荷。此贴的描述说明。

最近经常看见坛友在论坛上问串口接收的问题,我之前刚好由于项目需要用到PLC的PPI协议,需要不停地利用串口接收数据,一开始的时候采用单字节中断的方式接收判断。但是用来做通信的时候需要不停的产生串口接收中断,会严重影响主程序的运行。后来采用DMA接收的方式,但是一般情况下配置的DMA都是接定长的串口数据,对于未知长度的串口数据接收并不适用。后来在网上发现了一种方法可以利用串口的空闲中断+DMA接收的方法完美解决此类问题,特别适用于不需要每个就收字节都判断的串口数据接收,下面说一下事实现思路和程序。

实现思路:采用STM32F103的串口1,并配置成空闲中断模式且使能DMA接收,并同时设置接收缓冲区和初始化DMA。那么初始化完成之后,当外部给单片机发送数据的时候,假设这帧数据长度是100个字节,那么在单片机接收到一个字节的时候并不会产生串口中断,而是DMA在后台把数据默默地搬运到你指定的缓冲区里面。当整帧数据发送完毕之后串口才会产生一次中断,此时可以利用DMA_GetCurrDataCounter();函数计算出本次的数据接受长度,从而进行数据处理。


帖子上使用的是103芯片,我是用F407芯片的,不知道是不是两个芯片的DMA模块上使用有区别,我都是照帖子的程序照搬过来的。


MYDMA_Enable(DMA2_Stream5,SEND_BUF_SIZE);                   //恢复DMA指针,等待下一次接受

//开启一次DMA传输
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
{

        DMA_Cmd(DMA_Streamx, DISABLE);                     
       
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}       
               
        DMA_SetCurrDataCounter(DMA_Streamx,ndtr);         

        DMA_Cmd(DMA_Streamx, ENABLE);                     
}

觉得可能是上面这几段代码有问题,感觉DMA指针没有恢复的样子







友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
9条回答
奔跑的蟑螂
2019-07-20 18:44
我把程序DMA初始化时的模式改成了循环模式DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;程序就正常了!!!真的郁闷了,虽然问题是解决了,但我还是不知道为什么。觉得问题是调用MYDMA_Enable(DMA2_Stream5,SEND_BUF_SIZE);这个函数的时候,DMA指针没有复位的原因。但如果是这样,那么为什么会没有复位。
MYDMA_Enable()函数的实现:
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
{      
       DMA_Cmd(DMA_Streamx, DISABLE);                      //1رÕDMA′«êä
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}        //è·±£DMA¿éòÔ±»éèÖà        
        DMA_SetCurrDataCounter(DMA_Streamx,ndtr);          //êy¾Y′«êäá¿  
        DMA_Cmd(DMA_Streamx, ENABLE);                      //¿aÆôDMA′«êä
}          



问题1:如果是DMA指针没有复位的问题,那么是为什么没有复位呢?
问题2:DMA的初始化的循环模式与普通模式到底有什么具体的区别。

[mw_shl_code=c,true]#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "dma.h"

//ALIENTEK ì½Ë÷ÕßSTM32F407¿a·¢°å êμÑé23
//DMA êμÑé-¿aoˉêy°æ±¾  
//¼¼êõÖ§3Ö£owww.openedv.com
//ìÔ±|μêÆì£ohttp://eboard.taobao.com  
//1ãÖYêDDÇòíμç×ó¿Æ¼¼óDÏT1«Ë¾  
//×÷ÕߣoÕyμãÔ-×ó @ALIENTEK

#define SEND_BUF_SIZE 200
extern u8 SendBuff[SEND_BUF_SIZE];       

int main(void)
{
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//éèÖÃÏμí3ÖD¶ÏóÅÏ輶·Ö×é2
        delay_init(168);     //3õê¼»ˉÑóê±oˉêy
        uart_init(115200);        //3õê¼»ˉ′®¿ú2¨ìØÂêÎa115200
        MYDMA_Config(DMA2_Stream5,DMA_Channel_4,(u32)&USART1->DR,(u32)SendBuff,SEND_BUF_SIZE);//DMA2,STEAM7,CH4,íaéèÎa′®¿ú1,′æ′¢Æ÷ÎaSendBuff,3¤¶èÎa:SEND_BUF_SIZE.          
        MYDMA_Enable(DMA2_Stream5,SEND_BUF_SIZE);        //¿aÆôò»′ÎDMA′«êä
       
        while(1);
}

[/mw_shl_code]

[mw_shl_code=c,true]#include "dma.h"                                                                                                                                                     
#include "delay.h"                 
//////////////////////////////////////////////////////////////////////////////////         
//±¾3ìDòÖ»1©Ñ§Ï°ê1óã¬Î′¾-×÷ÕßDí¿é£¬2»μÃóÃóúÆäËüèÎoÎóÃí¾
//ALIENTEK STM32F407¿a·¢°å
//DMA Çy¶ˉ′úÂë          
//ÕyμãÔ-×ó@ALIENTEK
//¼¼êõÂÛì3:www.openedv.com
//′′½¨èÕÆú:2014/5/6
//°æ±¾£oV1.0
//°æè¨ËùóD£¬μá°æ±Ø¾¿¡£
//Copyright(C) 1ãÖYêDDÇòíμç×ó¿Æ¼¼óDÏT1«Ë¾ 2014-2024
//All rights reserved                                                                          
//////////////////////////////////////////////////////////////////////////////////          


//DMAxμĸ÷í¨μàÅäÖÃ
//ÕaàïμÄ′«êäDÎê½êÇ1춨μÄ,Õaμãòa¸ù¾Y2»í¬μÄÇé¿öà′DT¸Ä
//′ó′æ′¢Æ÷->íaéèÄ£ê½/8λêy¾Y¿í¶è/′æ′¢Æ÷Ôöá¿Ä£ê½
//DMA_StreamxMAêy¾Yá÷,DMA1_Stream0~7/DMA2_Stream0~7
//chxMAí¨μàÑ¡Ôñ,@ref DMA_channel DMA_Channel_0~DMA_Channel_7
//par:íaéèμØÖ·
//mar:′æ′¢Æ÷μØÖ·
//ndtr:êy¾Y′«êäá¿  
void MYDMA_Config(DMA_Stream_TypeDef *DMA_Streamx,u32 chx,u32 par,u32 mar,u16 ndtr)
{

        DMA_InitTypeDef  DMA_InitStructure;
       
        if((u32)DMA_Streamx>(u32)DMA2)//μÃμ½μ±Ç°streamêÇêôóúDMA2»1êÇDMA1
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);//DMA2ê±Öóê1Äü
               
        }else
        {
          RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);//DMA1ê±Öóê1Äü
        }
  DMA_DeInit(DMA_Streamx);
       
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}//μè′yDMA¿éÅäÖÃ
       
  /* ÅäÖÃ DMA Stream */
  DMA_InitStructure.DMA_Channel = chx;  //í¨μàÑ¡Ôñ
  DMA_InitStructure.DMA_PeripheralBaseAddr = par;//DMAíaéèμØÖ·
  DMA_InitStructure.DMA_Memory0BaseAddr = mar;//DMA ′æ′¢Æ÷0μØÖ·
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;//íaéèμ½′æ′¢Æ÷Ä£ê½
  DMA_InitStructure.DMA_BufferSize = ndtr;//êy¾Y′«êäá¿
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;//íaéè·ÇÔöá¿Ä£ê½
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//′æ′¢Æ÷Ôöá¿Ä£ê½
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;//íaéèêy¾Y3¤¶è:8λ
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;//′æ′¢Æ÷êy¾Y3¤¶è:8λ
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;// ê1óÃÑ-»·Ä£ê½£¬2»¿é2éóÃÆÕí¨Ä£ê½£¬2»ÖaÎaoÎ
  DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;//ÖDμèóÅÏ輶
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;//′æ′¢Æ÷í»·¢μ¥′Î′«êä
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;//íaéèí»·¢μ¥′Î′«êä
  DMA_Init(DMA_Streamx, &DMA_InitStructure);//3õê¼»ˉDMA Stream
       
}
//¿aÆôò»′ÎDMA′«êä
//DMA_StreamxMAêy¾Yá÷,DMA1_Stream0~7/DMA2_Stream0~7
//ndtr:êy¾Y′«êäá¿  
void MYDMA_Enable(DMA_Stream_TypeDef *DMA_Streamx,u16 ndtr)
{

        DMA_Cmd(DMA_Streamx, DISABLE);                      //1رÕDMA′«êä
       
        while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}        //è·±£DMA¿éòÔ±»éèÖà 
               
        DMA_SetCurrDataCounter(DMA_Streamx,ndtr);          //êy¾Y′«êäá¿  

        DMA_Cmd(DMA_Streamx, ENABLE);                      //¿aÆôDMA′«êä
}       

[mw_shl_code=c,true]#include "sys.h"
#include "usart.h"       
#include "dma.h"
#include "delay.h"
//////////////////////////////////////////////////////////////////////////////////          
//èç1ûê1óÃucos,Ôò°üà¨ÏÂÃæμÄí·Îļt¼′¿é.
#if SYSTEM_SUPPORT_OS
#include "includes.h"                                        //ucos ê1óà         
#endif


//////////////////////////////////////////////////////////////////////////////////         
//±¾3ìDòÖ»1©Ñ§Ï°ê1óã¬Î′¾-×÷ÕßDí¿é£¬2»μÃóÃóúÆäËüèÎoÎóÃí¾
//ALIENTEK STM32F4ì½Ë÷Õß¿a·¢°å
//′®¿ú13õê¼»ˉ                  
//ÕyμãÔ-×ó@ALIENTEK
//¼¼êõÂÛì3:www.openedv.com
//DT¸ÄèÕÆú:2014/6/10
//°æ±¾£oV1.5
//°æè¨ËùóD£¬μá°æ±Ø¾¿¡£
//Copyright(C) 1ãÖYêDDÇòíμç×ó¿Æ¼¼óDÏT1«Ë¾ 2009-2019
//All rights reserved
//********************************************************************************
//V1.3DT¸ÄËμÃ÷
//Ö§3Öêêó|2»í¬ÆμÂêÏÂμÄ′®¿ú2¨ìØÂêéèÖÃ.
//¼óèëá˶ÔprintfμÄÖ§3Ö
//Ôö¼óáË′®¿ú½óêÕÃüáî1|Äü.
//DTÕyáËprintfμúò»¸ö×Ö·û¶aê§μÄbug
//V1.4DT¸ÄËμÃ÷
//1,DT¸Ä′®¿ú3õê¼»ˉIOμÄbug
//2,DT¸ÄáËUSART_RX_STA,ê1μÃ′®¿ú×î′ó½óêÕ×Ö½úêyÎa2μÄ14′η½
//3,Ôö¼óáËUSART_REC_LEN,óÃóú¶¨òå′®¿ú×î′óÔêDí½óêÕμÄ×Ö½úêy(2»′óóú2μÄ14′η½)
//4,DT¸ÄáËEN_USART1_RXμÄê1Äü·½ê½
//V1.5DT¸ÄËμÃ÷
//1,Ôö¼óá˶ÔUCOSIIμÄÖ§3Ö
//////////////////////////////////////////////////////////////////////////////////           


#define SEND_BUF_SIZE 200        //·¢Ëíêy¾Y3¤¶è,×îoÃμèóúsizeof(TEXT_TO_SEND)+2μÄÕûêy±¶.

u8 SendBuff[SEND_BUF_SIZE];        //·¢Ëíêy¾Y»o3åÇø

//////////////////////////////////////////////////////////////////
//¼óèëòÔÏÂ′úÂë,Ö§3Öprintfoˉêy,¶ø2»DèòaÑ¡Ôñuse MicroLIB          
#if 1
#pragma import(__use_no_semihosting)            
//±ê×¼¿aDèòaμÄÖ§3Öoˉêy                 
struct __FILE
{
        int handle;
};

FILE __stdout;      
//¶¨òå_sys_exit()òÔ±üÃaê1óðëÖ÷»úģ꽠  
_sys_exit(int x)
{
        x = x;
}
//Öض¨òåfputcoˉêy
int fputc(int ch, FILE *f)
{        
        while((USART1->SR&0X40)==0);//Ñ-»··¢Ëí,Ö±μ½·¢Ëííê±Ï   
        USART1->DR = (u8) ch;      
        return ch;
}
#endif

#if EN_USART1_RX   //èç1ûê1Äüá˽óêÕ       

void Usart1_Send(u8 *buf,u8 len)
{
        u8 t;
          for(t=0;t<len;t++)                //&#209;-&#187;··¢&#203;íêy&#190;Y
        {                  
                while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);          
                USART_SendData(USART1,buf[t]);
        }         
        while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);               
}

//3&#245;ê&#188;&#187;ˉIO ′&#174;&#191;ú1
//bound:2¨ì&#216;&#194;ê
void uart_init(u32 bound){
   //GPIO&#182;&#203;&#191;úéè&#214;&#195;
  GPIO_InitTypeDef GPIO_InitStructure;
        USART_InitTypeDef USART_InitStructure;
        NVIC_InitTypeDef NVIC_InitStructure;
       
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //ê1&#196;üGPIOAê±&#214;ó
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//ê1&#196;üUSART1ê±&#214;ó

        //′&#174;&#191;ú1&#182;&#212;ó|òy&#189;&#197;&#184;′ó&#195;ó3é&#228;
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9&#184;′ó&#195;&#206;aUSART1
        GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10&#184;′ó&#195;&#206;aUSART1
       
        //USART1&#182;&#203;&#191;ú&#197;&#228;&#214;&#195;
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9ó&#235;GPIOA10
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//&#184;′ó&#195;1|&#196;ü
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        //&#203;ù&#182;è50MHz
        GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //í&#198;íì&#184;′ó&#195;ê&#228;3&#246;
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //é&#207;à-
        GPIO_Init(GPIOA,&GPIO_InitStructure); //3&#245;ê&#188;&#187;ˉPA9£&#172A10

   //USART1 3&#245;ê&#188;&#187;ˉéè&#214;&#195;
        USART_InitStructure.USART_BaudRate = bound;//2¨ì&#216;&#194;êéè&#214;&#195;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;//×&#214;3¤&#206;a8&#206;&#187;êy&#190;Y&#184;&#241;ê&#189;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;//ò&#187;&#184;&#246;í£&#214;1&#206;&#187;
        USART_InitStructure.USART_Parity = USART_Parity_No;//&#206;T&#198;&#230;&#197;&#188;D£&#209;é&#206;&#187;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//&#206;Tó2&#188;têy&#190;Yá÷&#191;&#216;&#214;&#198;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;        //ê&#213;·¢&#196;£ê&#189;
  USART_Init(USART1, &USART_InitStructure); //3&#245;ê&#188;&#187;ˉ′&#174;&#191;ú1
       
        USART_DMACmd(USART1,USART_DMAReq_Rx,ENABLE);   //ê1&#196;ü′&#174;&#191;ú1 DMA&#189;óê&#213;
  USART_Cmd(USART1, ENABLE);  //ê1&#196;ü′&#174;&#191;ú1
       
        //USART_ClearFlag(USART1, USART_FLAG_TC);
       
#if EN_USART1_RX       
        USART_ITConfig(USART1, USART_IT_IDLE, ENABLE);//&#191;a&#198;&#244;&#207;à1&#216;&#214;D&#182;&#207;

        //Usart1 NVIC &#197;&#228;&#214;&#195;
  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//′&#174;&#191;ú1&#214;D&#182;&#207;í¨μà
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//&#199;à&#213;&#188;ó&#197;&#207;è&#188;&#182;3
        NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;                //×óó&#197;&#207;è&#188;&#182;3
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                        //IRQí¨μàê1&#196;ü
        NVIC_Init(&NVIC_InitStructure);        //&#184;ù&#190;Y&#214;&#184;&#182;¨μ&#196;2&#206;êy3&#245;ê&#188;&#187;ˉVIC&#188;&#196;′&#230;&#198;÷&#161;¢

#endif
       
}


void USART1_IRQHandler(void)                        //′&#174;&#191;ú1&#214;D&#182;&#207;·t&#206;&#241;3ìDò
{
        u8 Usart1_Rec_Cnt;
#if SYSTEM_SUPPORT_OS                 //è&#231;1&#251;SYSTEM_SUPPORT_OS&#206;a&#213;&#230;£&#172;&#212;òDèòa&#214;§3&#214;OS.
        OSIntEnter();   
#endif
       
        if(USART_GetITStatus(USART1, USART_IT_IDLE) != RESET)  //&#189;óê&#213;&#214;D&#182;&#207;(&#189;óê&#213;μ&#189;μ&#196;êy&#190;Y±&#216;D&#235;ê&#199;0x0d 0x0a&#189;á&#206;2)
                {
                       
                  USART_ReceiveData(USART1);//&#182;áè&#161;êy&#190;Y ×¢òa£o&#213;a&#190;&#228;±&#216;D&#235;òa£&#172;·&#241;&#212;ò2&#187;&#196;ü1&#187;&#199;&#229;3y&#214;D&#182;&#207;±ê&#214;&#190;&#206;&#187;&#161;£&#206;òò22&#187;&#214;aμà&#206;aé&#182;£&#161;
                  Usart1_Rec_Cnt = SEND_BUF_SIZE-DMA_GetCurrDataCounter(DMA2_Stream5);        //&#203;&#227;3&#246;&#189;ó±&#190;&#214;&#161;êy&#190;Y3¤&#182;è
                  
                        //***********&#214;&#161;êy&#190;Y′|àíoˉêy************//
                        printf ("The lenght:%d ",Usart1_Rec_Cnt);
                        printf ("The data: ");
                        Usart1_Send(SendBuff,Usart1_Rec_Cnt);
                        printf (" Over! ");
                        //*************************************//
                        USART_ClearITPendingBit(USART1, USART_IT_IDLE);         //&#199;&#229;3y&#214;D&#182;&#207;±ê&#214;&#190;
                       
//                        DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5);//&#199;&#229;3yDMA2_Steam7′&#171;ê&#228;íê3é±ê&#214;&#190;                       
               
//                        while(1)
//                        {
//                                if(DMA_GetFlagStatus(DMA2_Stream5,DMA_FLAG_TCIF5)!=RESET)//μè′yDMA2_Steam7′&#171;ê&#228;íê3é
//                                {
//                                        DMA_ClearFlag(DMA2_Stream5,DMA_FLAG_TCIF5);//&#199;&#229;3yDMA2_Steam7′&#171;ê&#228;íê3é±ê&#214;&#190;
//                                        break;
//                                }
//                        }

                        MYDMA_Enable(DMA2_Stream5,SEND_BUF_SIZE);                        //&#187;&#214;&#184;′DMA&#214;&#184;&#213;&#235;£&#172;μè′y&#207;&#194;ò&#187;′&#206;μ&#196;&#189;óê&#213;
     }
               
#if SYSTEM_SUPPORT_OS         //è&#231;1&#251;SYSTEM_SUPPORT_OS&#206;a&#213;&#230;£&#172;&#212;òDèòa&#214;§3&#214;OS.
        OSIntExit();                                                                                           
#endif
}
#endif       




[/mw_shl_code]   



















[/mw_shl_code]


一周热门 更多>