OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 27884|回复: 11

ADC采样率如何精准计算?定时器触发转换 DMA传输

[复制链接]

13

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2013-7-15
在线时间
0 小时
发表于 2013-8-10 11:37:49 | 显示全部楼层 |阅读模式
本人ADC初始化 程序如下:NPT256 采256个点,定时器3触发ADC转换,计算下来应该25.6K采样 有效频率12.8K 分析音频信号 步进100HZ,FFT后频谱显示很好,但是IFF后,输入正弦波超过4K就会显示出混叠。
让采样率提升十倍则问题解决。。一直对ADC采样率计算存在疑问,希望大神指点。。。



void Adcbydma_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStructure;
 ADC_InitTypeDef ADC_InitStructure;
 DMA_InitTypeDef DMA_InitStructure;
 NVIC_InitTypeDef NVIC_InitStructure;
 TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure; 

  
 /* Configure one bit for preemption priority */
  #if defined (VECT_TAB_RAM)
 /* Set the Vector Table base location at 0x20000000 */ 
 NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
      #elif defined(VECT_TAB_FLASH_IAP)
 NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x2000);
      #else  /* VECT_TAB_FLASH  */
 /* Set the Vector Table base location at 0x08000000 */
 NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);   
 #endif 



 /* Configure the NVIC Preemption Priority Bits */  
 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
 /* Enable the RTC Interrupt */
 NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn ;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
 NVIC_Init(&NVIC_InitStructure); 

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); 
/* Time Base configuration */ 
 TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  
#ifdef NPT_64 
TIM_TimeBaseStructure.TIM_Prescaler = 0;        
TIM_TimeBaseStructure.TIM_Period = 22499;           
#endif 
#ifdef NPT_256 
TIM_TimeBaseStructure.TIM_Prescaler = 0;        
TIM_TimeBaseStructure.TIM_Period = 2813;//25.6K采样 有效频率12.8K 分析音频信号 步进100HZ      
#endif 
#ifdef NPT_1024 
TIM_TimeBaseStructure.TIM_Prescaler = 0;        
TIM_TimeBaseStructure.TIM_Period = 3515;           
#endif 
TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;     
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;   
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 
TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update); 
TIM_Cmd(TIM3,ENABLE); 
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); 



/* Enable ADC1 and GPIOA clock */
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);


  /* Configure PA.01 (ADC Channel1) as analog input -------------------------*/
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStructure);


  /* DMA channel1 configuration ----------------------------------------------*/
  DMA_DeInit(DMA1_Channel1);
  DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address;
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_DualConvertedValueTab;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
  DMA_InitStructure.DMA_BufferSize = NPT;
  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_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);

  DMA_ITConfig(DMA1_Channel1,DMA_IT_TC,ENABLE); //开传输完中断
  
  /* Enable DMA channel1 */
  DMA_Cmd(DMA1_Channel1, ENABLE);

  RCC_ADCCLKConfig(RCC_PCLK2_Div6);
    /* ADC1 configuration ------------------------------------------------------*/
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
  ADC_InitStructure.ADC_ScanConvMode = DISABLE; 
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; 
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO ;//ADC_ExternalTrigConv_None;
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  ADC_InitStructure.ADC_NbrOfChannel = 1;
  ADC_Init(ADC1, &ADC_InitStructure);
  /* ADC1 regular channels configuration */ 
  ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_239Cycles5);    
  //ADC_RegularChannelConfig(ADC1, ADC_Channel_14, 2, ADC_SampleTime_239Cycles5);
  /* Enable ADC1 DMA */
  ADC_DMACmd(ADC1, ENABLE);

  /* Enable ADC1 */
  ADC_Cmd(ADC1, ENABLE);
  /* Enable Vrefint channel17 */
  //ADC_TempSensorVrefintCmd(ENABLE);

  
  /* Enable ADC1 reset calibaration register */   
  ADC_ResetCalibration(ADC1);
  /* Check the end of ADC1 reset calibration register */
  while(ADC_GetResetCalibrationStatus(ADC1));

  
  /* Start ADC1 calibaration */
  ADC_StartCalibration(ADC1);
  /* Check the end of ADC1 calibration */
  while(ADC_GetCalibrationStatus(ADC1));
    /* Start ADC1 Software Conversion */ 


/* Enable ADC1 EOC  interrupts */ 
// ADC_ITConfig(ADC1, ADC_IT_EOC ,ENABLE);


  ADC_SoftwareStartConvCmd(ADC1, ENABLE);

  /* Test on DMA1 channel1 transfer complete flag */

}

fftandifft.zip

5.91 MB, 下载次数: 656

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-10 12:46:29 | 显示全部楼层
DMA控制频率的话,只能结合ADC频率,采样周期,来设置采用频率了.优点是不需要什么中断,缺点就是设置比较麻烦.
用定时器控制,那就靠定时器精度保证,优点是设置方便,缺点是要频繁中断.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

13

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2013-7-15
在线时间
0 小时
 楼主| 发表于 2013-8-10 15:27:14 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
原子老师,我的问题是 现在用定时器TIM3触发ADC转换,理论上应该采样率有25.6k 有效频率12.3K  可为什么我示波器发出5K的正弦波,我IFFT后,频谱就混叠了?? 原子老师,你看我现在的配置的话,ADC的采样率是多少??
回复 支持 反对

使用道具 举报

96

主题

762

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1228
金钱
1228
注册时间
2012-10-19
在线时间
15 小时
发表于 2013-8-10 15:53:11 | 显示全部楼层
回复【2楼】正点原子:
---------------------------------
定时器控制为什么要中断?我没看明白
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-10 17:29:55 | 显示全部楼层
回复【4楼】tian123chi:
---------------------------------
在中断里面读啊.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-10 17:30:52 | 显示全部楼层
回复【3楼】sdsd555a:
---------------------------------
你这个经过IFFT变换我就不知道了,你可以测试下每秒钟的数据量,从而判断采样频率.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

13

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2013-7-15
在线时间
0 小时
 楼主| 发表于 2013-8-10 17:41:03 | 显示全部楼层
回复【4楼】tian123chi:
---------------------------------
其实 我没有写定时器的中断服务程序 这里设置中断只是到时出去ADC转换而已吧??

在网上程序上面 修改了一下的哈。。。
回复 支持 反对

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
71
金钱
71
注册时间
2013-8-11
在线时间
0 小时
发表于 2013-8-11 21:30:18 | 显示全部楼层
楼主 你是不是有 dsp库里的FFT算法 弄的? 你是怎么采集AD的值得 ?
回复 支持 反对

使用道具 举报

13

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2013-7-15
在线时间
0 小时
 楼主| 发表于 2013-8-12 17:07:24 | 显示全部楼层
回复【8楼】奥特曼5507:
---------------------------------
没有用DSP库 使用的C语言FFT算法 直接放进去的。。。AD使用TIM3触发转换  DMA传输的。。。现在还是FFT没有问题,可是IFFT就有问题,但是提高采样率就 都没有问题了
回复 支持 反对

使用道具 举报

7

主题

23

帖子

0

精华

初级会员

Rank: 2

积分
71
金钱
71
注册时间
2013-8-11
在线时间
0 小时
发表于 2013-8-13 11:15:24 | 显示全部楼层
楼主 能发你的例程 来参考 参考么 我用DSP库里的FFT 但用AD采集信号发生器的正弦波 不知道AD怎么采集 才能很好的还原原来的正弦波?
回复 支持 反对

使用道具 举报

13

主题

38

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2013-7-15
在线时间
0 小时
 楼主| 发表于 2013-8-16 11:05:50 | 显示全部楼层
回复【10楼】奥特曼5507:
---------------------------------
好 我把我的程序 发上来  你帮我参考一下 我的 采样率 如何具体计算??
回复 支持 反对

使用道具 举报

6

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
66
金钱
66
注册时间
2015-4-16
在线时间
4 小时
发表于 2015-12-1 10:52:01 | 显示全部楼层
看看,看不懂
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-20 21:19

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表