STM32F446 の内蔵 ADC, DAC を 2 チャンネルで使うためのライブラリ.このライブラリを登録した際のプログラム: Demo_DSP_ADDA_Dual. Library for build-in ADC and DAC in STM32F446 using with dual channels.
Dependents: F446_DSP_Oscilloscope Demo_DSP_ADDA_Dual TrG_Oscilloscope
Diff: DSP_AdcDualBase.cpp
- Revision:
- 0:c02c700a8ecf
- Child:
- 1:e1c5baa559de
diff -r 000000000000 -r c02c700a8ecf DSP_AdcDualBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DSP_AdcDualBase.cpp Tue Sep 22 04:52:53 2020 +0000 @@ -0,0 +1,107 @@ +//---------------------------------------------------------- +// STM32F446 の ADC2, ADC3 を使って同時に AD 変換を開始し, +// アナログ信号を入力するための抽象クラス +// CH1 は ADC2 を使用 +// CH2 は ADC3 を使用 +// Read(), Write() の引数: +// 第一引数:CH1,第二引数:CH2 +// +// 2020/09/22, Copyright (c) 2020 MIKAMI, Naoki +//---------------------------------------------------------- + +#include "DSP_AdcDualBase.hpp" +#pragma diag_suppress 870 // マルチバイト文字使用の警告抑制のため + +namespace Mikami +{ + DspAdcDualBase::DspAdcDualBase(float fSampling, + PinName pinCh1, PinName pinCh2) + : adcCh1_(ADC2), adcCh2_(ADC3) + { + // pin に対応する ADC が存在するか確認 + MBED_ASSERT(PinmapMatch(pinCh1, adcCh1_)); + MBED_ASSERT(PinmapMatch(pinCh2, adcCh2_)); + + // ピンに対応する GPIOx_MODER をアナログ・モードに設定する + pin_function(pinCh1, STM_MODE_ANALOG); + pin_function(pinCh2, STM_MODE_ANALOG); + // pin_function() が定義されている pinmap.c が含まれるディレクトリ: + // mbed-dev\targets\TARGET_STM + + // ADC にクロックを供給する + __HAL_RCC_ADC2_CLK_ENABLE(); + __HAL_RCC_ADC3_CLK_ENABLE(); + // クロック供給用マクロの定義:stm32f4xx_hal_rcc_ex.h + + Initialize(adcCh1_, pinCh1); // ADC2 の初期設定 + Initialize(adcCh2_, pinCh2); // ADC3 の初期設定 + ADC->CCR = 0x0; // ADC 共通の設定, 念のため + + // AD 変換器の外部トリガに使うタイマ (TIM8) の設定 + SetTim8(fSampling); + } + + // AD 変換器の初期設定 + void DspAdcDualBase::Initialize(ADC_TypeDef* adc, PinName pin) + { + // 一つの ADC につき,1 チャンネルのみ使用の設定 + adc->SQR1 &= ~ADC_SQR1_L; + + // pin に対応するチャンネルを使うための設定 + adc->SQR3 = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_ADC)); + // pinmap_function() のヘッダファイル: mbed\hal\pinmap.h + // pinmap_function() が定義されているファイル: mbed-dev\hal\mbed_pinmap_common.c + // STM_PIN_CHANNEL() の定義:mbed\TARGET_NUCLEO_F446RE\TOOLCHAIN_ARM_STD\ + // PinNamesTypes.h + + // ADC の CR1 の設定 + adc->CR1 = 0x0; // 12bit, 非Scan モード,AD 変換終了割込みを禁止 + + // ADC の CR2 の設定 + adc->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING // 外部トリガの立ち上がりで開始される + | ADC_EXTERNALTRIGCONV_T8_TRGO // 外部トリガ: Timer8 TRGO event + | ADC_CR2_ADON; // ADC を有効にする + } + + // AD 変換器の外部トリガに使うタイマ (TIM8) の設定 + // fSampling 標本化周波数 [kHz] + void DspAdcDualBase::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 とする + + uint32_t psc = 0; + uint16_t mul = 1; + fSampling = fSampling*1000; // Hz 単位に変換 + uint32_t arr; + while (true) + { + arr = (uint32_t)(SystemCoreClock/(mul*fSampling) + 0.5f); + if (arr <= 65536) break; + psc++; + mul++; + if (psc > 65535) + { + fprintf(stderr, "%8.2f kHz : 標本化周波数が低すぎます.\r\n", + fSampling); + mbed_die(); // ボードの緑色 LED を点滅させる + } + } + TIM->ARR = arr - 1; // Auto-reload レジスタの設定 + TIM->PSC = psc; // Prescaler の設定 + TIM->CR1 = TIM_CR1_CEN; // TIM8 を有効にする + } + + // pin に対応する AD 変換器が存在することを確認する + // pin A0, PA_0 など + // adc ADC1 など + bool DspAdcDualBase::PinmapMatch(PinName pin, ADC_TypeDef* const adc) + { + for (int n=0; PinMap_ADC[n].pin != NC; n++) + if ( ((PinMap_ADC[n].pin & 0xFF) == pin) & + (PinMap_ADC[n].peripheral == (uint32_t)adc) ) return true; + return false; + } +} \ No newline at end of file