stm32f407之數字濾波(操作寄存器)

數字濾波


      爲了對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

 

 

程序:

/************************************
    標題:數字濾波實驗
    軟件平臺: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測量後不經過濾波直接輸出:




經過濾波的輸出:


結論:經過濾波後,很好地把噪聲濾除了,但相位有一定的滯後,幅值會變小。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章