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

Dependencies:   Array_Matrix mbed SerialTxRxIntr DSP_ADDA_Dual

Files at this revision

API Documentation at this revision

Comitter:
MikamiUitOpen
Date:
Thu Sep 09 08:47:03 2021 +0000
Commit message:
1

Changed in this revision

Array_Matrix.lib Show annotated file Show diff for this revision Revisions of this file
DSP_ADDA_Dual.lib Show annotated file Show diff for this revision Revisions of this file
InputBuffer.hpp Show annotated file Show diff for this revision Revisions of this file
SerialTxRxIntr.lib Show annotated file Show diff for this revision Revisions of this file
XferBase.hpp Show annotated file Show diff for this revision Revisions of this file
XferWaveform.hpp Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Array_Matrix.lib	Thu Sep 09 08:47:03 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/DSP_ADDA_Dual.lib	Thu Sep 09 08:47:03 2021 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/MikamiUitOpen/code/DSP_ADDA_Dual/#a3148d75c1ea
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/InputBuffer.hpp	Thu Sep 09 08:47:03 2021 +0000
@@ -0,0 +1,58 @@
+//--------------------------------------------------------
+//  バッファの template クラス
+//
+//  2021/07/19, Copyright (c) 2021 MIKAMI, Naoki
+//-------------------------------------------------------
+
+#ifndef INPUT_BUFFER_HPP
+#define INPUT_BUFFER_HPP
+
+#include "Array.hpp"
+using namespace Mikami;
+
+class InputBuffer
+{
+public:
+    // コンストラクタ
+    explicit InputBuffer(int size, float initValue = 0)
+        : N_(size), buf_(2*size, initValue), index_(0), full_(false) {}
+    
+    // データを格納
+    void Store(float data1, float data2)
+    {
+        buf_[index_] = data1;
+        buf_[N_+index_++] = data2;
+    }
+    
+    // バッファからデータの取り出し
+    Array<float> Get() const { return buf_; }
+
+    // バッファが満杯で次の準備を行う
+    bool IsFullNext()
+    {
+        if (index_ < N_) return false;
+
+        index_ = 0;
+        full_ = true;
+        return true;
+    }
+
+    // バッファが満杯で,true を返す
+    bool IsFull()
+    {
+        bool temp = full_;
+        if (full_) full_ = false;
+        return temp;
+    }
+
+private:
+    const int N_;       // バッファのサイズに対応する値
+    Array<float> buf_;  // バッファ
+    int index_;         // 入力データのカウンタ
+    bool full_;         // 満杯の場合 true
+
+    // コピー・コンストラクタおよび代入演算子の禁止のため
+    InputBuffer(const InputBuffer&);
+    InputBuffer& operator=(const InputBuffer&);
+};
+#endif  // INPUT_BUFFER_HPP
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialTxRxIntr.lib	Thu Sep 09 08:47:03 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/XferBase.hpp	Thu Sep 09 08:47:03 2021 +0000
@@ -0,0 +1,49 @@
+//---------------------------------------------------------------------
+//  データを PC へ転送するための抽象基底クラス
+//
+//  2021/07/11, Copyright (c) 2021 MIKAMI, Naoki
+//---------------------------------------------------------------------
+
+#include <string>
+#include "SerialRxTxIntr.hpp"
+using namespace Mikami;
+
+#ifndef XFER_ABSTRACT_BASE_HPP
+#define XFER_ABSTRACT_BASE_HPP
+
+class XferBase
+{
+public:
+    // コンストラクタ
+    XferBase(SerialRxTxIntr& rxTx, int size)
+        : SIZE_(size), xn_(size), rxTx_(rxTx) {}
+
+    // データを PC へ転送(0 ~ 10,000 の範囲の値を 2 文字で表すコード化を利用)
+    void ToPC(const float data[])
+    {
+        Convert(data);
+        string str = "";
+        for (int n=0; n<SIZE_; n++)
+        {
+            str += ((xn_[n] >> 7) & 0x7F) + 0x10;
+            str += (xn_[n] & 0x7F) + 0x10;
+        }
+        rxTx_.TxString(str+"\n");
+    }
+
+protected:
+    const int SIZE_;        // PC に送るデータの数
+    Array<uint16_t> xn_;    // PC に送るデータ
+
+private:
+    SerialRxTxIntr& rxTx_;
+
+    // データを転送する際の形式に変換
+    //      data    元のデータ
+    virtual void Convert(const float data[]) = 0;
+
+    // コピー・コンストラクタおよび代入演算子の禁止のため
+    XferBase(const XferBase&);
+    XferBase& operator=(const XferBase&);
+};
+#endif  // XFER_ABSTRACT_BASE_HPP
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/XferWaveform.hpp	Thu Sep 09 08:47:03 2021 +0000
@@ -0,0 +1,39 @@
+//---------------------------------------------------------------------
+//  波形データを PC へ転送するための XferBase の派生クラス
+//
+//  2021/07/11, Copyright (c) 2021 MIKAMI, Naoki
+//---------------------------------------------------------------------
+
+#include "XferBase.hpp"
+
+#ifndef XFER_WAVEFORM_DERIVED_HPP
+#define XFER_WAVEFORM_DERIVED_HPP
+
+class XferWaveform : public XferBase
+{
+public:
+    // コンストラクタ
+    XferWaveform(SerialRxTxIntr& rxTx, int size)
+        : XferBase(rxTx, size) {}
+
+private:
+    // 転送すべきデータを転送する形式に変換
+    //      -1 <= xIn[] <= 1
+    //      対応関係:1 => 10000, -1 => 0
+    virtual void Convert(const float xIn[])
+    {
+        static const float FACTOR = 5000.0f;
+        for (int n=0; n<SIZE_; n++)
+        {
+            float x = FACTOR*(xIn[n] + 1.0f);
+            if (x > 10000) x = 10000;
+            if (x < 0) x = 0;
+            xn_[n] = (uint16_t)x;
+        }
+    }
+
+    // コピー・コンストラクタおよび代入演算子の禁止のため
+    XferWaveform(const XferWaveform&);
+    XferWaveform& operator=(const XferWaveform&);
+};
+#endif  // XFER_WAVEFORM_DERIVED_HPP
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Sep 09 08:47:03 2021 +0000
@@ -0,0 +1,64 @@
+//---------------------------------------------------------------------
+//  オシロスコープ (Nucleo-F446RE 用)
+//      ● 入力  A0: チャンネル1,A1 チャンネル2
+//
+//  2021/07/19, Copyright (c) 2021 MIKAMI, Naoki
+//---------------------------------------------------------------------
+
+#include <string>
+#include "DSP_AdcDualIntr.hpp"
+#include "InputBuffer.hpp"
+#include "XferWaveform.hpp"
+using namespace Mikami;
+
+#ifndef __STM32F446xx_H
+#error "Use Nucleo-F446RE"
+#endif
+
+const int N_FRAME_ = 1000;  // 1フレーム当たり標本化するデータ数
+
+DspAdcDualIntr myAdc_(100, A0, A1);
+InputBuffer buf_(N_FRAME_); // AD の結果を保存するバッファ
+
+// ADC 変換終了割り込みに対する割り込みサービス・ルーチン
+void AdcIsr()
+{
+    float sn1, sn2;
+    myAdc_.Read(sn1, sn2);
+    buf_.Store(sn1, sn2);       // バッファへ格納
+    if (buf_.IsFullNext())      // バッファが満杯になったら ADC 割り込みを禁止する
+        myAdc_.DisableIntr();
+}
+
+int main()
+{
+    SerialRxTxIntr rxTx;                // PC との通信用,最初は 9600 baud
+    XferWaveform tx(rxTx, 2*N_FRAME_);  // PC に転送するためのオブジェクトの生成
+
+    myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て
+    myAdc_.DisableIntr();
+    while (true)
+    {
+        // PC からのコマンドの解析
+        if (rxTx.IsEol())       // 受信バッファのデータが有効になった場合の処理
+        {
+            string str = rxTx.GetBuffer();
+            if (str == "Oscilloscope")
+            {
+                rxTx.TxString("ACK\n"); // PC からの "Oscilloscope" 受信に対して"ACK" を送信
+                wait_ms(10);
+                rxTx.Baud(460800);      // 以降は 460,800 baud
+            }
+            else if (str.substr(0, 2) == "GO")
+            {
+                // str の [2..5] の内容:標本化周波数
+                int fs = atoi(str.substr(2, 4).c_str());    // 標本化周波数
+                myAdc_.SetFs(fs);       // 標本化周波数再設定
+                myAdc_.EnableIntr();    // ADC 割り込みを有効にする
+            }
+        }
+
+        if (buf_.IsFull())
+            tx.ToPC(buf_.Get());    // データを PC へ転送
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Sep 09 08:47:03 2021 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400
\ No newline at end of file