打印
[STM32F4]

【转】stm32f407之数字滤波(操作寄存器)

[复制链接]
1717|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
焚琴煮鹤|  楼主 | 2016-9-10 21:36 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

   为了对stm32f4的ADC和DAC有更多的了解,我决定做一个实用性比较强的实验。就是数字滤波实验,利用stm32f4的DAC可以产生噪声的特点,利用它的一路DAC产生叠加噪声的信号作为原始信号。然后用ADC测量,把结果经过滤波处理后用DAC的另一通道把结果输出,用双踪示波器观察。

一阶惯性滤波器及其数字化

一阶惯性滤波器的传递函数为:


利用一阶差分法离散化,可以得到一阶惯性数字滤波算法:


其中T为采样周期,为滤波时间常数。T和必须根据信号频谱来选择。



沙发
焚琴煮鹤|  楼主 | 2016-9-10 21:37 | 只看该作者
编程实现:
a.     设定一个1024点正弦波表,用DAC1叠加噪声输出
b.     配置定时器6更新频率为1M
c.     DAC的时钟为TIM6更新事件,1024点,频率大概为0.5M
d.     在TIM6的更新中断中启动一次AD转换
e.     AD转换中断中做滤波处理,然后把数值送DAC2,启动一次DAC2


程序:

[plain] view plain copy


  • /************************************  
  •     标题:数字滤波实验  
  •     软件平台:IAR for ARM6.21  
  •     硬件平台:stm32f4-discovery  
  •     主频:168M  
  •   
  •     描述:用DAC1产生一路叠加了噪声的信号  
  •           用ADC通道11测量上面产生的信号  
  •           对ADC的测量结果进行滤波处理  
  •           用DAC2把滤波后的结果输出  
  •       
  •     author:小船  
  •     data:2012-02-17  
  • *************************************/  
  •   
  • #include <stm32f4xx.h>   
  • #include "MyDebugger.h"  
  • #include "sintable.h"   
  •   
  • /*********变量声明********/  
  • uint16_t Y0, Y1;//滤波器输出值  
  • float T = 0.000001;//采样周期  
  • float C = 0.00003; //滤波常数  
  •   
  • /*********函数声明********/  
  • void timer6_Init(void);  
  • void ADC3_IN11_Config(void);  
  • void DAC_channel2_Config(void);  
  • void Generate_SinSignal_with_Noise(void);  
  •   
  • void main ()  
  • {     
  •   
  •   SCB->AIRCR = 0x05FA0000 | 0x400;  //中断优先级分组 抢占:响应=3:1  
  •    
  •   MyDebugger_Init();  
  •    
  •   ADC3_IN11_Config();  
  •   Generate_SinSignal_with_Noise();  
  •   DAC_channel2_Config();   
  •   timer6_Init();   
  •   
  •   while(1)  
  •   {  
  •   };  
  • }  
  •   
  • /**************************************  
  •   函数名:timer6_Init  
  •   参数:无  
  •   返回值:无  
  •   功能:设置定时器6更新频率为1M  
  •         定时器6更新事件为DAC1、2时钟  
  •         更新中断启动ADC检测  
  • **************************************/  
  • void timer6_Init(void)  
  • {  
  •   /***定时器设置***/  
  •   RCC->APB1ENR |= (1<<4);//打开TIM6时钟  
  •   TIM6->PSC = 0;   
  •   TIM6->ARR = 83;  //使得更新事件频率为1m  
  •   TIM6->CR2 |=  0x00000020;//更新事件输出  
  •   TIM6->DIER |= 1; //使能中断  
  •   TIM6->CR1 |= 1; //开始计时  
  • }  
  •   
  • /**************************************  
  •   函数名:Generate_SinSignal_with_Noise  
  •   参数:无  
  •   返回值:无  
  •   功能:用DAC1产生一路叠加了噪声的信号  
  • ***************************************/  
  • void Generate_SinSignal_with_Noise(void)  
  • {  
  •   /***GPIO设置***/  
  •   RCC->AHB1ENR |= (1<<0); //打开GPIOA时钟  
  •   GPIOA->MODER |= 0x00000F00;//PA4、5模拟模式  
  •   GPIOA->PUPDR &= 0xfffff0ff;//无上拉无下拉     
  •    
  •   /***DAC设置***/  
  •   RCC->APB1ENR |= (1<<29); //使能DAC时钟  
  •   DAC->CR &= 0xffff0000;  
  •   /*  
  •   使能DMA堵塞中断  
  •   使能通道1触发  
  •   叠加噪声  
  •   */  
  •   DAC->CR |= ( (1<<13) | (1<<2) | 0x00000040 | 0x00000800);   
  •   NVIC->IP[54] = 0xA0;  
  •   NVIC->ISER[1] |= (1<<(54-32));  
  •    
  •   /***DMA设置***/  
  •   RCC->AHB1ENR |= (1<<21); //使能DMA1时钟  
  •   DAC->CR &= ~(1<<12);//DAC dma发送模式除能  
  •   DMA1_Stream5->CR &= 0xFFFFFFFE; //除能DMA1_Stream5  
  •   while(DMA1_Stream5->CR & 0x00000001);//确保DMA可以被设置   
  •   DMA1->HIFCR |= 0x000004f0;//传送前清空DMA1_Stream5所有中断标志   
  •   DMA1_Stream5->PAR = (uint32_t)&DAC->DHR12R1;//设置外设地址  
  •   DMA1_Stream5->M0AR = (uint32_t)SinTable; //设置内存地址  
  •   DMA1_Stream5->CR |= 0x0002800;//16位数据  
  •   DMA1_Stream5->NDTR = 1024; //设置dma传输数据的数量  
  •   /*  
  •     设置dma通道7,即DAC1  
  •     优先级Medium  
  •     传输方向内存到外设  
  •     内存递增模式  
  •     循环模式  
  •   */  
  •   DMA1_Stream5->CR |= ( 0x0e000000 | 0x00010000 | (1<<6)  
  •                         | (1<<10) | (1<<8) );   
  •    
  •   DMA1_Stream5->CR |= 1; //DMA数据流5使能  
  •    
  •   DAC->CR |= (1<<0);   //DAC通道1使能  
  •   
  •   DAC->CR |= (1<<12);//DAC dma发送模式使能  
  • }  
  •   
  • /**************************************  
  •   函数名:ADC3_IN11_Config  
  •   参数:无  
  •   返回值:无  
  •   功能:用ADC通道11测量上面产生的信号  
  • ***************************************/  
  • void ADC3_IN11_Config(void)  
  • {  
  •     /***GPIO设置***/  
  •   RCC->AHB1ENR |= (1<<2); //打开GPIOC时钟  
  •   GPIOC->MODER &= 0xfffffff3;//PC1模拟模式  
  •   GPIOC->MODER |= 0x0000000C;  
  •   GPIOC->PUPDR &= 0xfffffff3;//无上拉无下拉     
  •    
  •   /***ADC3设置***/  
  •   RCC->APB2ENR |= (1<<10); //使能ADC3时钟  
  •   ADC3->SQR1 = 0x00000000;//转换一个通道  
  •   ADC3->SQR3 = 0x0000000B;//第一个通道为ADC3_in11  
  •   ADC3->CR1 &= 0x00000000;   
  •   ADC3->CR2 &= 0x00000000;   
  • //单次转换  
  •   ADC3->CR1 |= (1<<5);//使能转换完成中断  
  •   NVIC->IP[18] = 0xc0;  
  •   NVIC->ISER[0] |= (1<<18);   
  • }  
  •   
  • /**************************************  
  •   函数名:DAC_channel2_Config  
  •   参数:无  
  •   返回值:无  
  •   功能:用DAC2把滤波后的结果输出  
  • ***************************************/  
  • void DAC_channel2_Config(void)  
  • {  
  •   /***DAC设置***/  
  •   RCC->APB1ENR |= (1<<29); //使能DAC时钟  
  •   DAC->CR &= 0x0000ffff;  
  •   /*  
  •   使能通道2触发   
  •   配置为软件触发  
  •   */  
  •   DAC->CR |= ( (1<<18) | (0x00380000) );   
  •    
  •   DAC->CR |= (1<<16);   //DAC通道2使能  
  • }  
  •   
  • void TIM6_DAC_IRQHandler(void)  
  • {  
  •   if( DAC->SR & (1<<13) )  
  •   {  
  •     MyDebugger_LEDs(red, on);//亮红灯指示DAC1的DMA传输数据错误  
  •     DAC->SR &= ~(1<<13);   
  •   }  
  •    
  •   if(TIM6->SR)  
  •   {      
  •     ADC3->CR2 |= (1<<0);   //开启AD转换   
  •     ADC3->CR2 |= (1<<30); //规则通道转换开始  
  •       
  •     TIM6->SR &= ~(0x0001);   
  •   }  
  • }  
  •    
  • void ADC_IRQHandler(void)  
  • {  
  •   if( ADC3->SR & (1<<1))  
  •   {  
  •     Y0 = (uint16_t)( (float)(( T / C ) * ADC3->DR) //滤波公式  
  •                       + (float)(( 1 - T / C ) * Y1) );  
  •     Y1 = Y0;  
  •     DAC->DHR12R2 = Y0;  //DAC2输出滤波后的结果  
  •     DAC->SWTRIGR |= (1<<1);  
  •       
  •     ADC3->SR &= ~(1<<1);  
  •   }  
  • }  





输出的信号:





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




经过滤波的输出:


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

使用特权

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

本版积分规则

63

主题

106

帖子

3

粉丝