打印
[STM32F4]

大声的问一句关于STM32F407 DMA重启的问题解决了么,快疯了。

[复制链接]
11358|26
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lee_hwa|  楼主 | 2013-12-17 16:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
碰到DMA关闭后重新开启DMA不能产生中断的问题。
DMA_Mode_Circular,DMA_Mode_Normal两个模式都不行,

DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
然后
DMA_Cmd(DMA2_Stream0, DISABLE);  
DMA_Cmd(DMA2_Stream0, ENABLE);
第二次还是进不了中断。
沙发
dirtwillfly| | 2013-12-17 20:37 | 只看该作者
你试试:先把你用DMA的外设关闭,后重新配置DMA,然后开启DMA和外设

使用特权

评论回复
板凳
feilusia| | 2013-12-17 20:59 | 只看该作者
DMA不能随便关的吧,要先查询一些标志位,比如传输是否结束等,判断是否可关才关。

使用特权

评论回复
地板
lee_hwa|  楼主 | 2013-12-18 09:06 | 只看该作者
dirtwillfly 发表于 2013-12-17 20:37
你试试:先把你用DMA的外设关闭,后重新配置DMA,然后开启DMA和外设

我把AD先关闭了,然后再关闭DMA。也不行。

使用特权

评论回复
5
lee_hwa|  楼主 | 2013-12-18 09:07 | 只看该作者
feilusia 发表于 2013-12-17 20:59
DMA不能随便关的吧,要先查询一些标志位,比如传输是否结束等,判断是否可关才关。 ...

哦,你是试过么?我试了试,等传输结束后再关闭,还是不行。

使用特权

评论回复
6
qzwx741| | 2013-12-18 09:09 | 只看该作者
看2L,先把你用DMA的外设关闭,后重新配置DMA,然后开启DMA和外设,应该是这个问题

使用特权

评论回复
7
ticomi| | 2013-12-18 09:12 | 只看该作者
我的一段关闭DMA的代码,使用正常:实在DMA接收完成的中断里关闭的
DMA_Cmd(DMA2_Stream0, DISABLE);        //Disable DMA2 Stream0
        DMA_Cmd(DMA2_Stream3, DISABLE);        //Disable DMA2 STream3

        DMA_ClearFlag(DMA2_Stream3, DMA_FLAG_TCIF3);        //Clear DMA2 STream3 Transfer Complete Flag
        DMA_ClearFlag(DMA2_Stream0, DMA_FLAG_TCIF0);        //Clear DMA2 STream0 Transfer Complete Flag       
       
       
       
        DMA_SetCurrDataCounter(DMA2_Stream3, ADC_TX_SIZE);        //Enable DMA2 Stream3
        DMA_SetCurrDataCounter(DMA2_Stream0, ADC_RX_SIZE);        //Enable DMA2 Stream0       

使用特权

评论回复
8
lee_hwa|  楼主 | 2013-12-18 09:49 | 只看该作者
ticomi 发表于 2013-12-18 09:12
我的一段关闭DMA的代码,使用正常:实在DMA接收完成的中断里关闭的

你的是STM32F407么

使用特权

评论回复
9
lee_hwa|  楼主 | 2013-12-18 09:54 | 只看该作者
ticomi 发表于 2013-12-18 09:12
我的一段关闭DMA的代码,使用正常:实在DMA接收完成的中断里关闭的

据说STM32F103没有问题

使用特权

评论回复
10
lee_hwa|  楼主 | 2013-12-18 09:56 | 只看该作者
DMA_SetCurrDataCounter(DMA2_Stream0, ADC_RX_SIZE)可以  Enable DMA2 Stream0     是什么道理? ADC_RX_SIZE是多少

使用特权

评论回复
11
lee_hwa|  楼主 | 2013-12-18 10:18 | 只看该作者
请各位专家指点一下:
DMA_InitTypeDef DMA_InitStructure;        //DMA³õʼ»¯½á¹¹ÌåÉùÃ÷
void DMA_Config(void)
{
  //ADC_InitTypeDef       ADC_InitStructure;
  //ADC_CommonInitTypeDef ADC_CommonInitStructure;
  //DMA_InitTypeDef       DMA_InitStructure;
  //GPIO_InitTypeDef      GPIO_InitStructure;

  /* Enable ADC1, DMA2 and GPIO clocks ****************************************/
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  
  DMA_DeInit(DMA2_Stream0);
       
         
  /* DMA2 Stream0 channel2 configuration **************************************/
  DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC1ConvertedValue;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
  DMA_InitStructure.DMA_BufferSize = SAMPLEING_POINTS;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//DMA_MemoryInc_Disable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;//DMA_Mode_Normal;//
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);
  DMA_Cmd(DMA2_Stream0, ENABLE);
        DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
}
void DMA2_Stream0_IRQHandler(void)
{
   
//if (DMA_GetFlagStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)
if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0) != RESET)
{
  DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
  //DMA_ClearFlag(DMA2_Stream0,DMA_FLAG_TCIF0);
        //DMA_Cmd(DMA2_Stream0, DISABLE);
        ADC_SoftwareStartConvCmd(ADC1,DISABLE);
  DMA_Cmd(DMA2_Stream0, DISABLE);

        DMARecFlag=1;
       
}
       
}
void DMAReConfig(void)
{
DMA_DeInit(DMA2_Stream0);
DMA_InitStructure.DMA_BufferSize = SAMPLEING_POINTS;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA2_Stream0, ENABLE);
}
 while (1)
  {
    #ifdef PRINT_ON_LCD
    /* Display ADC converted value on LCD */
        Display(max,max_position);
    #endif
                //ADC_Cmd(ADC1, ENABLE);
                if (ADCStartFlag==1)
    {
                 //DMA_Config();
                 //DMA2_Stream0->CNDTR = 0x00000064;
                 //ADC_Config();       
           //DMA_Cmd(DMA2_Stream0, ENABLE);         
                 //ADC_DMACmd(ADC1, ENABLE);
                 //ADC_Cmd(ADC1, ENABLE);
                 ADC_SoftwareStartConvCmd(ADC1,ENABLE);//¿ªÊ¼²É¼¯
               
                 ADCStartFlag=0;
           while(DMARecFlag==1) //´«Êä½áÊø£¬½øÐмÆËã
     {
                         DMARecFlag=0;
                        //ADC_Cmd(ADC1, DISABLE);
                         //ADC_SoftwareStartConvCmd(ADC1,DISABLE);
                         //DMA_Cmd(DMA2_Stream0, DISABLE);
                         DMAReConfig();
                        // DMA_Config();
                       
                   max=0;
                     for(i=0;i<SAMPLEING_POINTS ;i++)
                       {
                                     if (ADC1ConvertedValue[i]>max)
                                   {  max=ADC1ConvertedValue[i];
                                            max_position=i;
                                   }
                       }
                  j=max;
                        //break;
      }      
    }
        }

使用特权

评论回复
12
lee_hwa|  楼主 | 2013-12-18 10:19 | 只看该作者
lee_hwa 发表于 2013-12-18 10:18
请各位专家指点一下:

while里break没有注释掉。代码里是错的。

使用特权

评论回复
13
ticomi| | 2013-12-18 12:30 | 只看该作者
lee_hwa 发表于 2013-12-18 09:49
你的是STM32F407么

是的407

使用特权

评论回复
14
ticomi| | 2013-12-18 12:32 | 只看该作者
lee_hwa 发表于 2013-12-18 09:56
DMA_SetCurrDataCounter(DMA2_Stream0, ADC_RX_SIZE)可以  Enable DMA2 Stream0     是什么道理? ADC_RX_S ...

这个是每次启动DMA接收数据前需要设置的接收量,ADC_RX_SIZE是DMA的读取数据量,如果每次都是读取一样的数据量,可以不用每次设置一次。

使用特权

评论回复
15
//YZC| | 2013-12-18 13:33 | 只看该作者
每次开启DMA之前,先关闭下DMA,重新写下传输地址和传输长度

使用特权

评论回复
16
lee_hwa|  楼主 | 2013-12-19 09:10 | 只看该作者
ticomi 发表于 2013-12-18 12:32
这个是每次启动DMA接收数据前需要设置的接收量,ADC_RX_SIZE是DMA的读取数据量,如果每次都是读取一样的 ...

1.DMA_SetCurrDataCounter(DMA2_Stream0, ADC_RX_SIZE)后使用DMA_Cmd(DMA2_Stream0, ENABLE)么?
2.你的外设是AD么,不是的话,是什么呀?

使用特权

评论回复
17
lee_hwa|  楼主 | 2013-12-19 09:10 | 只看该作者
//YZC 发表于 2013-12-18 13:33
每次开启DMA之前,先关闭下DMA,重新写下传输地址和传输长度

我每次都关闭,然后重新congfig都不行。

使用特权

评论回复
18
ticomi| | 2013-12-19 09:24 | 只看该作者
lee_hwa 发表于 2013-12-19 09:10
1.DMA_SetCurrDataCounter(DMA2_Stream0, ADC_RX_SIZE)后使用DMA_Cmd(DMA2_Stream0, ENABLE)么?
2.你的 ...

外设是ADC,高速ADC。这段代码是在DMA采集完成的中断里实现的。
先关闭DMA的接收和发送通道,然后清除对应的中断

做相应的工作后决定再次启动DMA前,需要重新配置和使能DMA的,如代码段。

这里我想说明下的是,如果你使用DMA配合SPI读取ADC数据的话,一定是要采用DMA来通过SPI发送数据,否则是读取不到数据的,也会出现各种莫名其妙的问题。所以一定要配置两个DMA Stream,一个属于发送数据,一个属于接收SPI的数据。

使用特权

评论回复
19
//YZC| | 2013-12-19 13:52 | 只看该作者
lee_hwa 发表于 2013-12-19 09:10
我每次都关闭,然后重新congfig都不行。

DMA没问题那就是外设的问题了,外设不工作DMA当然无法完成,为啥DMA完成中断里会有“ADC_SoftwareStartConvCmd(ADC1,DISABLE);”这一句?你的代码结构没怎么看清,或许是你对ADC的配置出了问题,根据我的经验,ADC初始化好后,启动和关闭DMA不需要再去配置ADC,楼主不妨找找外设上的原因

使用特权

评论回复
20
lee_hwa|  楼主 | 2013-12-19 17:28 | 只看该作者
//YZC 发表于 2013-12-19 13:52
DMA没问题那就是外设的问题了,外设不工作DMA当然无法完成,为啥DMA完成中断里会有“ADC_SoftwareStartCo ...

是呀,有的人不是说要先disable外设,在disable dma么。我觉得也有问题。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

33

主题

147

帖子

1

粉丝