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

Dependencies:   Array_Matrix mbed SerialTxRxIntr UIT_FFT_Real

Files at this revision

API Documentation at this revision

Comitter:
MikamiUitOpen
Date:
Tue Jan 28 01:27:07 2020 +0000
Parent:
1:a90b573b335a
Child:
3:687ae0dd092f
Commit message:
3

Changed in this revision

ADDA_BasePolling/F446_ADC_Intr.cpp Show diff for this revision Revisions of this file
ADDA_BasePolling/F446_ADC_Intr.hpp Show diff for this revision Revisions of this file
ADDA_BasePolling/F446_ADC_Polling.cpp Show diff for this revision Revisions of this file
ADDA_BasePolling/F446_ADC_Polling.hpp Show diff for this revision Revisions of this file
ADDA_BasePolling/F446_DAC.hpp Show diff for this revision Revisions of this file
F446_ADDA/F446_AdcBase.cpp Show annotated file Show diff for this revision Revisions of this file
F446_ADDA/F446_AdcBase.hpp Show annotated file Show diff for this revision Revisions of this file
F446_ADDA/F446_AdcIntr.hpp Show annotated file Show diff for this revision Revisions of this file
F446_ADDA/F446_AdcPolling.hpp Show annotated file Show diff for this revision Revisions of this file
F446_ADDA/F446_Dac.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
--- a/ADDA_BasePolling/F446_ADC_Intr.cpp	Fri Jan 17 02:04:09 2020 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,22 +0,0 @@
-//-------------------------------------------------------------
-//  F446 内蔵 ADC2 を割込み方式で使うための派生クラス
-//      基底クラス: AdcF446_Polling
-//
-//  2020/01/12, Copyright (c) 2020 MIKAMI, Naoki
-//-------------------------------------------------------------
-
-#include "F446_ADC_Intr.hpp"
-
-namespace Mikami
-{
-    // 割込みベクタの設定と AD 変換割込みを有効にする
-    void AdcF446_Intr::SetIntrVec(void (*Func)())
-    {
-        fp = Func;          // 引数として渡された処理を割り当てる
-        NVIC_SetVector(ADC_IRQn, (uint32_t)Isr);    // "core_cm4.h" 参照
-        NVIC_EnableIRQ(ADC_IRQn);                   // "core_cm4.h" 参照
-    }    
-
-    // static メンバの実体
-    void (*AdcF446_Intr::fp)();
-}
--- a/ADDA_BasePolling/F446_ADC_Intr.hpp	Fri Jan 17 02:04:09 2020 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-//-------------------------------------------------------------
-//  F446 内蔵 ADC2 を割込み方式で使うための派生クラス(ヘッダ)
-//      基底クラス: AdcF446_Polling
-//
-//  2020/01/12, Copyright (c) 2020 MIKAMI, Naoki
-//-------------------------------------------------------------
-
-#include "F446_ADC_Polling.hpp"
-
-#ifndef ADC_F446_INTERRUPT_HPP
-#define ADC_F446_INTERRUPT_HPP
-
-namespace Mikami
-{
-    class AdcF446_Intr : public AdcF446_Polling
-    {
-    public:
-        // コンストラクタ
-        //      fSampling 標本化周波数 [kHz]
-        //      pin     入力ピンの名前
-        AdcF446_Intr(float fSampling, PinName pin)
-            : AdcF446_Polling(fSampling, pin)
-        {   myAdc_->CR1 |= ADC_CR1_EOCIE; }     // AD 変換終了割り込みを許可
-
-        virtual ~AdcF446_Intr() {}
-
-        // 割込みベクタの設定と AD 変換割込みを有効にする
-        void SetIntrVec(void (*Func)());
-
-        // AD 変換された値を読み込む
-        //      -1.0f <= AD変換された値 < 1.0f
-        virtual float Read() const { return ToFloat(myAdc_->DR); }
-
-    private:
-        static void (*fp)();    // 割込みサービス・ルーチンの中で実行される関数のポインタ
-
-        // 割込みサービス・ルーチン,このクラスで使っている ADC であることを確認
-        static void Isr()
-        {   if ((myAdc_->SR & ADC_SR_EOC_Msk) == ADC_SR_EOC) fp(); }
-    };
-}
-#endif  // ADC_F446_INTERRUPT_HPP
--- a/ADDA_BasePolling/F446_ADC_Polling.cpp	Fri Jan 17 02:04:09 2020 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,89 +0,0 @@
-//-------------------------------------------------------------
-//  F446 内蔵 ADC2 のためのポーリング方式のクラス
-//
-//  2020/01/12, Copyright (c) 2020 MIKAMI, Naoki
-//-------------------------------------------------------------
-
-#include "F446_ADC_Polling.hpp"
-#include "PeripheralPins.h" // PinMap_ADC を使う場合に必要
-#pragma diag_suppress 870   // マルチバイト文字使用の警告抑制のため
-// PeripheralPins.c は以下よりたどって行けば取得可能
-// https://gitlab.exmachina.fr/fw-libs/mbed-os/tree/5.8.1
-
-namespace Mikami
-{
-    // コンストラクタ
-    AdcF446_Polling::AdcF446_Polling(float fSampling, PinName pin)
-    {
-        SetGPIO(pin);                   // GPIO の設定
-
-        __HAL_RCC_ADC2_CLK_ENABLE();    // ADC2 にクロックを供給する
-        // __HAL_RCC_ADC2_CLK_ENABLE() の定義:stm32f4xx_hal_rcc_ex.h
-
-        // pin に対応するチャンネルを使うための設定
-        myAdc_->SQR3 = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_ADC));
-        // pinmap_function() のヘッダファイル: mbed\hal\pinmap.h
-        // STM_PIN_CHANNEL() の定義:PinNamesTypes.h
-
-        // ADC の CR1 の設定
-        myAdc_->CR1 = 0x0;      // AD 変換終了割り込みを禁止
-        // ADC の CR2 の設定
-        myAdc_->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING   // 外部トリガの立ち上がりで開始される
-                    | ADC_EXTERNALTRIGCONV_T8_TRGO      // 外部トリガ: Timer8 TRGO event
-                    | ADC_CR2_ADON;                     // ADC を有効にする
-
-        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
-        SetTim8(fSampling);
-    }
-
-    // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
-    //      fSampling 標本化周波数 [kHz]
-    void AdcF446_Polling::SetTim8(float fSampling)
-    {
-        __HAL_RCC_TIM8_CLK_ENABLE();    // クロック供給. "stm32f4xx_hal_rcc.h" 参照
-        TIM_TypeDef* const TIM = TIM8;
-
-        TIM->CR2 = TIM_TRGO_UPDATE;     // Update event を TRGO (trigger output) とする
-
-        float arrF = (SystemCoreClock/fSampling)/1000.0f;
-        if (arrF >65535)
-        {
-            fprintf(stderr, "%8.2f kHz : 標本化周波数が低すぎます.\r\n", fSampling);
-            while (true) {}
-        }
-        TIM->ARR = floor(arrF + 0.5f) - 1;  // Auto-reload レジスタの設定
-        TIM->PSC = 0;                   // Prescaler の設定
-        TIM->CR1 = TIM_CR1_CEN;         // TIM8 を有効にする
-    }
-
-    // AD 変換器に関係のある GPIO の設定
-    void AdcF446_Polling::SetGPIO(PinName pin)
-    {
-        // 各シンボルは stm32f4xx_hal_gpio.h で定義されている
-        // MODIFY_REG() マクロは stm32f4xx.h で定義されている
-        uint32_t nShift = STM_PIN(pin) << 1;
-        uint32_t moder = GPIO_MODE_ANALOG << nShift;
-        uint32_t mask = 0x03 << nShift;
-        switch (STM_PORT(pin))
-        {
-            case 0:
-                if (__HAL_RCC_GPIOA_IS_CLK_DISABLED())
-                    __HAL_RCC_GPIOA_CLK_ENABLE();       // GPIOA にクロックを供給
-                MODIFY_REG(GPIOA->MODER, mask, moder);  // GPIOA のピンを設定
-                break;
-            case 1:
-                if (__HAL_RCC_GPIOB_IS_CLK_DISABLED())
-                    __HAL_RCC_GPIOB_CLK_ENABLE();       // GPIOB にクロックを供給
-                MODIFY_REG(GPIOB->MODER, mask, moder);  // GPIOB のピンを設定
-                break;
-            case 2:
-                if (__HAL_RCC_GPIOC_IS_CLK_DISABLED())
-                    __HAL_RCC_GPIOC_CLK_ENABLE();       // GPIOC にクロックを供給
-                MODIFY_REG(GPIOC->MODER, mask, moder);  // GPIOC のピンを設定
-                break;
-        }
-    }
-
-    // static メンバの実体
-    ADC_TypeDef* const AdcF446_Polling::myAdc_ = ADC2;
-}
--- a/ADDA_BasePolling/F446_ADC_Polling.hpp	Fri Jan 17 02:04:09 2020 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-//-------------------------------------------------------------
-//  F446 内蔵 ADC2 のためのポーリング方式のクラス(ヘッダ)
-//
-//  2020/01/12, Copyright (c) 2020 MIKAMI, Naoki
-//-------------------------------------------------------------
-
-#include "mbed.h"
-
-#ifndef ADC_F446_POLLING_HPP
-#define ADC_F446_POLLING_HPP
-
-namespace Mikami
-{
-    class AdcF446_Polling
-    {
-    public:
-        // コンストラクタ
-        //      fSampling 標本化周波数 [kHz]
-        //      pin     入力ピンの名前
-        AdcF446_Polling(float fSampling, PinName pin);
-
-        virtual ~AdcF446_Polling() {}
-
-        // AD 変換された値を読み込む
-        //      -1.0f <= AD変換された値 < 1.0f
-        virtual float Read() const
-        {
-            while ((myAdc_->SR & ADC_SR_EOC) != ADC_SR_EOC) {}
-            return ToFloat(myAdc_->DR);
-        }
-
-    protected:
-////        ADC_TypeDef* const myAdc_;  // AD 変換器に対応するポインタ
-            static ADC_TypeDef* const myAdc_;   // AD 変換器に対応するポインタ
-
-        float ToFloat(uint16_t x) const { return AMP_*(x - 2048); }
-
-    private:
-        static const float AMP_ = 1.0f/2048.0f;
-        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
-        //      fSampling 標本化周波数 [kHz]
-        void SetTim8(float fSampling);
-        
-        // AD 変換器に関係のある GPIO の設定
-        void SetGPIO(PinName pin);
-
-        // コピー・コンストラクタ禁止のため
-        AdcF446_Polling(const AdcF446_Polling&);
-        // 代入演算子禁止のため
-        AdcF446_Polling& operator=(const AdcF446_Polling&);
-    };
-}
-#endif  // ADC_F446_POLLING2_HPP
--- a/ADDA_BasePolling/F446_DAC.hpp	Fri Jan 17 02:04:09 2020 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-//--------------------------------------------------------
-//  STM32F446 内蔵の DAC 用のクラス
-//      出力端子:   A2  (PA_4)
-//
-//  2020/01/12, Copyright (c) 2020 MIKAMI, Naoki
-//--------------------------------------------------------
-#include "mbed.h"
-
-#ifndef DAC_F446_SINGLE_HPP
-#define DAC_F446_SINGLE_HPP
-
-namespace Mikami
-{
-    class DacF446
-    {
-    public:
-        // コンストラクタ, A2 に接続される CH1 のみを有効にする
-        DacF446() : da_(A2) { DAC->CR = DAC_CR_EN1; }
-
-        virtual ~DacF446() {}
-
-        // -1.0f <= data <= 1.0f
-        void Write(float data) { WriteDacCh1(ToUint16(data)); }
-
-        // 0 <= data <= 4095
-        void Write(uint16_t data) { WriteDacCh1(__USAT(data, BIT_WIDTH_)); }
-
-    private:
-        static const int BIT_WIDTH_ = 12;
-        AnalogOut da_;
-
-        // DAC の CH1 へ右詰めで出力する
-        void WriteDacCh1(uint16_t val) { DAC->DHR12R1 = 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  // DAC_F446_SINGLE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F446_ADDA/F446_AdcBase.cpp	Tue Jan 28 01:27:07 2020 +0000
@@ -0,0 +1,91 @@
+//-------------------------------------------------------------
+//  F446 内蔵 ADC2 のための抽象基底クラス
+//
+//  2020/01/28, Copyright (c) 2020 MIKAMI, Naoki
+//-------------------------------------------------------------
+
+#include "F446_AdcBase.hpp"
+#include "PeripheralPins.h" // PinMap_ADC を使う場合に必要
+#pragma diag_suppress 870   // マルチバイト文字使用の警告抑制のため
+// PeripheralPins.c は以下よりたどって行けば取得可能
+// https://gitlab.exmachina.fr/fw-libs/mbed-os/tree/5.8.1
+
+namespace Mikami
+{
+    // コンストラクタ
+    AdcF446_Base::AdcF446_Base(float fSampling, PinName pin)
+    {
+        SetGPIO(pin);                   // GPIO の設定
+
+        __HAL_RCC_ADC2_CLK_ENABLE();    // ADC2 にクロックを供給する
+        // __HAL_RCC_ADC2_CLK_ENABLE() の定義:stm32f4xx_hal_rcc_ex.h
+
+        // 1 チャンネルのみ使用の設定
+        myAdc_->SQR1 &= ~ADC_SQR1_L;
+        // pin に対応するチャンネルを使うための設定
+        myAdc_->SQR3 = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_ADC));
+        // pinmap_function() のヘッダファイル: mbed\hal\pinmap.h
+        // STM_PIN_CHANNEL() の定義:PinNamesTypes.h
+
+        // ADC の CR1 の設定
+        myAdc_->CR1 = 0x0;  // 12bit, 非Scan モード,AD 変換終了割込みを禁止
+        // ADC の CR2 の設定
+        myAdc_->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING   // 外部トリガの立ち上がりで開始される
+                    | ADC_EXTERNALTRIGCONV_T8_TRGO      // 外部トリガ: Timer8 TRGO event
+                    | ADC_CR2_ADON;                     // ADC を有効にする
+
+        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
+        SetTim8(fSampling);
+    }
+
+    // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
+    //      fSampling 標本化周波数 [kHz]
+    void AdcF446_Base::SetTim8(float fSampling)
+    {
+        __HAL_RCC_TIM8_CLK_ENABLE();    // クロック供給. "stm32f4xx_hal_rcc.h" 参照
+        TIM_TypeDef* const TIM = TIM8;
+
+        TIM->CR2 = TIM_TRGO_UPDATE;     // Update event を TRGO (trigger output) とする
+
+        float arrF = (SystemCoreClock/fSampling)/1000.0f;
+        if (arrF >65535)
+        {
+            fprintf(stderr, "%8.2f kHz : 標本化周波数が低すぎます.\r\n", fSampling);
+            while (true) {}
+        }
+        TIM->ARR = floor(arrF + 0.5f) - 1;  // Auto-reload レジスタの設定
+        TIM->PSC = 0;                   // Prescaler の設定
+        TIM->CR1 = TIM_CR1_CEN;         // TIM8 を有効にする
+    }
+
+    // AD 変換器に関係のある GPIO の設定
+    void AdcF446_Base::SetGPIO(PinName pin)
+    {
+        // 各シンボルは stm32f4xx_hal_gpio.h で定義されている
+        // MODIFY_REG() マクロは stm32f4xx.h で定義されている
+        uint32_t nShift = STM_PIN(pin) << 1;
+        uint32_t moder = GPIO_MODE_ANALOG << nShift;
+        uint32_t mask = 0x03 << nShift;
+        switch (STM_PORT(pin))
+        {
+            case 0:
+                if (__HAL_RCC_GPIOA_IS_CLK_DISABLED())
+                    __HAL_RCC_GPIOA_CLK_ENABLE();       // GPIOA にクロックを供給
+                MODIFY_REG(GPIOA->MODER, mask, moder);  // GPIOA のピンを設定
+                break;
+            case 1:
+                if (__HAL_RCC_GPIOB_IS_CLK_DISABLED())
+                    __HAL_RCC_GPIOB_CLK_ENABLE();       // GPIOB にクロックを供給
+                MODIFY_REG(GPIOB->MODER, mask, moder);  // GPIOB のピンを設定
+                break;
+            case 2:
+                if (__HAL_RCC_GPIOC_IS_CLK_DISABLED())
+                    __HAL_RCC_GPIOC_CLK_ENABLE();       // GPIOC にクロックを供給
+                MODIFY_REG(GPIOC->MODER, mask, moder);  // GPIOC のピンを設定
+                break;
+        }
+    }
+
+    // static メンバの実体
+    ADC_TypeDef* const AdcF446_Base::myAdc_ = ADC2;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F446_ADDA/F446_AdcBase.hpp	Tue Jan 28 01:27:07 2020 +0000
@@ -0,0 +1,46 @@
+//-------------------------------------------------------------
+//  F446 内蔵 ADC2 のための抽象基底クラス(ヘッダ)
+//
+//  2020/01/28 Copyright (c) 2020 MIKAMI, Naoki
+//-------------------------------------------------------------
+
+#include "mbed.h"
+
+#ifndef ADC_F446_BASE_HPP
+#define ADC_F446_BASE_HPP
+
+namespace Mikami
+{
+    class AdcF446_Base
+    {
+    public:
+        // コンストラクタ
+        //      fSampling 標本化周波数 [kHz]
+        //      pin     入力ピンの名前
+        AdcF446_Base(float fSampling, PinName pin);
+
+        virtual ~AdcF446_Base() {}
+
+        // AD 変換された値を読み込む
+        //      -1.0f <= AD変換された値 < 1.0f
+        virtual float Read() const = 0; // 純粋仮想関数
+
+    protected:
+        static ADC_TypeDef* const myAdc_;   // AD 変換器に対応するポインタ
+        float ToFloat(uint16_t x) const { return AMP_*(x - 2048); }
+    
+    private:
+        static const float AMP_ = 1.0f/2048.0f;
+        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
+        //      fSampling 標本化周波数 [kHz]
+        void SetTim8(float fSampling);
+        
+        // AD 変換器に関係のある GPIO の設定
+        void SetGPIO(PinName pin);
+
+        // コピー・コンストラクタ,代入演算子の禁止のため
+        AdcF446_Base(const AdcF446_Base&);
+        AdcF446_Base& operator=(const AdcF446_Base&);
+    };
+}
+#endif  // ADC_F446_BASE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F446_ADDA/F446_AdcIntr.hpp	Tue Jan 28 01:27:07 2020 +0000
@@ -0,0 +1,50 @@
+//-------------------------------------------------------------
+//  F446 内蔵 ADC2 を割込み方式で使うための派生クラス(ヘッダ)
+//      基底クラス: AdcF446_Base
+//
+//  2020/01/28, Copyright (c) 2020 MIKAMI, Naoki
+//-------------------------------------------------------------
+
+#include "F446_AdcBase.hpp"
+
+#ifndef ADC_F446_INTERRUPT_HPP
+#define ADC_F446_INTERRUPT_HPP
+
+namespace Mikami
+{
+    class AdcF446_Intr : public AdcF446_Base
+    {
+    public:
+        // コンストラクタ
+        //      fSampling 標本化周波数 [kHz]
+        //      pin     入力ピンの名前
+        AdcF446_Intr(float fSampling, PinName pin)
+            : AdcF446_Base(fSampling, pin)
+        {   myAdc_->CR1 |= ADC_CR1_EOCIE; }     // AD 変換終了割り込みを許可
+
+        virtual ~AdcF446_Intr() {}
+
+        // 割込みベクタの設定と AD 変換割込みを有効にする
+        void SetIntrVec(void (*Func)())
+        {
+            fp = Func;          // 引数として渡された処理を割り当てる
+            NVIC_SetVector(ADC_IRQn, (uint32_t)Isr);    // "core_cm4.h" 参照
+            NVIC_EnableIRQ(ADC_IRQn);                   // "core_cm4.h" 参照
+        }    
+
+        // AD 変換された値を読み込む
+        //      -1.0f <= AD変換された値 < 1.0f
+        virtual float Read() const { return ToFloat(myAdc_->DR); }
+
+    private:
+        static void (*fp)();    // 割込みサービス・ルーチンの中で実行される関数のポインタ
+
+        // 割込みサービス・ルーチン,このクラスで使っている ADC であることを確認
+        static void Isr()
+        {   if ((myAdc_->SR & ADC_SR_EOC_Msk) == ADC_SR_EOC) fp(); }
+    };
+
+    // static メンバの実体
+    void (*AdcF446_Intr::fp)();
+}
+#endif  // ADC_F446_INTERRUPT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F446_ADDA/F446_AdcPolling.hpp	Tue Jan 28 01:27:07 2020 +0000
@@ -0,0 +1,35 @@
+//-------------------------------------------------------------
+//  F446 内蔵 ADC2 をポーリング方式で使うための派生クラス(ヘッダ)
+//      基底クラス: AdcF446_Base
+//
+//  2020/01/28, Copyright (c) 2020 MIKAMI, Naoki
+//-------------------------------------------------------------
+
+#include "F446_AdcBase.hpp"
+
+#ifndef ADC_F446_POLLING_HPP
+#define ADC_F446_POLLING_HPP
+
+namespace Mikami
+{
+    class AdcF446_Polling : public AdcF446_Base
+    {
+    public:
+        // コンストラクタ
+        //      fSampling 標本化周波数 [kHz]
+        //      pin     入力ピンの名前
+        AdcF446_Polling(float fSampling, PinName pin)
+            : AdcF446_Base(fSampling, pin) {}
+
+        virtual ~AdcF446_Polling() {}
+
+        // AD 変換された値を読み込む
+        //      -1.0f <= AD変換された値 < 1.0f
+        virtual float Read() const
+        {
+            while ((myAdc_->SR & ADC_SR_EOC) != ADC_SR_EOC) {}
+            return ToFloat(myAdc_->DR);
+        }
+    };
+}
+#endif  // ADC_F446_POLLING_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/F446_ADDA/F446_Dac.hpp	Tue Jan 28 01:27:07 2020 +0000
@@ -0,0 +1,45 @@
+//--------------------------------------------------------
+//  STM32F446 内蔵の DAC 用のクラス
+//      出力端子:   A2  (PA_4)
+//
+//  2020/01/28, Copyright (c) 2020 MIKAMI, Naoki
+//--------------------------------------------------------
+#include "mbed.h"
+
+#ifndef DAC_F446_SINGLE_HPP
+#define DAC_F446_SINGLE_HPP
+
+namespace Mikami
+{
+    class DacF446
+    {
+    public:
+        // コンストラクタ, A2 に接続される CH1 のみを有効にする
+        DacF446() : da_(A2) { DAC->CR = DAC_CR_EN1; }
+
+        virtual ~DacF446() {}
+
+        // -1.0f <= data <= 1.0f
+        void Write(float data) { WriteDacCh1(ToUint16(data)); }
+
+        // 0 <= data <= 4095
+        void Write(uint16_t data) { WriteDacCh1(__USAT(data, BIT_WIDTH_)); }
+
+    private:
+        static const int BIT_WIDTH_ = 12;
+        AnalogOut da_;
+
+        // DAC の CH1 へ右詰めで出力する
+        void WriteDacCh1(uint16_t val) { DAC->DHR12R1 = 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  // DAC_F446_SINGLE_HPP
--- a/main.cpp	Fri Jan 17 02:04:09 2020 +0000
+++ b/main.cpp	Tue Jan 28 01:27:07 2020 +0000
@@ -15,14 +15,14 @@
 //
 //  PC 側のプログラムのフォルダ:プログラム\PC\F446_FFT_Analyzer
 //
-//  2020/01/13, Copyright (c) 2020 MIKAMI, Naoki
+//  2020/01/28, Copyright (c) 2020 MIKAMI, Naoki
 //---------------------------------------------------------------------
 
 #include "mbed.h"
 #include <string>
 #include "Array.hpp"
-#include "F446_ADC_Intr.hpp"
-#include "F446_DAC.hpp"
+#include "F446_AdcIntr.hpp"
+#include "F446_Dac.hpp"
 #include "FFT_Analyzer.hpp"
 #include "DoubleBuffer.hpp"
 #include "Coefs_IIR6_LP_8k_Biquad.hpp"  // 縦続形 IIR フィルタの係数