OpenEdv-开源电子网

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

做数字滤波器,使用adc+dma采样数据,处理后通过dac+dma输出,两个dma会影响滤波函数的问题。

[复制链接]
回帖奖励 8 金钱 回复本帖可获得 1 金钱奖励! 每人限 1 次

4

主题

9

帖子

0

精华

新手入门

积分
11
金钱
11
注册时间
2022-1-25
在线时间
4 小时
发表于 2022-6-19 11:34:31 | 显示全部楼层 |阅读模式
如题,想做一个数字滤波器,adc采样数据后再通过dac把滤波后的信号发送出去,然后卡在两个dma上面了。目前是在用adc+dma采样数据,通过滤波函数处理后串口发送出去,同时dac输出一个与” adc采样数据无关 “的正弦波,观察dac+dma能否正常工作。
遇到的问题是,dac在关闭的时候,adc接受的一个三次谐波,经过滤波函数,滤波函数正常工作,将滤波后信号串口打印,是一个正弦波。
dac在正常工作并输出正弦波的时候,adc同样接受的一个三次谐波,经过滤波函数,此时滤波函数滤波后的信号变为三次谐波,就是没起到作用,求大佬解惑。
下面是adc+dma的代码配置
  1. #include "adc.h"
  2. #include "delay.h"       
  3. #include <string.h>
  4. #include "filter.h"

  5. #define TEST_LENGTH_SAMPLES  300

  6. extern u16 ADC_Raw[TEST_LENGTH_SAMPLES];
  7. u16 temp[TEST_LENGTH_SAMPLES];
  8. extern float testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES];       

  9. //初始化ADC                                                                                                                          
  10. void DMA_Config(DMA_Stream_TypeDef *DMA_Streamx,uint32_t chx,uint32_t par,uint32_t mar,uint16_t ndtr,uint32_t pri)
  11. {

  12.         DMA_InitTypeDef  DMA_InitStructure;
  13.        
  14.         if((u32)DMA_Streamx>(u32)DMA2)                                                                                                                                                                        //得到当前stream是属于DMA2还是DMA1
  15.         {
  16.           RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);                                                                                //DMA2时钟使能
  17.                
  18.         }else
  19.         {
  20.           RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);                                                                                //DMA1时钟使能
  21.         }
  22.   DMA_DeInit(DMA_Streamx);
  23.        
  24.         while (DMA_GetCmdStatus(DMA_Streamx) != DISABLE){}                                                                                        //等待DMA可配置
  25.        
  26.   /* 配置 DMA Stream */
  27.   DMA_InitStructure.DMA_Channel            = chx;                                                                                                 //通道选择
  28.   DMA_InitStructure.DMA_PeripheralBaseAddr = par;                                                                                                  //DMA外设地址
  29.   DMA_InitStructure.DMA_Memory0BaseAddr    = mar;                                                                                                        //DMA 存储器0地址
  30.   DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralToMemory;        //外设到内存
  31.   DMA_InitStructure.DMA_BufferSize         = ndtr;                                                                                                //数据传输量
  32.   DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;                //外设非增量模式
  33.   DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;                                //存储器增量模式
  34.   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据长度:16位
  35.   DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;                        //存储器数据长度:16位
  36.   DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;                                                        //使用循环模式
  37.   DMA_InitStructure.DMA_Priority           = pri;                                                        //优先级
  38.   DMA_InitStructure.DMA_FIFOMode           = DMA_FIFOMode_Disable;         
  39.   DMA_InitStructure.DMA_FIFOThreshold      = DMA_FIFOThreshold_Full;
  40.   DMA_InitStructure.DMA_MemoryBurst        = DMA_MemoryBurst_Single;                        //存储器突发单次传输
  41.   DMA_InitStructure.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;        //外设突发单次传输
  42.   DMA_Init(DMA_Streamx, &DMA_InitStructure);                                                                                                                        //初始化DMA Stream
  43.                                                                                                
  44.                
  45.         /* DMA2_Stream0 enable */
  46.   DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC);
  47.         DMA_ITConfig(DMA2_Stream0, DMA_IT_TC, ENABLE);
  48.         DMA_Cmd(DMA_Streamx, ENABLE);     
  49. }

  50. //初始化ADC3IN7引脚
  51. void ADCInit_GPIO(void)
  52. {
  53.         GPIO_InitTypeDef  GPIO_InitStructure;

  54.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

  55.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  56.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;  
  57.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  58.   GPIO_Init(GPIOA, &GPIO_InitStructure);  
  59. }

  60. void ADC_Config(void)
  61. {
  62.         ADC_CommonInitTypeDef ADC_CommonInitStructure;
  63.   ADC_InitTypeDef       ADC_InitStructure;
  64.    
  65.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
  66.    
  67.   RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,ENABLE);      
  68.   RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3,DISABLE);   

  69.   ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
  70.   ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
  71.   ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
  72.   ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
  73.   ADC_CommonInit(&ADC_CommonInitStructure);
  74.    
  75.   ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
  76.   ADC_InitStructure.ADC_ScanConvMode = ENABLE;
  77.   ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
  78.   ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising;
  79.   ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;//定时器2外部触发  
  80.   ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
  81.   ADC_InitStructure.ADC_NbrOfConversion = 1; //M   
  82.   ADC_Init(ADC3, &ADC_InitStructure);
  83.     delay_ms(5);
  84.   ADC_RegularChannelConfig(ADC3, ADC_Channel_0, 1, ADC_SampleTime_480Cycles);   
  85.   ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);//源数据变化时开启DMA传输
  86.   ADC_DMACmd(ADC3, ENABLE);  //使能ADC的DMA传输
  87.   ADC_Cmd(ADC3, ENABLE);
  88.        
  89. }




  90. void NVIC_Config(void)
  91. {
  92.         NVIC_InitTypeDef NVIC_InitStructure;
  93.   
  94.         NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//最高一位用于配置抢占优先级,低三位用于配置响应优先级
  95.        
  96.   NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  
  97.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;  
  98.   NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;        
  99.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            
  100.   NVIC_Init(&NVIC_InitStructure);   
  101.    
  102.   NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;  
  103.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;  
  104.   NVIC_InitStructure.NVIC_IRQChannelSubPriority =1;        
  105.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           
  106.   NVIC_Init(&NVIC_InitStructure);   
  107. }

  108. void Timer_Init(void)
  109. {
  110.         TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;


  111.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);         


  112.   TIM_Cmd(TIM2, DISABLE);
  113.   TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  114.    
  115.   //T=(84 * 625) / 84M = 625us = 20ms/32,1600HZ
  116.   TIM_TimeBaseStructure.TIM_Prescaler = 4199        ;//84-1;
  117.   TIM_TimeBaseStructure.TIM_Period = 1;//312500/CurrentFreq - 1;
  118.   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  119.   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up ;
  120.   TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  121.    
  122.    
  123.   TIM_ARRPreloadConfig(TIM2, ENABLE);
  124.   TIM_SelectOutputTrigger(TIM2, TIM_TRGOSource_Update);  

  125.   TIM_Cmd(TIM2, ENABLE);
  126. }

  127. void TIM2_IRQHandler(void)  
  128. {
  129.   if(TIM_GetITStatus(TIM2, TIM_IT_Update))  
  130.   {  
  131.                 //LED0=~LED0;
  132.     TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
  133.   }
  134.    
  135. }
  136. u16 adc_cov;
  137. u16 ADC3_IN7_RES;


  138. void DMA2_Stream0_IRQHandler(void)  
  139. {
  140.         u16 i=0;
  141. if(DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
  142. {
  143.          memcpy(temp, ADC_Raw, sizeof(u16)*TEST_LENGTH_SAMPLES);
  144.                 for(i=0;i<TEST_LENGTH_SAMPLES;i++){
  145.                         testInput_f32_50Hz_200Hz[i]=(float)temp[i];
  146.                 }
  147.                 printf("\r\n-------arm_fir_f32_lp();-------\r\n");
  148.                 arm_fir_f32_lp();
  149.                 printf("\r\n------arm_fir_f32_lp();--------\r\n");
  150.    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);
  151.          
  152. }
  153. }
  154.          









复制代码
以下是dac+dma和定时器的配置
  1. //dac.c

  2. #include "dac.h"


  3. //DAC通道1输出初始化
  4. void DAC_Mode_Init(u16 mar)
  5. {
  6.     DAC_InitTypeDef DAC_InitType;
  7.     DMA_InitTypeDef DMA_InitStre;
  8.     GPIO_InitTypeDef  GPIO_InitStructure;
  9.    
  10.                 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟
  11.                 RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);//使能DAC时钟
  12.     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);//DMA时钟
  13.        
  14.        
  15.                 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
  16.                 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;//模拟输入
  17.                 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//下拉
  18.                 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  
  19.                 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  20.                 GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
  21.     /************************* 通道1 ***************************/
  22.     //使用DMA模式-寄存器到外设
  23.     DAC_InitType.DAC_Trigger=DAC_Trigger_T2_TRGO;    //必须使用触发功能 TEN1=0
  24.     DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;//不使用波形发生
  25.     DAC_InitType.DAC_LFSRUnmask_TriangleAmplitude=DAC_LFSRUnmask_Bit0;//屏蔽、幅值设置
  26.     DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Disable;    //DAC1输出缓存关闭 BOFF1=1
  27.                 DAC_Init(DAC_Channel_1,&DAC_InitType);     //初始化DAC通道1
  28.     DAC_Cmd(DAC_Channel_1, ENABLE);  //使能DAC通道1
  29.    
  30.    
  31.     //DMA初始化
  32.     DMA_DeInit(DMA1_Stream5);//复位
  33.     DMA_InitStre.DMA_PeripheralBaseAddr=(uint32_t)&(DAC->DHR12R1);//外设 DAC1_DR
  34.     DMA_InitStre.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
  35.     DMA_InitStre.DMA_PeripheralDataSize=DMA_PeripheralDataSize_HalfWord;//半字
  36.     DMA_InitStre.DMA_PeripheralInc=DMA_PeripheralInc_Disable;//外设地址增加失能
  37.    
  38.     DMA_InitStre.DMA_Memory0BaseAddr=mar;    //内存地址
  39.     DMA_InitStre.DMA_MemoryInc=DMA_MemoryInc_Enable;//寄存器(变量)地址增加
  40.     DMA_InitStre.DMA_MemoryDataSize=DMA_MemoryDataSize_HalfWord;//半字
  41.     DMA_InitStre.DMA_MemoryBurst=DMA_MemoryBurst_Single;
  42.    
  43.     DMA_InitStre.DMA_Channel=DMA_Channel_7;
  44.     DMA_InitStre.DMA_DIR=DMA_DIR_MemoryToPeripheral;//寄存器到外设输出
  45.     DMA_InitStre.DMA_BufferSize=300;//一个输出循环中数据长度
  46.     DMA_InitStre.DMA_Mode=DMA_Mode_Circular;//循环发送
  47.    
  48.     DMA_InitStre.DMA_Priority=DMA_Priority_High;
  49.     DMA_InitStre.DMA_FIFOMode=DMA_FIFOMode_Disable;
  50.     DMA_InitStre.DMA_FIFOThreshold=DMA_FIFOThreshold_1QuarterFull;
  51.     DMA_Init(DMA1_Stream5,&DMA_InitStre);//初始化
  52.    
  53.     DMA_Cmd(DMA1_Stream5,ENABLE);//DMA使能
  54.     DAC_DMACmd(DAC_Channel_1, ENABLE);//DAC-DMA使能
  55.         }

  56. //time.c
  57. #include "timer.h"
  58. #include "led.h"


  59. //通用定时器4中断初始化
  60. //arr:自动重装值。
  61. //psc:时钟预分频数
  62. //定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
  63. //Ft=定时器工作频率,单位:Mhz
  64. //这里使用的是定时器2
  65. void TIM2_Int_Init(u16 arr,u16 psc)
  66. {
  67.         TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  68.         NVIC_InitTypeDef NVIC_InitStructure;
  69.        
  70.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   ///使能TIM2时钟
  71.        
  72.        
  73.         TIM_DeInit(TIM2); // 初始化
  74.         TIM_TimeBaseStructInit(&TIM_TimeBaseInitStructure); // 初始化
  75.        
  76.   TIM_TimeBaseInitStructure.TIM_Period = arr;         //自动重装载值
  77.         TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  //定时器分频
  78.         TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
  79.         TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
  80.        
  81.         TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//初始化TIM2
  82.        
  83.         TIM_SelectOutputTrigger(TIM2,TIM_TRGOSource_Update); // **与上一方案不同**
  84.         TIM_Cmd(TIM2,ENABLE); //使能定时器2
  85.        
  86.        
  87. }
复制代码
以下是滤波函数
  1. #include "filter.h"
  2. #include "arm_math.h"

  3. #define TEST_LENGTH_SAMPLES  300    /* 采样点数 */
  4. #define BLOCK_SIZE           1             /* 调用一次arm_fir_f32处理的采样点个数 */
  5. #define NUM_TAPS             29      /* 滤波器系数个数 */

  6. float32_t testInput_f32_50Hz_200Hz[TEST_LENGTH_SAMPLES]; /* 采样点 */
  7. static float32_t testOutput[TEST_LENGTH_SAMPLES];               /* 滤波后的输出 */
  8. static float32_t firStateF32[BLOCK_SIZE + NUM_TAPS - 1];        /* 状态缓存,大小numTaps + blockSize - 1*/

  9. uint32_t blockSize = BLOCK_SIZE;
  10. uint32_t numBlocks = TEST_LENGTH_SAMPLES/BLOCK_SIZE;            /* 需要调用arm_fir_f32的次数 */


  11. const float32_t firCoeffs32LP[NUM_TAPS] = {
  12.    0.001066399611256, 0.002126085729052, 0.003159337947181, 0.003059846159226,
  13.   -1.968950437715e-18, -0.00705866005337, -0.01651859315877, -0.02329385602413,
  14.    -0.01997951839664,5.751341766627e-18,  0.03857458762271,  0.09055123279738,
  15.      0.1441009644858,   0.1844676143613,    0.199489117838,   0.1844676143613,
  16.      0.1441009644858,  0.09055123279738,  0.03857458762271,5.751341766627e-18,
  17.    -0.01997951839664, -0.02329385602413, -0.01651859315877, -0.00705866005337,
  18.   -1.968950437715e-18, 0.003059846159226, 0.003159337947181, 0.002126085729052,
  19.    0.001066399611256
  20. };


  21. void arm_fir_f32_lp(void)
  22. {
  23.         uint32_t i;
  24.         arm_fir_instance_f32 S;
  25.         float32_t  *inputF32, *outputF32;

  26.         /* 初始化输入输出缓存指针 */
  27.         inputF32 = &testInput_f32_50Hz_200Hz[0];
  28.         outputF32 = &testOutput[0];

  29.         /* 初始化结构体S */
  30.         arm_fir_init_f32(&S,                           
  31.                                          NUM_TAPS,
  32.                         (float32_t *)&firCoeffs32LP[0],
  33.                          &firStateF32[0],
  34.                          blockSize);

  35.         /* 实现FIR滤波,这里每次处理1个点 */
  36.         for(i=0; i < numBlocks; i++)
  37.         {
  38.                 arm_fir_f32(&S, inputF32 + (i * blockSize),  outputF32 + (i * blockSize),  blockSize);
  39.         }
  40.        

  41.         /* 打印滤波后结果 */
  42.         for(i=0; i<TEST_LENGTH_SAMPLES; i++)
  43.         {
  44.                 printf("%f\r\n",  outputF32[i]);
  45.         }

  46. }
复制代码


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

使用道具 举报

12

主题

3344

帖子

1

精华

论坛元老

Rank: 8Rank: 8

积分
8463
金钱
8463
注册时间
2020-5-11
在线时间
3904 小时
发表于 2022-6-20 10:01:58 | 显示全部楼层

回帖奖励 +1 金钱

看你DMA都是循环模式,取数据时DMA没停,不怕乱套吗。
专治疑难杂症
回复 支持 1 反对 0

使用道具 举报

2

主题

369

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
4241
金钱
4241
注册时间
2020-7-24
在线时间
714 小时
发表于 2022-6-20 10:13:44 | 显示全部楼层

回帖奖励 +1 金钱

帮顶  
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-2-25 15:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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