![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
CQ出版社セミナ,2021/12/07開催「実習・C++言語によるArmマイコンのプログラミング」で使うプログラム.
Dependencies: Array_Matrix mbed SerialTxRxIntr UIT_FFT_Real
main.cpp@4:741883d4a075, 2020-02-05 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Wed Feb 05 08:58:16 2020 +0000
- Revision:
- 4:741883d4a075
- Parent:
- 2:d28a3f741217
- Child:
- 5:5e55a5f440c0
5
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:a80f730d32a8 | 1 | //--------------------------------------------------------------------- |
MikamiUitOpen | 0:a80f730d32a8 | 2 | // FFT によるスペクルアナライザ (Nucleo-F446RE 用) |
MikamiUitOpen | 0:a80f730d32a8 | 3 | // |
MikamiUitOpen | 0:a80f730d32a8 | 4 | // ● ST-Link Firmware の V2.J28.M16 で動作確認 |
MikamiUitOpen | 0:a80f730d32a8 | 5 | // |
MikamiUitOpen | 0:a80f730d32a8 | 6 | // ● ST-Link Firmware のアップグレードには stsw-link07.zip |
MikamiUitOpen | 0:a80f730d32a8 | 7 | // に含まれている "ST-LinkUpgrade.exe" を使う |
MikamiUitOpen | 0:a80f730d32a8 | 8 | // |
MikamiUitOpen | 0:a80f730d32a8 | 9 | // ● PC 側のプログラム: "F446_FFT_Analyzer" |
MikamiUitOpen | 0:a80f730d32a8 | 10 | // ● ボーレート: 460800 baud |
MikamiUitOpen | 0:a80f730d32a8 | 11 | // ● 受信データの文字列の終了マーク: "\r" |
MikamiUitOpen | 0:a80f730d32a8 | 12 | // |
MikamiUitOpen | 0:a80f730d32a8 | 13 | // ● 入力: A1 |
MikamiUitOpen | 0:a80f730d32a8 | 14 | // ● モニタ用出力:A2 |
MikamiUitOpen | 0:a80f730d32a8 | 15 | // |
MikamiUitOpen | 0:a80f730d32a8 | 16 | // PC 側のプログラムのフォルダ:プログラム\PC\F446_FFT_Analyzer |
MikamiUitOpen | 0:a80f730d32a8 | 17 | // |
MikamiUitOpen | 4:741883d4a075 | 18 | // 2020/02/05, Copyright (c) 2020 MIKAMI, Naoki |
MikamiUitOpen | 0:a80f730d32a8 | 19 | //--------------------------------------------------------------------- |
MikamiUitOpen | 0:a80f730d32a8 | 20 | |
MikamiUitOpen | 0:a80f730d32a8 | 21 | #include "mbed.h" |
MikamiUitOpen | 0:a80f730d32a8 | 22 | #include <string> |
MikamiUitOpen | 0:a80f730d32a8 | 23 | #include "Array.hpp" |
MikamiUitOpen | 2:d28a3f741217 | 24 | #include "F446_AdcIntr.hpp" |
MikamiUitOpen | 2:d28a3f741217 | 25 | #include "F446_Dac.hpp" |
MikamiUitOpen | 0:a80f730d32a8 | 26 | #include "FFT_Analyzer.hpp" |
MikamiUitOpen | 0:a80f730d32a8 | 27 | #include "DoubleBuffer.hpp" |
MikamiUitOpen | 0:a80f730d32a8 | 28 | #include "Coefs_IIR6_LP_8k_Biquad.hpp" // 縦続形 IIR フィルタの係数 |
MikamiUitOpen | 0:a80f730d32a8 | 29 | #include "IIR_Cascade.hpp" // 縦続形 IIR フィルタ |
MikamiUitOpen | 0:a80f730d32a8 | 30 | #include "Xfer.hpp" |
MikamiUitOpen | 0:a80f730d32a8 | 31 | using namespace Mikami; |
MikamiUitOpen | 0:a80f730d32a8 | 32 | |
MikamiUitOpen | 0:a80f730d32a8 | 33 | const int N_FFT_ = 512; // FFT の点数 |
MikamiUitOpen | 0:a80f730d32a8 | 34 | const int N_FRAME_ = N_FFT_/2; // 1フレーム当たり標本化するデータ数 |
MikamiUitOpen | 0:a80f730d32a8 | 35 | const int N_FFT_2_ = N_FFT_/2; // FFT の点数の半分 |
MikamiUitOpen | 0:a80f730d32a8 | 36 | const int RATIO_ = 10; // オーバーサンプリングの倍率 |
MikamiUitOpen | 0:a80f730d32a8 | 37 | |
MikamiUitOpen | 0:a80f730d32a8 | 38 | DoubleBuffer<float, N_FRAME_> buf_(0); // AD の結果を保存するバッファ |
MikamiUitOpen | 0:a80f730d32a8 | 39 | AdcF446_Intr myAdc_(16*RATIO_, A1); // 標本化周波数: 160 kHz |
MikamiUitOpen | 0:a80f730d32a8 | 40 | DacF446 myDac; |
MikamiUitOpen | 0:a80f730d32a8 | 41 | IirCascade df_(ORDER_, CK_, G0_); // ダウンサンプリング用 Anti-alias フィルタ |
MikamiUitOpen | 0:a80f730d32a8 | 42 | |
MikamiUitOpen | 0:a80f730d32a8 | 43 | // ADC 変換終了割り込みに対する割り込みサービス・ルーチン |
MikamiUitOpen | 0:a80f730d32a8 | 44 | void AdcIsr() |
MikamiUitOpen | 0:a80f730d32a8 | 45 | { |
MikamiUitOpen | 0:a80f730d32a8 | 46 | static int count = 0; |
MikamiUitOpen | 0:a80f730d32a8 | 47 | |
MikamiUitOpen | 0:a80f730d32a8 | 48 | float xn = myAdc_.Read(); |
MikamiUitOpen | 0:a80f730d32a8 | 49 | myDac.Write(xn); // モニタ用 |
MikamiUitOpen | 0:a80f730d32a8 | 50 | float yn = df_.Execute(xn); // ダウンサンプリング用 Anti-alias フィルタの実行 |
MikamiUitOpen | 0:a80f730d32a8 | 51 | |
MikamiUitOpen | 0:a80f730d32a8 | 52 | if (++count >= RATIO_) |
MikamiUitOpen | 0:a80f730d32a8 | 53 | { |
MikamiUitOpen | 0:a80f730d32a8 | 54 | buf_.Store(yn); // ダウンサンプリングされたデータをバッファへ格納 |
MikamiUitOpen | 0:a80f730d32a8 | 55 | count = 0; |
MikamiUitOpen | 0:a80f730d32a8 | 56 | buf_.IfFullSwitch(); // バッファが満杯であればバッファを切り替える |
MikamiUitOpen | 0:a80f730d32a8 | 57 | } |
MikamiUitOpen | 0:a80f730d32a8 | 58 | } |
MikamiUitOpen | 0:a80f730d32a8 | 59 | |
MikamiUitOpen | 0:a80f730d32a8 | 60 | int main() |
MikamiUitOpen | 0:a80f730d32a8 | 61 | { |
MikamiUitOpen | 0:a80f730d32a8 | 62 | SerialRxTxIntr rxTx(32, 460800); // PC との通信用 |
MikamiUitOpen | 0:a80f730d32a8 | 63 | Xfer tx(rxTx, N_FFT_/2+1); // PC に転送するためのオブジェクトの生成 |
MikamiUitOpen | 0:a80f730d32a8 | 64 | FftAnalyzer analyzer(N_FFT_); // FFT によるスペクトル解析オブジェクトの生成 |
MikamiUitOpen | 0:a80f730d32a8 | 65 | |
MikamiUitOpen | 0:a80f730d32a8 | 66 | Array<float> sn(N_FFT_, 0.0f); // スペクトル解析の対象となるデータ |
MikamiUitOpen | 0:a80f730d32a8 | 67 | Array<float> db(N_FRAME_); // 解析結果:対数スペクトル [dB] |
MikamiUitOpen | 0:a80f730d32a8 | 68 | |
MikamiUitOpen | 0:a80f730d32a8 | 69 | NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高 |
MikamiUitOpen | 0:a80f730d32a8 | 70 | NVIC_SetPriority(USART2_IRQn, 1); |
MikamiUitOpen | 0:a80f730d32a8 | 71 | |
MikamiUitOpen | 0:a80f730d32a8 | 72 | bool ready = false; // スペクトルの計算終了で true |
MikamiUitOpen | 0:a80f730d32a8 | 73 | bool okGo = false; // "GO" を受信したら true |
MikamiUitOpen | 0:a80f730d32a8 | 74 | |
MikamiUitOpen | 0:a80f730d32a8 | 75 | myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て |
MikamiUitOpen | 0:a80f730d32a8 | 76 | while (true) |
MikamiUitOpen | 0:a80f730d32a8 | 77 | { |
MikamiUitOpen | 0:a80f730d32a8 | 78 | // PC からのコマンドの解析 |
MikamiUitOpen | 0:a80f730d32a8 | 79 | if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理 |
MikamiUitOpen | 0:a80f730d32a8 | 80 | { |
MikamiUitOpen | 0:a80f730d32a8 | 81 | string str = rxTx.GetBuffer(); |
MikamiUitOpen | 0:a80f730d32a8 | 82 | if (str == "FFTAnalyzer") |
MikamiUitOpen | 4:741883d4a075 | 83 | //// rxTx.Tx("ACK\n"); // PC からの "FFTAnalyzer" に対して "ACK" を送信 |
MikamiUitOpen | 4:741883d4a075 | 84 | rxTx.TxString("ACK\n"); // PC からの "FFTAnalyzer" に対して "ACK" を送信 |
MikamiUitOpen | 0:a80f730d32a8 | 85 | else if (str == "GO") okGo = true; // データの転送要求あり |
MikamiUitOpen | 0:a80f730d32a8 | 86 | } |
MikamiUitOpen | 0:a80f730d32a8 | 87 | |
MikamiUitOpen | 0:a80f730d32a8 | 88 | if (buf_.IsFull()) // 入力データが満杯の場合,以下の処理を行う |
MikamiUitOpen | 0:a80f730d32a8 | 89 | { |
MikamiUitOpen | 0:a80f730d32a8 | 90 | for (int n=0; n<N_FFT_2_; n++) // フレームの後半のデータを前半に移動する |
MikamiUitOpen | 0:a80f730d32a8 | 91 | sn[n] = sn[n+N_FRAME_]; |
MikamiUitOpen | 0:a80f730d32a8 | 92 | for (int n=0; n<N_FRAME_; n++) // フレームの後半には新しいデータを格納する |
MikamiUitOpen | 0:a80f730d32a8 | 93 | sn[n+N_FFT_2_] = buf_.Get(n); |
MikamiUitOpen | 0:a80f730d32a8 | 94 | |
MikamiUitOpen | 0:a80f730d32a8 | 95 | analyzer.Execute(sn, db); // スペクトル解析の実行 |
MikamiUitOpen | 0:a80f730d32a8 | 96 | tx.Convert(db); // スペクトル解析の結果を転送する形式に変換 |
MikamiUitOpen | 0:a80f730d32a8 | 97 | ready = true; // スペクトル解析終了 |
MikamiUitOpen | 0:a80f730d32a8 | 98 | } |
MikamiUitOpen | 0:a80f730d32a8 | 99 | |
MikamiUitOpen | 0:a80f730d32a8 | 100 | // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する |
MikamiUitOpen | 0:a80f730d32a8 | 101 | if (okGo && ready) |
MikamiUitOpen | 0:a80f730d32a8 | 102 | { |
MikamiUitOpen | 0:a80f730d32a8 | 103 | tx.ToPC(); // データを PC へ転送 |
MikamiUitOpen | 0:a80f730d32a8 | 104 | ready = false; |
MikamiUitOpen | 0:a80f730d32a8 | 105 | okGo = false; |
MikamiUitOpen | 0:a80f730d32a8 | 106 | } |
MikamiUitOpen | 0:a80f730d32a8 | 107 | } |
MikamiUitOpen | 4:741883d4a075 | 108 | } |