FFT アナライザ このプログラムの説明は,CQ出版社「トランジスタ技術」の2021年10月号から開始された連載記事「STM32マイコンではじめるPC計測」の中にあります.このプログラムといっしょに使うPC側のプログラムについても同誌を参照してください.
Dependencies: Array_Matrix mbed SerialTxRxIntr DSP_ADDA UIT_FFT_Real Window
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 }
Generated on Tue Jul 12 2022 21:44:08 by 1.7.2