天天看點

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

完整版教程下載下傳位址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=94547

第49章       STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

本章節講解LMS最小均方自适應濾波器實作,無需Matlab生成系數,可以自學習。

49.1 初學者重要提示

49.2 自适應濾波器介紹

49.3 LMS最小均方自适應濾波器介紹

49.4 Matlab自适應濾波器實作

49.5 自适應濾波器設計

49.6 實驗例程說明(MDK)

49.7 實驗例程說明(IAR)

49.8 總結

  1.   ARM DSP庫提供了LMS最小均方自适應濾波和歸一化最小均方自适應濾波器,推薦使用歸一化方式,因為歸一化方法的步長更容易設定。
  2.   自适應濾波器的濾波因數步長設定比較考究,詳見本章教程第5.3小結。

自适應濾波器能夠根據輸入信号自動調整濾波系數進行數字濾波。作為對比,非自适應濾波器有靜态的濾波器系數,這些靜态系數一起組成傳遞函數。

對于一些應用來說,由于事先并不知道需要進行操作的參數,例如一些噪聲信号的特性,是以要求使用自适應的系數進行處理。在這種情況下,通常使用自适應濾波器,自适應濾波器使用回報來調整濾波器系數以及頻率響應。

随着處理器性能的增強,自适應濾波器的應用越來越常見,時至今日它們已經廣泛地用于手機以及其它通信裝置、數位錄像機和數位照相機以及醫療監測裝置中。

49.3 LMS最小均方介紹

LMS 最小均方自适應濾波器能夠"學習"未知的傳輸特性。LMS濾波器使用梯度下降方法,根據瞬時錯誤信号更新濾波系數。自适應濾波器常用于通信系統、均衡器和降噪。

LMS 濾波器由以下兩個部分組成。第一部分是 FIR 濾波器。第二部分是系數更新機制。LMS 濾波器具有兩個輸入信号。x[n] 是FIR 濾波器輸入,而參考輸入d[n]對應 FIR 濾波器的預期輸出。更新 FIR濾波器系數,以便 FIR濾波器的輸出與參考輸入比對。濾波器系數更新機制基于 FIR 濾波器輸出和參考輸入之間的差異。當濾波器調整時,"錯誤信号"e[n]傾向于為零。LMS 處理功能接受輸入和參考輸入信号,并生成濾波器輸出和錯誤信号。

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

輸出信号 y[n] 由标準 FIR 濾波器計算:

     y[n] = b[0] * x[n] + b[1] * x[n-1] + b[2] * x[n-2] + ...+ b[numTaps-1] * x[n-numTaps+1]

誤差信号等于參考信号 d[n] 和濾波器輸出之間的內插補點:

     e[n] = d[n] - y[n]。

在計算每個樣本的誤差信号後,計算濾波器狀态變量的瞬時能量:

    E = x[n]^2 + x[n-1]^2 + ... + x[n-numTaps+1]^2。

然後在逐個樣本的基礎上更新濾波器系數 b[k]:

     b[k] = b[k] + e[n] * (mu/E) * x[n-k],對于 k=0, 1, ..., numTaps-1

其中 mu 是步長,并且控制系數收斂速度。在函數arm_lms_norm_init_f32中,pCoeffs 指向大小為 numTaps 的濾波器系數數組。系數按時間倒序存儲:

   {b[numTaps-1], b[numTaps-2], b[N-2], ..., b[1], b[0]}

pState 指向一個大小為 numTaps + blockSize - 1 的狀态數組。 狀态緩沖區中的樣本按順序存儲:

 {x[n-numTaps+1], x[n-numTaps], x[n-numTaps-1], x[n-numTaps-2]....x[0], x[1], .. ., x[blockSize-1]}

注意,狀态緩沖區的長度超過了濾波器系數數組的長度 blockSize-1 個樣本。

首先建立兩個混合信号,便于更好測試濾波器效果。

混合信号Mix_Signal_1 = 信号Signal_Original_1+白噪聲。

混合信号Mix_Signal_2 = 信号Signal_Original_2+白噪聲。

Fs = 1000;                                                          %采樣率
N  = 1000;                                                          %采樣點數
n  = 0:N-1;
t   = 0:1/Fs:1-1/Fs;                                                %時間序列
Signal_Original_1 =sin(2*pi*10*t)+sin(2*pi*20*t)+sin(2*pi*30*t);
Noise_White_1    = [0.3*randn(1,500), rand(1,500)]; %前500點高斯分部白噪聲,後500點均勻分布白噪聲
Mix_Signal_1   = Signal_Original_1 + Noise_White_1; %構造的混合信号

Signal_Original_2  =  [zeros(1,100), 20*ones(1,20), -2*ones(1,30), 5*ones(1,80), -5*ones(1,30), 9*ones(1,140), -4*ones(1,40), 3*ones(1,220), 
12*ones(1,100), 5*ones(1,20), 25*ones(1,30), 7 *ones(1,190)];

Noise_White_2     =  0.5*randn(1,1000);                             %高斯白噪聲
Mix_Signal_2        =  Signal_Original_2 + Noise_White_2;           %構造的混合信号      

濾波代碼實作如下:

%****************************************************************************************
%  
%                信号Mix_Signal_1 和 Mix_Signal_2 分别作自适應濾波
%
%***************************************************************************************

%混合信号 Mix_Signal_1 自适應濾波
N=1000;                                             %輸入信号抽樣點數N
k=100;                                              %時域抽頭LMS算法濾波器階數
u=0.001;                                            %步長因子

%設定初值
yn_1=zeros(1,N);                            %output signal
yn_1(1:k)=Mix_Signal_1(1:k);                %将輸入信号SignalAddNoise的前k個值作為輸出yn_1的前k個值
w=zeros(1,k);                               %設定抽頭權重初值
e=zeros(1,N);                               %誤差信号

%用LMS算法疊代濾波
for i=(k+1):N
        XN=Mix_Signal_1((i-k+1):(i));
        yn_1(i)=w*XN';
        e(i)=Signal_Original_1(i)-yn_1(i);
        w=w+2*u*e(i)*XN;
end

subplot(4,1,1);
plot(Mix_Signal_1);                            %Mix_Signal_1 原始信号
axis([k+1,1000,-4,4]);
title('原始信号');

subplot(4,1,2);
plot(yn_1);                                     %Mix_Signal_1 自适應濾波後信号
axis([k+1,1000,-4,4]);
title('自适應濾波後信号');

%混合信号 Mix_Signal_2 自适應濾波
N=1000;                                           %輸入信号抽樣點數N
k=500;                                            %時域抽頭LMS算法濾波器階數
u=0.000011;                                       %步長因子

%設定初值
yn_1=zeros(1,N);                              %output signal
yn_1(1:k)=Mix_Signal_2(1:k);                  %将輸入信号SignalAddNoise的前k個值作為輸出yn_1的前k個值
w=zeros(1,k);                                 %設定抽頭權重初值
e=zeros(1,N);                                 %誤差信号

%用LMS算法疊代濾波
for i=(k+1):N
        XN=Mix_Signal_2((i-k+1):(i));
        yn_1(i)=w*XN';
        e(i)=Signal_Original_2(i)-yn_1(i);
        w=w+2*u*e(i)*XN;
end

subplot(4,1,3);
plot(Mix_Signal_2);                  %Mix_Signal_1 原始信号
axis([k+1,1000,-10,30]);
title('原始信号');

subplot(4,1,4);
plot(yn_1);                          %Mix_Signal_1 自适應濾波後信号
axis([k+1,1000,-10,30]);
title('自适應濾波後信号');      

Matlab運作效果:

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

49.5 自适應器設計

自适應濾波器的主要通過下面兩個函數實作,支援逐點實時濾波。

49.5.1 函數arm_lms_norm_init_f32

函數原型:

void arm_lms_norm_init_f32(
        arm_lms_norm_instance_f32 * S,
        uint16_t numTaps,
        float32_t * pCoeffs,
        float32_t * pState,
        float32_t mu,
        uint32_t blockSize);      

函數描述:

此函數用于自适應濾波器初始化。

函數參數:

  •   第1個參數是arm_lms_norm_instance_f32類型結構體變量。
  •   第2個參數是濾波因數個數。
  •   第3個參數是濾波因數位址。
  •   第4個參數指向狀态變量數組,這個數組用于函數内部計算資料的緩存。
  •   第5個參數用于設定濾波因數更新的步長。
  •   第6個參數是每次處理的資料個數,最小可以每次處理1個資料,最大可以每次全部處理完。

49.5.2 函數arm_lms_norm_f32

void arm_lms_norm_f32(
        arm_lms_norm_instance_f32 * S,
  const float32_t * pSrc,
        float32_t * pRef,
        float32_t * pOut,
        float32_t * pErr,
        uint32_t blockSize);      

此函數用于自适應濾波器實時濾波。

  •   第2個參數是源資料位址。
  •   第3個參數是參考資料位址,需要使用者提供想要逼近的波形效果。
  •   第4個參數是輸出資料位址。
  •   第5個參數是誤差資料位址。

注意事項:

結構體arm_lms_norm_instance_f32的定義如下(在檔案arm_math.h檔案):

typedef struct
  {
          uint16_t numTaps;     /**< number of coefficients in the filter. */
          float32_t *pState;    /**< points to the state variable array. The array is of length
 numTaps+blockSize-1. */
          float32_t *pCoeffs;   /**< points to the coefficient array. The array is of length numTaps. */
          float32_t mu;         /**< step size that control filter coefficient updates. */
          float32_t energy;     /**< saves previous frame energy. */
          float32_t x0;         /**< saves previous input sample. */
  } arm_lms_norm_instance_f32;      

1、參數numTaps用于設定濾波因數個數。

2、pState指向狀态變量數組,這個數組用于函數内部計算資料的緩存。

3、參數pCoeffs指向濾波因數,濾波因數數組長度為numTaps。但要注意pCoeffs指向的濾波因數應該按照如下的逆序進行排列:

{b[numTaps-1],  b[numTaps-2],  b[N-2],  ...,  b[1],  b[0]} 

但滿足線性相位特性的FIR濾波器具有奇對稱或者偶對稱的系數,偶對稱時逆序排列還是他本身。

4、參數mu用于設定濾波因數更新的步長。

5、blockSize 這個參數的大小沒有特殊要求,最小可以每次處理1個資料,最大可以每次全部處理完。

49.5.3 濾除200Hz正弦波測試(含不同步長測試,重要)

原始波形200Hz + 50Hz正弦波,濾除200Hz正弦波測試:

/*
*********************************************************************************************************
*    函 數 名: arm_lms_f32_test1
*    功能說明: 原始波形200Hz + 50Hz正弦波,濾除200Hz正弦波。
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void arm_lms_f32_test1(void)
{
    uint32_t i;
    float32_t  *inputF32, *outputF32, *inputREF, *outputERR;
    arm_lms_norm_instance_f32 lmsS={0};

    
    for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    {
        /* 50Hz正弦波+200Hz正弦波,采樣率1KHz */
        testInput_f32_50Hz_200Hz[i] = arm_sin_f32(2*3.1415926f*50*i/1000) +
 arm_sin_f32(2*3.1415926f*200*i/1000);
        testInput_f32_REF[i] =  arm_sin_f32(2*3.1415926f*50*i/1000);
    }
    
    /* 如果是實時性的濾波,僅需清零一次 */
    memset(lmsCoeffs32,0,sizeof(lmsCoeffs32));
    memset(lmsStateF32,0,sizeof(lmsStateF32));    

    /* 初始化輸入輸出緩存指針 */
    inputF32 = (float32_t *)&testInput_f32_50Hz_200Hz[0]; /* 原始波形 */
    outputF32 = (float32_t *)&testOutput[0];              /* 濾波後輸出波形 */
    inputREF = (float32_t *)&testInput_f32_REF[0];        /* 參考波形 */  
    outputERR = (float32_t *)&test_f32_ERR[0];            /* 誤差資料 */  
 
    
    /* 歸一化LMS初始化 */
    arm_lms_norm_init_f32 (&lmsS,                            /* LMS結構體 */
                           NUM_TAPS,                      /* 濾波器系數個數 */
                            (float32_t *)&lmsCoeffs32[0], /* 濾波 */ 
                            &lmsStateF32[0],              /* 濾波器系數 */
                            0.1,                          /* 步長 */
                            blockSize);                   /* 處理的資料個數 */



    /* 實作LMS自适應濾波,這裡每次處理1個點 */
    for(i=0; i < numBlocks; i++)
    {
        
        arm_lms_norm_f32(&lmsS, /* LMS結構體 */
                        inputF32 + (i * blockSize),      /* 輸入資料 */
                        inputREF + (i * blockSize),      /* 輸出資料 */
                        outputF32 + (i * blockSize),     /* 參考資料 */
                        outputERR + (i * blockSize),     /* 誤差資料 */
                        blockSize);                     /* 處理的資料個數 */

    }
    

    /* 列印濾波後結果 */
    for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    {
        printf("%f, %f, %f\r\n", testInput_f32_50Hz_200Hz[i], outputF32[i], test_f32_ERR[i]);
    }
}      

下面是濾波因數步長調節為0.1時的濾波器效果,淺藍色是原始波形,黃色黃色是濾波後波形,綠色是誤內插補點:

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

步長為0.01時效果,可以看到逼近參考波形的速度較慢:

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

步長為1的效果,逼近參考波形的速度更快,前面的波形由一段陡增。

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

關于步長,沒有特别好的方式直接鎖定那種步長大小更合适,一般的處理思路是按照10倍關系先鎖定範圍,比如先測試步長為1,0.1,0.001等來測試,然後進一步設定一個合适的值。

49.5.4 濾除白噪聲測試(一)

原始波形由任意波形+ 高斯分布白噪聲 + 均勻分布白噪聲組成,濾除高斯分布白噪聲 + 均勻分布白噪聲。

/*
*********************************************************************************************************
*    函 數 名: arm_lms_f32_test2
*    功能說明: 原始波形由任意波形+ 高斯分布白噪聲 + 均勻分布白噪聲組成,濾除高斯分布白噪聲 + 均勻分布白噪聲。
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void arm_lms_f32_test2(void)
{
    uint32_t i;
    arm_lms_norm_instance_f32 lmsS;
    float32_t  *inputF32, *outputF32, *inputREF, *outputERR;
    
    /* 如果是實時性的濾波,僅需清零一次 */
    memset(lmsCoeffs32,0,sizeof(lmsCoeffs32));
    memset(lmsStateF32,0,sizeof(lmsStateF32));        

    /* 初始化輸入輸出緩存指針 */
    inputF32 = (float32_t *)&MixData[0];       /* 原始波形 */
    outputF32 = (float32_t *)&testOutput[0];   /* 濾波後輸出波形 */
    inputREF = (float32_t *)&OrigalData[0];    /* 參考波形 */  
    outputERR = (float32_t *)&test_f32_ERR[0]; /* 誤差資料 */  

    
    /* 歸一化LMS初始化 */
    arm_lms_norm_init_f32 (&lmsS,                         /* LMS結構體 */
                           NUM_TAPS,                      /* 濾波器系數個數 */
                            (float32_t *)&lmsCoeffs32[0], /* 濾波 */ 
                            &lmsStateF32[0],              /* 濾波器系數 */
                            0.01,                          /* 步長 */
                            blockSize);                   /* 處理的資料個數 */


    /* 實作LMS自适應濾波,這裡每次處理1個點 */
    for(i=0; i < numBlocks; i++)
    {
        
        arm_lms_norm_f32(&lmsS, /* LMS結構體 */
                        inputF32 + (i * blockSize),   /* 輸入資料 */
                        inputREF + (i * blockSize),   /* 輸出資料 */
                        outputF32 + (i * blockSize),  /* 參考資料 */
                        outputERR + (i * blockSize),  /* 誤差資料 */
                        blockSize);                      /* 處理的資料個數 */

    }
    
    
    /* 列印濾波後結果 */
    for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    {
        printf("%f, %f, %f\r\n", MixData[i], outputF32[i], test_f32_ERR[i]);
    }
    
}      

下面是濾波因數步長調節為0.01時的濾波器效果,淺藍色是原始波形,黃色黃色是濾波後波形,綠色是誤內插補點:

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

這個波形做了兩個周期,前1024點和後1024點,後面1024點濾除白噪聲的效果已經比較好,而前1024的點的前半段一直在逼近我們設定的參考波形中。另外從誤內插補點波形中,我們可以看到原始波形跳變的地方,誤內插補點也會有一個跳變,然後向0趨近。這是自适應濾波器特性決定的,不斷的調節濾波器系數中。

我們再來看下将濾波因數步長調節為0.1時的效果:

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

可以看到逼近速度很快,但是逼近效果一般,也就是白噪聲的濾除效果一般。

49.5.5 濾除白噪聲測試(二)

原始波形10Hz正弦波 + 20Hz正弦波 + 30Hz正弦波 + 高斯分布白噪聲 + 均勻分布白噪聲。濾除高斯分布白噪聲 + 均勻分布白噪聲。

/*
*********************************************************************************************************
*    函 數 名: arm_lms_f32_test3
*    功能說明: 10Hz正弦波 + 20Hz正弦波 + 30Hz正弦波 + 高斯分布白噪聲 + 均勻分布白噪聲,濾除高斯分布白噪聲 + 均勻分布白噪聲
*    形    參: 無
*    返 回 值: 無
*********************************************************************************************************
*/
void arm_lms_f32_test3(void)
{    
    uint32_t i;
    arm_lms_norm_instance_f32 lmsS;
    float32_t  *inputF32, *outputF32, *inputREF, *outputERR;
    
    
    /* 如果是實時性的濾波,僅需清零一次 */
    memset(lmsCoeffs32,0,sizeof(lmsCoeffs32));
    memset(lmsStateF32,0,sizeof(lmsStateF32));    
    
    /* 初始化輸入輸出緩存指針 */
    inputF32 = (float32_t *)&MixData1[0];       /* 原始波形 */
    outputF32 = (float32_t *)&testOutput[0];    /* 濾波後輸出波形 */
    inputREF = (float32_t *)&OrigalData1[0];    /* 參考波形 */  
    outputERR = (float32_t *)&test_f32_ERR[0];  /* 誤差資料 */  

    /* 歸一化LMS初始化 */
    arm_lms_norm_init_f32 (&lmsS,                         /* LMS結構體 */
                           NUM_TAPS,                      /* 濾波器系數個數 */
                            (float32_t *)&lmsCoeffs32[0], /* 濾波 */ 
                            &lmsStateF32[0],              /* 濾波器系數 */
                            0.1,                          /* 步長 */
                            blockSize);                   /* 處理的資料個數 */


    /* 實作LMS自适應濾波,這裡每次處理1個點 */
    for(i=0; i < numBlocks; i++)
    {
        
        arm_lms_norm_f32(&lmsS, /* LMS結構體 */
                        inputF32 + (i * blockSize),   /* 輸入資料 */
                        inputREF + (i * blockSize),   /* 輸出資料 */
                        outputF32 + (i * blockSize),  /* 參考資料 */
                        outputERR + (i * blockSize),  /* 誤差資料 */
                        blockSize);                      /* 處理的資料個數 */

    }
    
    /* 列印濾波後結果 */
    for(i=0; i<TEST_LENGTH_SAMPLES; i++)
    {
        printf("%f, %f, %f\r\n", MixData1[i], outputF32[i], test_f32_ERR[i]);
    }
    
}      
【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

配套例子:

V6-234_自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

實驗目的:

  1. 學習LMS最小均方濾波器。

實驗内容:

  1. 啟動一個自動重裝軟體定時器,每100ms翻轉一次LED2。
  2. 按下按鍵K1,列印測試波形1和濾波後的波形資料。
  3. 按下按鍵K2,列印測試波形2和濾波後的波形資料。
  4. 按下按鍵K3,列印測試波形3和濾波後的波形資料。

使用AC6注意事項

特别注意附件章節C的問題

上電後序列槽列印的資訊:

波特率 115200,資料位 8,奇偶校驗位無,停止位 1。

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

RTT方式列印資訊:

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

程式設計:

  系統棧大小配置設定:

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)

  硬體外設初始化

硬體外設的初始化是在 bsp.c 檔案實作:

/*
*********************************************************************************************************
*    函 數 名: bsp_Init
*    功能說明: 初始化所有的硬體裝置。該函數配置CPU寄存器和外設的寄存器并初始化一些全局變量。隻需要調用一次
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_Init(void)
{
    /* 
       STM32F429 HAL 庫初始化,此時系統用的還是F429自帶的16MHz,HSI時鐘:
       - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。
       - 設定NVIC優先級分組為4。
     */
    HAL_Init();

    /* 
       配置系統時鐘到168MHz
       - 切換使用HSE。
       - 此函數會更新全局變量SystemCoreClock,并重新配置HAL_InitTick。
    */
    SystemClock_Config();

    /* 
       Event Recorder:
       - 可用于代碼執行時間測量,MDK5.25及其以上版本才支援,IAR不支援。
       - 預設不開啟,如果要使能此選項,務必看V5開發闆使用者手冊第8章
    */    
#if Enable_EventRecorder == 1  
    /* 初始化EventRecorder并開啟 */
    EventRecorderInitialize(EventRecordAll, 1U);
    EventRecorderStart();
#endif
    
    bsp_InitKey();        /* 按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描 */
    bsp_InitTimer();      /* 初始化滴答定時器 */
    bsp_InitUart();    /* 初始化序列槽 */
    bsp_InitExtIO();   /* 初始化擴充IO */
    bsp_InitLed();        /* 初始化LED */
}      

  主功能:

主程式實作如下操作:

  •   啟動一個自動重裝軟體定時器,每100ms翻轉一次LED2。
  •   按下按鍵K1,列印測試波形1和濾波後的波形資料。
  •   按下按鍵K2,列印測試波形2和濾波後的波形資料。
  •   按下按鍵K3,列印測試波形3和濾波後的波形資料。
/*
*********************************************************************************************************
*    函 數 名: main
*    功能說明: c程式入口
*    形    參: 無
*    返 回 值: 錯誤代碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{
    uint8_t ucKeyCode;        /* 按鍵代碼 */
    uint16_t i;

    bsp_Init();        /* 硬體初始化 */
    PrintfLogo();    /* 列印例程資訊到序列槽1 */

    PrintfHelp();    /* 列印操作提示資訊 */
        

    bsp_StartAutoTimer(0, 100);    /* 啟動1個100ms的自動重裝的定時器 */

    /* 進入主程式循環體 */
    while (1)
    {
        bsp_Idle();        /* 這個函數在bsp.c檔案。使用者可以修改這個函數實作CPU休眠和喂狗 */
        

        if (bsp_CheckTimer(0))    /* 判斷定時器逾時時間 */
        {
            /* 每隔100ms 進來一次 */
            bsp_LedToggle(2);    /* 翻轉LED的狀态 */
        }
        
        ucKeyCode = bsp_GetKey();    /* 讀取鍵值, 無鍵按下時傳回 KEY_NONE = 0 */
        if (ucKeyCode != KEY_NONE)
        {
            switch (ucKeyCode)
            {
                case KEY_DOWN_K1:            /* K1鍵按下 */
                    arm_lms_f32_test1();
                    break;
                
                case KEY_DOWN_K2:            /* K2鍵按下 */
                    arm_lms_f32_test2();
                    break;
                
                case KEY_DOWN_K3:            /* K3鍵按下 */
                    arm_lms_f32_test3();
                    break;                
    
                default:
                    /* 其它的鍵值不處理 */
                    break;
            }
        }

    }
}      

【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)
【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)
【STM32F429的DSP教程】第49章 STM32F429的自适應濾波器實作,無需Matlab生成系數(支援實時濾波)
/*
*********************************************************************************************************
*    函 數 名: bsp_Init
*    功能說明: 初始化所有的硬體裝置。該函數配置CPU寄存器和外設的寄存器并初始化一些全局變量。隻需要調用一次
*    形    參:無
*    返 回 值: 無
*********************************************************************************************************
*/
void bsp_Init(void)
{
    /* 
       STM32F407 HAL 庫初始化,此時系統用的還是F407自帶的16MHz,HSI時鐘:
       - 調用函數HAL_InitTick,初始化滴答時鐘中斷1ms。
       - 設定NVIC優先級分組為4。
     */
    HAL_Init();

    /* 
       配置系統時鐘到168MHz
       - 切換使用HSE。
       - 此函數會更新全局變量SystemCoreClock,并重新配置HAL_InitTick。
    */
    SystemClock_Config();

    /* 
       Event Recorder:
       - 可用于代碼執行時間測量,MDK5.25及其以上版本才支援,IAR不支援。
       - 預設不開啟,如果要使能此選項,務必看V5開發闆使用者手冊第8章
    */    
#if Enable_EventRecorder == 1  
    /* 初始化EventRecorder并開啟 */
    EventRecorderInitialize(EventRecordAll, 1U);
    EventRecorderStart();
#endif
    
    bsp_InitKey();        /* 按鍵初始化,要放在滴答定時器之前,因為按鈕檢測是通過滴答定時器掃描 */
    bsp_InitTimer();      /* 初始化滴答定時器 */
    bsp_InitUart();    /* 初始化序列槽 */
    bsp_InitLed();        /* 初始化LED */        
}      
/*
*********************************************************************************************************
*    函 數 名: main
*    功能說明: c程式入口
*    形    參: 無
*    返 回 值: 錯誤代碼(無需處理)
*********************************************************************************************************
*/
int main(void)
{
    uint8_t ucKeyCode;        /* 按鍵代碼 */
    uint16_t i;

    bsp_Init();        /* 硬體初始化 */
    PrintfLogo();    /* 列印例程資訊到序列槽1 */

    PrintfHelp();    /* 列印操作提示資訊 */
        

    bsp_StartAutoTimer(0, 100);    /* 啟動1個100ms的自動重裝的定時器 */

    /* 進入主程式循環體 */
    while (1)
    {
        bsp_Idle();        /* 這個函數在bsp.c檔案。使用者可以修改這個函數實作CPU休眠和喂狗 */
        

        if (bsp_CheckTimer(0))    /* 判斷定時器逾時時間 */
        {
            /* 每隔100ms 進來一次 */
            bsp_LedToggle(2);    /* 翻轉LED的狀态 */
        }
        
        ucKeyCode = bsp_GetKey();    /* 讀取鍵值, 無鍵按下時傳回 KEY_NONE = 0 */
        if (ucKeyCode != KEY_NONE)
        {
            switch (ucKeyCode)
            {
                case KEY_DOWN_K1:            /* K1鍵按下 */
                    arm_lms_f32_test1();
                    break;
                
                case KEY_DOWN_K2:            /* K2鍵按下 */
                    arm_lms_f32_test2();
                    break;
                
                case KEY_DOWN_K3:            /* K3鍵按下 */
                    arm_lms_f32_test3();
                    break;                
    
                default:
                    /* 其它的鍵值不處理 */
                    break;
            }
        }

    }
}      

本章節主要講解了自适應濾波器,功能比較強勁,熟練應用需要多做測試。

微信公衆号:armfly_com

安富萊論壇:www.armbbs.cn

安富萊淘寶:https://armfly.taobao.com