CQ出版社セミナ,2021/12/07開催「実習・C++言語によるArmマイコンのプログラミング」で使うプログラム.

Dependencies:   Array_Matrix mbed SerialTxRxIntr UIT_FFT_Real

Revision:
0:a80f730d32a8
Child:
2:d28a3f741217
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jan 15 12:43:11 2020 +0000
@@ -0,0 +1,108 @@
+//---------------------------------------------------------------------
+//  FFT によるスペクルアナライザ (Nucleo-F446RE 用)
+//
+//      ● ST-Link Firmware の V2.J28.M16 で動作確認
+//
+//      ● ST-Link Firmware のアップグレードには stsw-link07.zip
+//        に含まれている "ST-LinkUpgrade.exe" を使う 
+//
+//      ● PC 側のプログラム: "F446_FFT_Analyzer"
+//      ● ボーレート: 460800 baud
+//      ● 受信データの文字列の終了マーク: "\r"
+//
+//      ● 入力:  A1
+//      ● モニタ用出力:A2
+//
+//  PC 側のプログラムのフォルダ:プログラム\PC\F446_FFT_Analyzer
+//
+//  2020/01/13, Copyright (c) 2020 MIKAMI, Naoki
+//---------------------------------------------------------------------
+
+#include "mbed.h"
+#include <string>
+#include "Array.hpp"
+#include "F446_ADC_Intr.hpp"
+#include "F446_DAC.hpp"
+#include "FFT_Analyzer.hpp"
+#include "DoubleBuffer.hpp"
+#include "Coefs_IIR6_LP_8k_Biquad.hpp"  // 縦続形 IIR フィルタの係数
+#include "IIR_Cascade.hpp"              // 縦続形 IIR フィルタ
+#include "Xfer.hpp"
+using namespace Mikami;
+
+const int N_FFT_ = 512;             // FFT の点数
+const int N_FRAME_ = N_FFT_/2;      // 1フレーム当たり標本化するデータ数
+const int N_FFT_2_ = N_FFT_/2;      // FFT の点数の半分
+const int RATIO_ = 10;              // オーバーサンプリングの倍率
+
+DoubleBuffer<float, N_FRAME_> buf_(0);    // AD の結果を保存するバッファ
+AdcF446_Intr myAdc_(16*RATIO_, A1); // 標本化周波数: 160 kHz
+DacF446 myDac;
+IirCascade df_(ORDER_, CK_, G0_);   // ダウンサンプリング用 Anti-alias フィルタ
+
+// ADC 変換終了割り込みに対する割り込みサービス・ルーチン
+void AdcIsr()
+{
+    static int count = 0;
+
+    float xn = myAdc_.Read();
+    myDac.Write(xn);            // モニタ用
+    float yn = df_.Execute(xn); // ダウンサンプリング用 Anti-alias フィルタの実行
+
+    if (++count >= RATIO_)
+    {
+        buf_.Store(yn);         // ダウンサンプリングされたデータをバッファへ格納
+        count = 0;
+        buf_.IfFullSwitch();    // バッファが満杯であればバッファを切り替える
+    }
+}
+
+int main()
+{
+    SerialRxTxIntr rxTx(32, 460800);    // PC との通信用
+    Xfer tx(rxTx, N_FFT_/2+1);          // PC に転送するためのオブジェクトの生成
+    FftAnalyzer analyzer(N_FFT_);       // FFT によるスペクトル解析オブジェクトの生成
+
+    Array<float> sn(N_FFT_, 0.0f);      // スペクトル解析の対象となるデータ
+    Array<float> db(N_FRAME_);          // 解析結果:対数スペクトル [dB]
+
+    NVIC_SetPriority(ADC_IRQn, 0);      // AD変換終了割り込みの優先度が最高
+    NVIC_SetPriority(USART2_IRQn, 1);
+
+    bool ready = false; // スペクトルの計算終了で true
+    bool okGo = false;  // "GO" を受信したら true
+
+    myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て
+    while (true)
+    {
+        // PC からのコマンドの解析
+        if (rxTx.IsEol())      // 受信バッファのデータが有効になった場合の処理
+        {
+            string str = rxTx.GetBuffer();
+            if (str == "FFTAnalyzer")
+                rxTx.Tx("ACK\n");  // PC からの "FFTAnalyzer" に対して "ACK" を送信
+            else if (str == "GO") okGo = true;  // データの転送要求あり
+        }
+
+        if (buf_.IsFull())  // 入力データが満杯の場合,以下の処理を行う
+        {
+            for (int n=0; n<N_FFT_2_; n++)  // フレームの後半のデータを前半に移動する
+                sn[n] = sn[n+N_FRAME_];
+            for (int n=0; n<N_FRAME_; n++)  // フレームの後半には新しいデータを格納する
+                sn[n+N_FFT_2_] = buf_.Get(n);
+
+            analyzer.Execute(sn, db);   // スペクトル解析の実行
+            tx.Convert(db);             // スペクトル解析の結果を転送する形式に変換
+            ready = true;               // スペクトル解析終了
+        }
+
+        // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する
+        if (okGo && ready)
+        {
+            tx.ToPC();      // データを PC へ転送
+            ready = false;
+            okGo = false;
+        }
+    }
+}
+