DSP

STM32F407之数字滤波

2019-07-13 19:24发布

为了对stm32f4的ADC和DAC有更多的了解,我决定做一个实用性比较强的实验。就是数字滤波实验,利用stm32f4的DAC可以产生噪声的特点,利用它的一路DAC产生叠加噪声的信号作为原始信号。然后用ADC测量,把结果经过滤波处理后用DAC的另一通道把结果输出,用双踪示波器观察。     一阶惯性滤波器及其数字化 一阶惯性滤波器的传递函数为:
利用一阶差分法离散化,可以得到一阶惯性数字滤波算法:
其中T为采样周期,为滤波时间常数。T和必须根据信号频谱来选择。         编程实现: a.     设定一个1024点正弦波表,用DAC1叠加噪声输出 b.     配置定时器6更新频率为1M c.     DAC的时钟为TIM6更新事件,1024点,频率大概为0.5M d.     在TIM6的更新中断中启动一次AD转换 e.     AD转换中断中做滤波处理,然后把数值送DAC2,启动一次DAC2     程序: [plain] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /************************************  
  2.     标题:数字滤波实验  
  3.     软件平台:IAR for ARM6.21  
  4.     硬件平台:stm32f4-discovery  
  5.     主频:168M  
  6.   
  7.     描述:用DAC1产生一路叠加了噪声的信号  
  8.           用ADC通道11测量上面产生的信号  
  9.           对ADC的测量结果进行滤波处理  
  10.           用DAC2把滤波后的结果输出  
  11.       
  12.     author:小船  
  13.     data:2012-02-17  
  14. *************************************/  
  15.   
  16. #include    
  17. #include "MyDebugger.h"  
  18. #include "sintable.h"   
  19.   
  20. /*********变量声明********/  
  21. uint16_t Y0, Y1;//滤波器输出值  
  22. float T = 0.000001;//采样周期  
  23. float C = 0.00003; //滤波常数  
  24.   
  25. /*********函数声明********/  
  26. void timer6_Init(void);  
  27. void ADC3_IN11_Config(void);  
  28. void DAC_channel2_Config(void);  
  29. void Generate_SinSignal_with_Noise(void);  
  30.   
  31. void main ()  
  32. {     
  33.   
  34.   SCB->AIRCR = 0x05FA0000 | 0x400;  //中断优先级分组 抢占:响应=3:1  
  35.    
  36.   MyDebugger_Init();  
  37.    
  38.   ADC3_IN11_Config();  
  39.   Generate_SinSignal_with_Noise();  
  40.   DAC_channel2_Config();    
  41.   timer6_Init();   
  42.   
  43.   while(1)  
  44.   {  
  45.   };  
  46. }  
  47.   
  48. /**************************************  
  49.   函数名:timer6_Init  
  50.   参数:无  
  51.   返回值:无  
  52.   功能:设置定时器6更新频率为1M  
  53.         定时器6更新事件为DAC1、2时钟  
  54.         更新中断启动ADC检测  
  55. **************************************/  
  56. void timer6_Init(void)  
  57. {  
  58.   /***定时器设置***/  
  59.   RCC->APB1ENR |= (1<<4);//打开TIM6时钟  
  60.   TIM6->PSC = 0;   
  61.   TIM6->ARR = 83;  //使得更新事件频率为1m  
  62.   TIM6->CR2 |=  0x00000020;//更新事件输出  
  63.   TIM6->DIER |= 1; //使能中断  
  64.   TIM6->CR1 |= 1; //开始计时  
  65. }  
  66.   
  67. /**************************************  
  68.   函数名:Generate_SinSignal_with_Noise  
  69.   参数:无  
  70.   返回值:无  
  71.   功能:用DAC1产生一路叠加了噪声的信号  
  72. ***************************************/  
  73. void Generate_SinSignal_with_Noise(void)  
  74. {  
  75.   /***GPIO设置***/  
  76.   RCC->AHB1ENR |= (1<<0); //打开GPIOA时钟  
  77.   GPIOA->MODER |= 0x00000F00;//PA4、5模拟模式  
  78.   GPIOA->PUPDR &= 0xfffff0ff;//无上拉无下拉     
  79.     
  80.   /***DAC设置***/  
  81.   RCC->APB1ENR |= (1<<29); //使能DAC时钟  
  82.   DAC->CR &= 0xffff0000;  
  83.   /*  
  84.   使能DMA堵塞中断  
  85.   使能通道1触发  
  86.   叠加噪声  
  87.   */  
  88.   DAC->CR |= ( (1<<13) | (1<<2) | 0x00000040 | 0x00000800);    
  89.   NVIC->IP[54] = 0xA0;  
  90.   NVIC->ISER[1] |= (1<<(54-32));  
  91.    
  92.   /***DMA设置***/  
  93.   RCC->AHB1ENR |= (1<<21); //使能DMA1时钟  
  94.   DAC->CR &= ~(1<<12);//DAC dma发送模式除能  
  95.   DMA1_Stream5->CR &= 0xFFFFFFFE; //除能DMA1_Stream5  
  96.   while(DMA1_Stream5->CR & 0x00000001);//确保DMA可以被设置   
  97.   DMA1->HIFCR |= 0x000004f0;//传送前清空DMA1_Stream5所有中断标志   
  98.   DMA1_Stream5->PAR = (uint32_t)&DAC->DHR12R1;//设置外设地址  
  99.   DMA1_Stream5->M0AR = (uint32_t)SinTable; //设置内存地址  
  100.   DMA1_Stream5->CR |= 0x0002800;//16位数据  
  101.   DMA1_Stream5->NDTR = 1024; //设置dma传输数据的数量  
  102.   /*  
  103.     设置dma通道7,即DAC1  
  104.     优先级Medium  
  105.     传输方向内存到外设  
  106.     内存递增模式  
  107.     循环模式  
  108.   */  
  109.   DMA1_Stream5->CR |= ( 0x0e000000 | 0x00010000 | (1<<6)  
  110.                         | (1<<10) | (1<<8) );   
  111.     
  112.   DMA1_Stream5->CR |= 1; //DMA数据流5使能  
  113.     
  114.   DAC->CR |= (1<<0);   //DAC通道1使能  
  115.   
  116.   DAC->CR |= (1<<12);//DAC dma发送模式使能  
  117. }  
  118.   
  119. /**************************************  
  120.   函数名:ADC3_IN11_Config  
  121.   参数:无  
  122.   返回值:无  
  123.   功能:用ADC通道11测量上面产生的信号  
  124. ***************************************/  
  125. void ADC3_IN11_Config(void)  
  126. {  
  127.     /***GPIO设置***/  
  128.   RCC->AHB1ENR |= (1<<2); //打开GPIOC时钟  
  129.   GPIOC->MODER &= 0xfffffff3;//PC1模拟模式  
  130.   GPIOC->MODER |= 0x0000000C;  
  131.   GPIOC->PUPDR &= 0xfffffff3;//无上拉无下拉     
  132.     
  133.   /***ADC3设置***/  
  134.   RCC->APB2ENR |= (1<<10); //使能ADC3时钟  
  135.   ADC3->SQR1 = 0x00000000;//转换一个通道  
  136.   ADC3->SQR3 = 0x0000000B;//第一个通道为ADC3_in11  
  137.   ADC3->CR1 &= 0x00000000;   
  138.   ADC3->CR2 &= 0x00000000;    
  139.  //单次转换  
  140.   ADC3->CR1 |= (1<<5);//使能转换完成中断  
  141.   NVIC->IP[18] = 0xc0;  
  142.   NVIC->ISER[0] |= (1<<18);   
  143. }  
  144.   
  145. /**************************************  
  146.   函数名:DAC_channel2_Config  
  147.   参数:无  
  148.   返回值:无  
  149.   功能:用DAC2把滤波后的结果输出  
  150. ***************************************/  
  151. void DAC_channel2_Config(void)  
  152. {  
  153.   /***DAC设置***/  
  154.   RCC->APB1ENR |= (1<<29); //使能DAC时钟  
  155.   DAC->CR &= 0x0000ffff;  
  156.   /*  
  157.   使能通道2触发   
  158.   配置为软件触发  
  159.   */  
  160.   DAC->CR |= ( (1<<18) | (0x00380000) );   
  161.     
  162.   DAC->CR |= (1<<16);   //DAC通道2使能  
  163. }  
  164.   
  165. void TIM6_DAC_IRQHandler(void)  
  166. {  
  167.   if( DAC->SR & (1<<13) )  
  168.   {  
  169.     MyDebugger_LEDs(red, on);//亮红灯指示DAC1的DMA传输数据错误  
  170.     DAC->SR &= ~(1<<13);   
  171.   }  
  172.     
  173.   if(TIM6->SR)  
  174.   {      
  175.     ADC3->CR2 |= (1<<0);   //开启AD转换    
  176.     ADC3->CR2 |= (1<<30); //规则通道转换开始  
  177.       
  178.     TIM6->SR &= ~(0x0001);   
  179.   }  
  180. }  
  181.    
  182. void ADC_IRQHandler(void)  
  183. {  
  184.   if( ADC3->SR & (1<<1))  
  185.   {  
  186.     Y0 = (uint16_t)( (float)(( T / C ) * ADC3->DR) //滤波公式  
  187.                       + (float)(( 1 - T / C ) * Y1) );  
  188.     Y1 = Y0;  
  189.     DAC->DHR12R2 = Y0;  //DAC2输出滤波后的结果  
  190.     DAC->SWTRIGR |= (1<<1);  
  191.       
  192.     ADC3->SR &= ~(1<<1);  
  193.   }  
  194. }  


输出的信号:


用AD测量后不经过滤波直接输出:


经过滤波的输出:
结论:经过滤波后,很好地把噪声滤除了,但相位有一定的滞后,幅值会变小。