你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

ADC+DMA采集并传输完成后的中断问题

[复制链接]
这名比较叼 提问时间:2016-12-13 14:52 /
现在需要单路AD连续采集2048个数据存入数组并通过DMA传输至存储器并进行FFT变换,AD采集和FFT变换两个分开的部分已经可以了,但是加在一起的话就不知道数据采集和传输是怎样的一个顺序了,AD采集到的电压值是正确的,但是传递到fft的输入就完全变了,这是什么原因呢,下面附下我的配置函数,希望知道的朋友帮帮忙看下,谢谢!(文字复制过来就乱码了,不过应该不影响看懂程序吧)#include "bsp_adc.h"
#include "arm_math.h"

__IO uint16_t ADC_ConvertedValue[2048];

static void ADC_GPIO_Config(void)
{
                GPIO_InitTypeDef GPIO_InitStructure;
       
        // ʹÄÜ GPIO ʱÖÓ
        RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_GPIO_CLK, ENABLE);
               
        // ÅäÖÃ IO
        GPIO_InitStructure.GPIO_Pin = RHEOSTAT_ADC_GPIO_PIN;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;            
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; //²»ÉÏÀ­²»ÏÂÀ­
        GPIO_Init(RHEOSTAT_ADC_GPIO_PORT, &GPIO_InitStructure);               
}

void NVIC_Config(void)
{
  NVIC_InitTypeDef   NVIC_InitStructure;

  /* Enable the DMA2_Stream0 gloabal Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = DMA_IRQ;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

static void ADC_Mode_Config(void)
{
        DMA_InitTypeDef DMA_InitStructure;
        ADC_InitTypeDef ADC_InitStructure;
  ADC_CommonInitTypeDef ADC_CommonInitStructure;

       
  // ------------------DMA Init ½á¹¹Ìå²ÎÊý ³õʼ»¯--------------------------

  RCC_AHB1PeriphClockCmd(RHEOSTAT_ADC_DMA_CLK, ENABLE);

  DMA_InitStructure.DMA_Channel = RHEOSTAT_ADC_DMA_CHANNEL;
        // ÍâÉè»ùַΪ£ºADC Êý¾Ý¼Ä´æÆ÷µØÖ·
        DMA_InitStructure.DMA_PeripheralBaseAddr = RHEOSTAT_ADC_DR_ADDR;       
  // ´æ´¢Æ÷µØÖ·£¬Êµ¼ÊÉϾÍÊÇÒ»¸öÄÚ²¿SRAMµÄ±äÁ¿       
        DMA_InitStructure.DMA_Memory0BaseAddr = (u32)&ADC_ConvertedValue;
  // Êý¾Ý´«Êä·½ÏòΪÍâÉèµ½´æ´¢Æ÷       
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;       
        // »º³åÇø´óСΪ£¬Ö¸Ò»´Î´«ÊäµÄÊý¾ÝÁ¿£¨Ò»´Î´«ÊäÍê³É¼´½øÈëÖжϣ©
        DMA_InitStructure.DMA_BufferSize = 2048;       
        // ÍâÉè¼Ä´æÆ÷Ö»ÓÐÒ»¸ö£¬µØÖ·²»ÓõÝÔö
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  // ´æ´¢Æ÷µØÖ·¹Ì¶¨
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  // // ÍâÉèÊý¾Ý´óСΪ°ë×Ö£¬¼´Á½¸ö×Ö½Ú
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  //        ´æ´¢Æ÷Êý¾Ý´óСҲΪ°ë×Ö£¬¸úÍâÉèÊý¾Ý´óСÏàͬ
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;       
        // Ñ­»·´«Êäģʽ
        DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
  // DMA ´«ÊäͨµÀÓÅÏȼ¶Îª¸ß£¬µ±Ê¹ÓÃÒ»¸öDMAͨµÀʱ£¬ÓÅÏȼ¶ÉèÖò»Ó°Ïì
        DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  // ½ûÖ¹DMA FIFO        £¬Ê¹ÓÃÖ±Á¬Ä£Ê½
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;  
  // FIFO ´óС£¬FIFOģʽ½ûֹʱ£¬Õâ¸ö²»ÓÃÅäÖà      
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  
  //³õʼ»¯DMAÁ÷£¬Á÷Ï൱ÓÚÒ»¸ö´óµÄ¹ÜµÀ£¬¹ÜµÀÀïÃæÓкܶàͨµÀ
        DMA_Init(RHEOSTAT_ADC_DMA_STREAM, &DMA_InitStructure);
        // ʹÄÜDMAÁ÷
  DMA_Cmd(RHEOSTAT_ADC_DMA_STREAM, ENABLE);
       
        // ¿ªÆôADCʱÖÓ
        RCC_APB2PeriphClockCmd(RHEOSTAT_ADC_CLK , ENABLE);
  // -------------------ADC Common ½á¹¹Ìå ²ÎÊý ³õʼ»¯------------------------
        // ¶ÀÁ¢ADCģʽ
  ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  // ʱÖÓΪfpclk=90MHZ 4·ÖƵ       
  ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
  // ½ûÖ¹DMAÖ±½Ó·ÃÎÊģʽ       
  ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  // ²ÉÑùʱ¼ä¼ä¸ô       
  ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_20Cycles;  
  ADC_CommonInit(&ADC_CommonInitStructure);
       
  // -------------------ADC Init ½á¹¹Ìå ²ÎÊý ³õʼ»¯--------------------------

  ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;                                 // ADC ·Ö±æÂÊ
  ADC_InitStructure.ADC_ScanConvMode = DISABLE;                                                                  // ½ûֹɨÃèģʽ£¬¶àͨµÀ²É¼¯²ÅÐèÒª       
  ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;                                                  // Á¬Ðøת»»       
  ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;                  //½ûÖ¹Íⲿ±ßÑØ´¥·¢
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;                          //ʹÓÃÈí¼þ´¥·¢£¬Íⲿ´¥·¢²»ÓÃÅäÖã¬×¢Ê͵ô¼´¿É
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;                                  //Êý¾ÝÓÒ¶ÔÆë       
  ADC_InitStructure.ADC_NbrOfConversion = 1;                     //ת»»Í¨µÀ 1¸ö                     
  ADC_Init(RHEOSTAT_ADC, &ADC_InitStructure);
  //---------------------------------------------------------------------------

  ADC_RegularChannelConfig(RHEOSTAT_ADC, RHEOSTAT_ADC_CHANNEL, 1, ADC_SampleTime_56Cycles);


  ADC_DMARequestAfterLastTransferCmd(RHEOSTAT_ADC, ENABLE);

  ADC_DMACmd(RHEOSTAT_ADC, ENABLE);
        DMA_ITConfig(DMA2_Stream0,DMA_IT_TC , ENABLE);
  /* Enable ADC3 */
  ADC_Cmd(RHEOSTAT_ADC, ENABLE);

  ADC_Cmd(RHEOSTAT_ADC, ENABLE);

  ADC_SoftwareStartConv(RHEOSTAT_ADC);
}



void ADC_Configuration(void)
{
        NVIC_Config();
        ADC_GPIO_Config();
        ADC_Mode_Config();
       
}


收藏 2 评论16 发布时间:2016-12-13 14:52

举报

16个回答
shuolang126 回答时间:2016-12-15 07:12:37
楼主也可以定义4096长度的数组,使用DMA半满和全满两个中断信号,利用乒乓方式,达到ADC采集,FFT变换同时进行,又不互相干扰的效果!

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

这名比较叼 回答时间:2016-12-13 15:33:20
wolfgang2015 发表于 2016-12-13 14:57
程序的执行时间、时序及 DMA状态控制,这是解决的方法.

这个考虑过,但我目前测试AD采集端给的是固定电压,我采集2048个点,值都是一样的,而且我是直接用赋值符传递到了fft输入端,不可能会变得啊,有一个问题就是AD采集值得数据类型是uint_16,而fft输入端数据的类型是float_32的,但是我要是AD采集端的数据类型改为浮点型的,那采集到的结果也错了,,,
这名比较叼 回答时间:2016-12-13 17:00:51
wenyangzeng 发表于 2016-12-13 15:47
没有看到你的主程序是如何安排ADC和FFT的。你应该在ADC采集2048个点数据DMA产生中断后停止ADC转换,进行FFT ...

这是我的主函数和中断向量函数,按照你说的,在存满2048个数据后,进入中断,将ADC失能,清除标志位,将StartFlag标志位置1,再将存储的数据送入FFT_input数组内,然后进行fft变换,感觉没问题啊
O_F4C[$9)}@JWAFZE~GR[OC.png
T@]JAB44XN5V)WPF[{MB]TW.png
wolfgang 回答时间:2016-12-13 14:56:43
很重要的问题需要清理思路,
  信号采集 和FFT处理是并行还是串行?
wolfgang 回答时间:2016-12-13 14:57:38
程序的执行时间、时序及 DMA状态控制,这是解决的方法.
wenyangzeng 回答时间:2016-12-13 15:47:34
没有看到你的主程序是如何安排ADC和FFT的。你应该在ADC采集2048个点数据DMA产生中断后停止ADC转换,进行FFT处理后重新启动新一轮ADC转换。否则当你在进行FFT处理时,有可能新的ADC数据已经更新缓冲区了。
wenyangzeng 回答时间:2016-12-13 17:49:47
这名比较叼 发表于 2016-12-13 17:00
这是我的主函数和中断向量函数,按照你说的,在存满2048个数据后,进入中断,将ADC失能,清除标志位,将S ...

感觉你应该在DMA中断函数中就应该立即停止ADC了,然后在FFT完成后再启动ADC。

评分

参与人数 1ST金币 +2 收起 理由
zero99 + 2

查看全部评分

wolfgang 回答时间:2016-12-13 18:25:55
wenyangzeng 发表于 2016-12-13 17:49
感觉你应该在DMA中断函数中就应该立即停止ADC了,然后在FFT完成后再启动ADC。 ...

正解~~~~~~
这名比较叼 回答时间:2016-12-14 20:58:26
wenyangzeng 发表于 2016-12-13 17:49
感觉你应该在DMA中断函数中就应该立即停止ADC了,然后在FFT完成后再启动ADC。 ...

谢谢你的帮助,已经改好了,
这名比较叼 回答时间:2016-12-14 20:58:57

谢谢指导!!
wenyangzeng 回答时间:2016-12-14 22:04:09

恭喜恭喜
斜阳 回答时间:2016-12-15 09:04:57
mark            
zbber 回答时间:2016-12-15 10:44:38
程序的执行时间、时序及 DMA状态控制,这是解决的方法
这名比较叼 回答时间:2016-12-20 09:54:25
shuolang126 发表于 2016-12-15 07:12
楼主也可以定义4096长度的数组,使用DMA半满和全满两个中断信号,利用乒乓方式,达到ADC采集,FFT变换同时 ...

什么意思?可以说详细点吗,在程序里面怎么实现
12下一页

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版