Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Array_Matrix mbed SerialTxRxIntr MyTicker7
Revision 0:53c0fa8a9aa2, committed 2021-09-09
- Comitter:
- MikamiUitOpen
- Date:
- Thu Sep 09 08:50:21 2021 +0000
- Child:
- 1:0430f1ed6c2c
- Commit message:
- 1
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Array_Matrix.lib Thu Sep 09 08:50:21 2021 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/MikamiUitOpen/code/Array_Matrix/#d3aa1ddb57e1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/F446_DAC.cpp Thu Sep 09 08:50:21 2021 +0000
@@ -0,0 +1,28 @@
+//-------------------------------------------------------------
+// STM32F446 内蔵の DAC 用のクラス
+// DAC_OUT1: A2 (PA_4)
+// DAC_OUT2: D13 (PA_5)
+//
+// 2020/10/17, Copyright (c) 2020 MIKAMI, Naoki
+//-------------------------------------------------------------
+
+#include "F446_DAC.hpp"
+
+namespace Mikami
+{
+ DacF446::DacF446(PinName pin) : da_(pin)
+ {
+ MBED_ASSERT((pin == A2) || (pin == D13));
+
+ if (pin == A2)
+ {
+ DAC->CR = DAC_CR_EN1;
+ fpWriteDac = &DacF446::WriteDac1;
+ }
+ else
+ {
+ DAC->CR = DAC_CR_EN2;
+ fpWriteDac = &DacF446::WriteDac2;
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/F446_DAC.hpp Thu Sep 09 08:50:21 2021 +0000
@@ -0,0 +1,57 @@
+//-------------------------------------------------------------
+// STM32F446 内蔵の DAC 用のクラス(ヘッダ)
+// 選択可能な入力端子:
+// A2 (PA_4): ---- デフォルト
+// D13 (PA_5): このポートはマイコンボードの LED も
+// ドライブするので使わない方がよい
+//
+// 2020/10/17, Copyright (c) 2020 MIKAMI, Naoki
+//-------------------------------------------------------------
+
+#include "mbed.h"
+
+#ifndef STM32F446xx
+#error Not NUCLEO-F446RE.
+#endif
+
+#ifndef F446_DAC_SINGLE_HPP
+#define F446_DAC_SINGLE_HPP
+
+namespace Mikami
+{
+ class DacF446
+ {
+ public:
+ // コンストラクタ
+ explicit DacF446(PinName pin = A2);
+
+ virtual ~DacF446() {}
+
+ // -1.0f <= data <= 1.0f
+ void Write(float data) { WriteDac(ToUint16(data)); }
+
+ // 0 <= data <= 4095
+ void Write(uint16_t data) { WriteDac(__USAT(data, BIT_WIDTH_)); }
+
+ private:
+ void (DacF446::*fpWriteDac)(uint16_t);
+
+ static const int BIT_WIDTH_ = 12;
+ AnalogOut da_;
+
+ // DAC の片方のチェンネルへ出力する
+ void WriteDac1(uint16_t val) { DAC->DHR12R1 = val; } // CH1 へ
+ void WriteDac2(uint16_t val) { DAC->DHR12R2 = val; } // CH2 へ
+
+ void WriteDac(uint16_t val) { (this->*fpWriteDac)(val); }
+
+ // 飽和処理を行い uint16_t 型のデータを戻り値とする
+ uint16_t ToUint16(float val)
+ { return __USAT((val + 1.0f)*2048.0f, BIT_WIDTH_); }
+
+ // コピー・コンストラクタ,代入演算子の禁止のため
+ DacF446(const DacF446&);
+ DacF446& operator=(const DacF446&);
+ };
+}
+#endif // F446_DAC_SINGLE_HPP
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FastSin.hpp Thu Sep 09 08:50:21 2021 +0000
@@ -0,0 +1,26 @@
+//-----------------------------------------------------------
+// FastSin() 関数
+// sin(πx/2) の値の計算
+//
+// 2020/06/01, Copyright (c) 2020 MIKAMI, Naoki
+//-----------------------------------------------------------
+
+#ifndef FASTSIN_POLYNOMIAL_HPP
+#define FASTSIN_POLYNOMIAL_HPP
+
+namespace Mikami
+{
+ // 引数の範囲: -2 <= x <= 2
+ inline float FastSin(float x)
+ {
+ static const float A1 = 1.570320019210f;
+ static const float A3 = -0.642113166941f;
+ static const float A5 = 0.071860854119f;
+
+ if (x > 1.0f) x = 2.0f - x;
+ if (x < -1.0f) x = -2.0f - x;
+ float x2 = x*x;
+ return ((A5*x2 + A3)*x2 + A1)*x;
+ }
+}
+#endif // FASTSIN_POLYNOMIAL_HPP
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IIR_Filter/Biquad.hpp Thu Sep 09 08:50:21 2021 +0000
@@ -0,0 +1,62 @@
+//--------------------------------------------------------------
+// 縦続形 IIR フィルタの構成要素として使う 2 次の IIR フィルタ
+// b0 は 1 と仮定している
+//
+// 2020/11/04, Copyright (c) 2020 MIKAMI, Naoki
+//--------------------------------------------------------------
+
+#include "mbed.h"
+
+#ifndef IIR_BIQUAD_HPP
+#define IIR_BIQUAD_HPP
+
+class Biquad
+{
+public:
+ // フィルタの係数をまとめて扱うための構造体
+ struct Coefs { float a1, a2, b1, b2; };
+
+ // デフォルト・コンストラクタ
+ // 係数は構造体 Ceofs で与える
+ Biquad(const Coefs ck = (Coefs){0, 0, 0, 0})
+ : a1_(ck.a1), a2_(ck.a2), b1_(ck.b1), b2_(ck.b2),
+ un1_(0), un2_(0) {}
+
+ // 係数を個別に与えるコンストラクタ
+ Biquad(float a1, float a2, float b1, float b2)
+ : a1_(a1), a2_(a2), b1_(b1), b2_(b2), un1_(0), un2_(0) {}
+
+ virtual ~Biquad() {}
+
+ // 2 次のフィルタを実行する
+ float Execute(float xn)
+ {
+ float un = xn + a1_*un1_ + a2_*un2_;
+ float yn = un + b1_*un1_ + b2_*un2_;
+
+ un2_ = un1_;
+ un1_ = un;
+
+ return yn;
+ }
+
+ // 係数を設定する
+ void SetCoefs(const Coefs ck)
+ {
+ a1_ = ck.a1;
+ a2_ = ck.a2;
+ b1_ = ck.b1;
+ b2_ = ck.b2;
+ }
+
+ // 内部変数(遅延器)のクリア
+ void Clear() { un1_ = un2_ = 0; }
+
+private:
+ float a1_, a2_, b1_, b2_; // フィルタの係数
+ float un1_, un2_; // 遅延器
+
+ // コピー・コンストラクタ禁止
+ Biquad(const Biquad&);
+};
+#endif // IIR_BIQUAD_HPP
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IIR_Filter/CoefficientsLp4.hpp Thu Sep 09 08:50:21 2021 +0000
@@ -0,0 +1,21 @@
+//----------------------------------------------------------------------
+// IIR フィルタの係数,縦続形,float 型
+//
+// 2020/10/17, Copyright (c) 2020 MIKAMI, Naoki
+//----------------------------------------------------------------------
+
+#include "Biquad.hpp"
+using namespace Mikami;
+
+// 低域通過フィルタ
+// 連立チェビシェフ特性
+// 次数 : 4 次
+// 標本化周波数:400.00 kHz
+// 遮断周波数 : 20.00 kHz
+// 通過域のリップル: 0.50 dB
+// 阻止域の減衰量 :40.00 dB
+const int ORDER_ = 4;
+const Biquad::Coefs hk_[] = {
+ { 1.712306E+00f, -7.512093E-01f, -9.111378E-01f, 1.0f},
+ { 1.819915E+00f, -9.194769E-01f, -1.719255E+00f, 1.0f}};
+const float G0_ = 1.196187E-02f; // 利得定数
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IIR_Filter/IirCascade.hpp Thu Sep 09 08:50:21 2021 +0000
@@ -0,0 +1,57 @@
+//---------------------------------------------------
+// 縦続形 IIR フィルタ
+//
+// 2020/11/04, Copyright (c) 2020 MIKAMI, Naoki
+//---------------------------------------------------
+
+#include "Biquad.hpp"
+#include "Array.hpp" // Array クラスが定義されている
+using namespace Mikami;
+
+#ifndef IIR_CASCADE_HPP
+#define IIR_CASCADE_HPP
+
+class IirCascade
+{
+public:
+ // コンストラクタ
+ IirCascade(int order, const Biquad::Coefs ck[], float g0)
+ : order_(order), hn_((order+1)/2)
+ { SetCoefs(order, ck, g0); }
+
+ // コンストラクタ
+ IirCascade(int order, const Biquad hk[], float g0)
+ : order_(order), hn_((order+1)/2, hk), g0_(g0) {}
+
+ virtual ~IirCascade() {}
+
+ // フィルタ処理を実行する
+ float Execute(float xn)
+ {
+ float yn = g0_*xn;
+ for (int k=0; k<(order_+1)/2; k++) yn = hn_[k].Execute(yn);
+ return yn;
+ }
+
+ // 係数の設定
+ void SetCoefs(int order, const Biquad::Coefs ck[], float g0)
+ {
+ if (order_ != order)
+ {
+ order_ = order;
+ hn_.SetSize((order+1)/2);
+ }
+ g0_ = g0;
+ for (int k=0; k<(order+1)/2; k++) hn_[k].SetCoefs(ck[k]);
+ }
+
+ // 内部変数(遅延器)のクリア
+ void Clear()
+ { for (int k=0; k<(order_+1)/2; k++) hn_[k].Clear(); }
+
+private:
+ int order_; // 次数
+ Array<Biquad> hn_; // Biquad クラスのオブジェクトの配列
+ float g0_; // 利得定数
+};
+#endif // IIR_CASCADE_HPP
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MSeq16.hpp Thu Sep 09 08:50:21 2021 +0000
@@ -0,0 +1,42 @@
+//---------------------------------------------------------
+// M 系列信号発生器(N = 16)
+//
+// 2021/08/23, Copyright (c) 2020 MIKAMI, Naoki
+//---------------------------------------------------------
+
+#include "mbed.h"
+
+#ifndef MSEQ16_HPP
+#define MSEQ16_HPP
+
+namespace Mikami
+{
+ class MSeq16
+ {
+ public:
+ MSeq16() : reg_(1) {}
+
+ // 戻り値: 1 => 1, 0 => -1
+ float Execute()
+ {
+ if ((reg_ & B_M_) == B_M_)
+ {
+ reg_ = ((reg_ ^ XOR_) << 1) | 1; // 1 の場合の処理
+ return 0.5f;
+ }
+ else
+ {
+ reg_ = reg_ << 1; // 0 の場合の処理
+ return -0.5f;
+ }
+ }
+ private:
+ static const uint16_t XOR_ = (1 << (2-1))
+ | (1 << (3-1))
+ | (1 << (5-1)); // XOR の位置に対応する定数
+ static const uint16_t B_M_ = 1 << (16-1); // 16 段目に相当するビットを調べる
+
+ uint16_t reg_;
+ };
+}
+#endif // MSEQ16_HPP
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyTicker7.lib Thu Sep 09 08:50:21 2021 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/MikamiUitOpen/code/MyTicker7/#f4269105fae0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialTxRxIntr.lib Thu Sep 09 08:50:21 2021 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/MikamiUitOpen/code/SerialTxRxIntr/#268977533f95
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp Thu Sep 09 08:50:21 2021 +0000
@@ -0,0 +1,140 @@
+//----------------------------------------------------------------------
+// ファンクション・ジェネレータ (Nucleo-F446RE 用)
+// COM ポートの自動検出に対応(9600 baud)
+//
+// 設定できる項目
+// 波形の種類: 正弦波,矩形波,合成矩形波(フーリエ級数の5倍波までの和)
+// 振幅: 0.00 ~ 1.00 倍
+// 周波数: 10 Hz ~ 10 kHz
+// ノイズ付加の有無
+// 標本化間隔:2.5 μs
+// 使用タイマ:TIM7
+// 信号出力のピン: A2
+//
+// PC 側のプログラム
+// CQ_FunctionGenerator
+//
+// 2021/09/05, Copyright (c) 2021 MIKAMI, Naoki
+//----------------------------------------------------------------------
+
+#include "F446_DAC.hpp" // DA 変換器用
+#include "SerialRxTxIntr.hpp" // シリアル通信用
+#include "MyTicker7.hpp" // タイマ用
+#include "FastSin.hpp" // 高速低精度 sin 関数
+#include "MSeq16.hpp" // ノイズ発生器で使う M 系列信号発生器
+#include "IirCascade.hpp" // ノイズ発生器で使う低域通過フィルタ
+#include "CoefficientsLp4.hpp" // 低域通過フィルタの係数
+#include <cctype> // isalpha() で使用
+using namespace Mikami;
+
+#ifndef __STM32F446xx_H
+#error "Use Nucleo-F446RE"
+#endif
+
+const float T0_ = 2.5f; // 出力の標本化間隔: 2.5 μs
+const float C0_ = 4.0f;
+const float C0_2_ = C0_/2.0f;
+const float C0T0_ = C0_*T0_*1.0e-6f;
+
+MyTicker7 timer_(T0_); // タイマ割り込み用クラスのオブジェクト,TIM7 を利用
+
+float phi_ = 0;
+float dPhi_ = C0T0_*1000; // 周波数決める変数,開始時は 1 kHz;
+float volume_ = 0.9f*0.5f; // 出力の振幅を決める変数,開始時は 0.45
+float volNoise_ = 0.5f; // ノイズの大きさを決める変数
+
+// DA 変換器に関する関数等
+DacF446 dac_; // DA 変換器オブジェクト
+void DacOut(float x) { dac_.Write(x); } // 引数の値を出力
+void DacZero(float x) { dac_.Write(0.0f); } // 0 を出力
+void (*fpDa)(float) = DacZero; // 起動時は 0 を出力
+
+// ノイズ付加に関する関数等
+MSeq16 mSeq_; // M 系列発生器
+IirCascade filter_(ORDER_, hk_, G0_); // 低域通過フィルタ
+float Noise() { return volNoise_*filter_.Execute(mSeq_.Execute()); }
+float NoiseFree() { return 0; }
+float (*fpN)() = NoiseFree; // 起動時はノイズなし
+
+// 発生する信号を定義する関数
+// 正弦波
+float Sin(float sinx) { return volume_*sinx + fpN(); }
+// 矩形波
+float Rect(float sinx)
+{
+ float x = (sinx >= 0) ? volume_ : -volume_;
+ return x + fpN();
+}
+// 矩形波(合成,5倍波まで)
+float Syn(float sinx)
+{
+ static const float ONE_3 = 1.0f/3.0f; // フーリエ合成で使用
+ static const float ONE_5 = 0.2f; // フーリエ合成で使用
+
+ float sinx2 = sinx*sinx;
+ float sin3x = (-4.0f*sinx2 + 3.0f)*sinx;
+ float sin5x = ((16.0f*sinx2 - 20.0f)*sinx2 + 5.0f)*sinx;
+
+ return volume_*(sinx + ONE_3*sin3x + ONE_5*sin5x) + fpN();
+}
+float (*fpS)(float) = Sin; // 起動時は正弦波
+
+// ラジオボタン,チェックボックスに対応する処理
+void Select(string str)
+{
+ if (str == "On") fpDa = DacOut; // 選択された信号の出力
+ if (str == "Off") fpDa = DacZero; // 0 を出力
+
+ if (str == "Sin") fpS = Sin; // 正弦波
+ if (str == "Rect") fpS = Rect; // 矩形波
+ if (str == "Syn") fpS = Syn; // 矩形波(5倍波まで)
+
+ if (str == "NsOn") fpN = Noise; // ノイズ付加
+ if (str == "NsOff") fpN = NoiseFree; // ノイズなし
+}
+
+// スライダ(TrackBar)に対応する処理
+void NumericCtrl(string str)
+{
+ char c1 = str[0]; // 先頭の文字を取得
+ float x = atof(str.substr(1).c_str());
+
+ if (c1 == '#') volume_ = x*0.9f; // 出力振幅の変更
+ if (c1 == '$') dPhi_ = C0T0_*x; // 周波数の変更
+ if (c1 == '%') volNoise_ = x; // ノイズの大きさの変更
+}
+
+// タイマ割り込みに対する割込みサービス・ルーチン
+void TimerIsr()
+{
+ float sinx = FastSin(phi_); // 基本波発生
+ fpDa(fpS(sinx)); // 指定された信号を出力
+
+ phi_ += dPhi_;
+ if (phi_ >= C0_2_) phi_ -= C0_; // オーバーフロー防止
+}
+
+int main()
+{
+ SerialRxTxIntr rxTx; // PC との通信用,9600 baud
+ // 以下の割り込み優先順位の設定を忘れないこと
+ NVIC_SetPriority(TIM7_IRQn, 0); // 最優先
+ NVIC_SetPriority(USART2_IRQn, 1); // USART2 割り込み:次に優先
+
+ timer_.Attach(&TimerIsr); // タイマ割り込み設定
+
+ while (true) // PC からの指令に対応する処理
+ {
+ if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理
+ {
+ string str = rxTx.GetBuffer();
+ if (str == "FG")
+ rxTx.TxString("ACK\n"); // PC からの "FG" に対して "ACK" を送信する
+ else
+ if (isalpha(str[0])) // 先頭が A ~ Z, a ~ z の場合
+ Select(str);
+ else // 先頭が A ~ Z, a ~ z 以外の場合
+ NumericCtrl(str);
+ }
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Thu Sep 09 08:50:21 2021 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/3a7713b1edbc \ No newline at end of file