FFT アナライザ このプログラムの説明は,CQ出版社「トランジスタ技術」の2021年10月号から開始された連載記事「STM32マイコンではじめるPC計測」の中にあります.このプログラムといっしょに使うPC側のプログラムについても同誌を参照してください.

Dependencies:   Array_Matrix mbed SerialTxRxIntr DSP_ADDA UIT_FFT_Real Window

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //---------------------------------------------------------------------
00002 //  FFT によるスペクトルアナライザ,白色雑音発生器付き (Nucleo-F446RE 用)
00003 //      ● PC 側のプログラム: "CQ_FFT_Analyzer"
00004 //      ● ボーレート
00005 //          ポートの検索時:   9,600 baud
00006 //          ポートの検索後: 460,800 baud
00007 //
00008 //      ● 入力:  A1
00009 //      ● 白色雑音の出力:A2
00010 //
00011 //  2021/10/22, Copyright (c) 2021 MIKAMI, Naoki
00012 //---------------------------------------------------------------------
00013 
00014 #include <string>
00015 #include "Array.hpp"
00016 #include "DSP_AdcIntr.hpp"
00017 #include "DSP_Dac.hpp"
00018 #include "FFT_Analyzer.hpp"
00019 #include "DoubleBuffer.hpp"
00020 #include "Coefs_IIR_LP.hpp" // 縦続形 IIR フィルタの係数
00021 #include "IirCascade.hpp"   // 縦続形 IIR フィルタ
00022 #include "MSeq16.hpp"       // M 系列発生器
00023 #include "XferSpectrum.hpp"
00024 using namespace Mikami;
00025 
00026 #ifndef __STM32F446xx_H
00027 #error "Use Nucleo-F446RE"
00028 #endif
00029 
00030 const int N_FFT_ = 1024;            // FFT の点数
00031 const int N_FRAME_ = N_FFT_;        // 1フレーム当たり標本化するデータ数
00032 const int N_SPC_ = N_FFT_/2 + 1;    // 有効なスペクトルの点数
00033 const int RATIO_ = 10;              // ダウンサンプリングの倍率:1/10
00034 const int N_TX_ = 501;              // PC に転送するデータ数
00035 
00036 DoubleBuffer buf_(N_FRAME_);            // ダウンサンプリングの結果を保存するバッファ
00037 DspAdcIntr myAdc_(10.24f*RATIO_, A1);   // 標本化周波数: 102.4 kHz
00038 DspDac myDac_;
00039 IirCascade df1_(ORDER1_, CK1_, G01_);   // ダウンサンプリング用 Anti-alias フィルタ
00040 IirCascade df2_(ORDER2_, CK2_, G02_);   // 白色雑音発生用低域通過フィルタ
00041 MSeq16 mSeq_;                           // M 系列信号発生器(N = 16)
00042 
00043 // ADC 変換終了割り込みに対する割り込みサービス・ルーチン
00044 void AdcIsr()
00045 {
00046     static int count = 0;
00047 
00048     float xn = myAdc_.Read();   // AD 変換された値を取得
00049 
00050     float noise = df2_.Execute(mSeq_.Execute());
00051     myDac_.Write(1.6f*noise);   // 白色雑音出力
00052 
00053     float yn = df1_.Execute(xn);    // ダウンサンプリング用 Anti-alias フィルタの実行
00054 
00055     if (++count >= RATIO_)
00056     {
00057         buf_.Store(yn);         // ダウンサンプリングされたデータをバッファへ格納
00058         count = 0;
00059         buf_.IsFullSwitch();    // バッファが満杯であればバッファを切り替える
00060     }
00061 }
00062 
00063 int main()
00064 {
00065     SerialRxTxIntr rxTx;                // PC との通信用,最初は 9600 baud
00066     XferSpectrum tx(rxTx, N_TX_);       // PC に転送するためのオブジェクトの生成
00067     FftAnalyzer analyzer(N_FFT_);       // FFT によるスペクトル解析オブジェクトの生成
00068 
00069     Array<float> sn(N_FFT_, 0.0f);      // スペクトル解析の対象となるデータ
00070     Array<float> absFt(N_SPC_);         // 解析結果:スペクトルの絶対値
00071 
00072     NVIC_SetPriority(ADC_IRQn, 0);      // AD変換終了割り込みの優先度が最高
00073     NVIC_SetPriority(USART2_IRQn, 1);
00074 
00075     bool ready = false; // スペクトルの計算終了で true
00076     bool okGo = false;  // "GO" を受信したら true
00077 
00078     myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て
00079     while (true)
00080     {
00081         // PC からのコマンドの解析
00082         if (rxTx.IsEol())      // 受信バッファのデータが有効になった場合の処理
00083         {
00084             string str = rxTx.GetBuffer();
00085             if (str == "FFTAnalyzer")
00086             {
00087                 rxTx.TxString("ACK\n"); // PC からの "FFTAnalyzer" に対して "ACK" を送信
00088                 wait_ms(10);
00089                 rxTx.Baud(460800);      // 以降は 460,800 baud
00090             }
00091             if (str.substr(0, 2) == "GO")
00092                 okGo = true;  // データの転送要求あり
00093         }
00094 
00095         if (buf_.IsFull())  // 入力データが満杯の場合,以下の処理を行う
00096         {
00097             for (int n=0; n<N_FRAME_; n++) sn[n] = buf_.Get(n);
00098             analyzer.Execute(sn, absFt);    // スペクトル解析の実行
00099             ready = true;                   // スペクトル解析終了
00100         }
00101 
00102         // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する
00103         if (okGo && ready)
00104         {
00105             tx.ToPC(absFt); // データを PC へ転送
00106             ready = false;
00107             okGo = false;
00108         }
00109     }
00110 }