不韋 呂 / DSP_ADDA_Dual

Dependents:   F446_DSP_Oscilloscope Demo_DSP_ADDA_Dual TrG_Oscilloscope

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DSP_AdcDualBase.cpp Source File

DSP_AdcDualBase.cpp

00001 //----------------------------------------------------------
00002 //  STM32F446 の ADC2, ADC3 を使って同時に AD 変換を開始し,
00003 //  アナログ信号を入力するための抽象クラス
00004 //      CH1 は ADC2 を使用
00005 //      CH2 は ADC3 を使用
00006 //  Read(), Write() の引数:
00007 //      第一引数:CH1,第二引数:CH2
00008 //
00009 //  2020/11/07, Copyright (c) 2020 MIKAMI, Naoki
00010 //----------------------------------------------------------
00011 
00012 #include "DSP_AdcDualBase.hpp"
00013 #pragma diag_suppress 870   // マルチバイト文字使用の警告抑制のため
00014 
00015 namespace Mikami
00016 {
00017     DspAdcDualBase::DspAdcDualBase(float fSampling,
00018                                    PinName pinCh1, PinName pinCh2)
00019         : adcCh1_(ADC2), adcCh2_(ADC3)
00020     {
00021         // pin に対応する ADC が存在するか確認
00022         MBED_ASSERT(PinmapMatch(pinCh1, adcCh1_));
00023         MBED_ASSERT(PinmapMatch(pinCh2, adcCh2_));
00024 
00025         // ピンに対応する GPIOx_MODER をアナログ・モードに設定する
00026         pin_function(pinCh1, STM_MODE_ANALOG);
00027         pin_function(pinCh2, STM_MODE_ANALOG);
00028         // pin_function() が定義されている pinmap.c が含まれるディレクトリ:
00029         // mbed-dev\targets\TARGET_STM
00030 
00031         // ADC にクロックを供給する
00032         __HAL_RCC_ADC2_CLK_ENABLE();
00033         __HAL_RCC_ADC3_CLK_ENABLE();
00034         // クロック供給用マクロの定義:stm32f4xx_hal_rcc_ex.h
00035 
00036         Initialize(adcCh1_, pinCh1);    // ADC2 の初期設定
00037         Initialize(adcCh2_, pinCh2);    // ADC3 の初期設定
00038         ADC->CCR = 0x0;     // ADC 共通の設定, 念のため
00039 
00040         // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
00041         SetFs(fSampling);
00042     }
00043 
00044     // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
00045     //      fSampling   標本化周波数 [kHz]
00046     void DspAdcDualBase::SetFs(float fSampling)
00047     {
00048         __HAL_RCC_TIM8_CLK_ENABLE();    // クロック供給. "stm32f4xx_hal_rcc.h" 参照
00049         TIM_TypeDef* const TIM = TIM8;
00050 
00051         TIM->CR2 = TIM_TRGO_UPDATE;     // Update event を TRGO とする
00052 
00053         uint32_t psc = 0;
00054         uint16_t mul = 1;
00055         fSampling = fSampling*1000;     // Hz 単位に変換
00056         uint32_t arr;
00057         while (true)
00058         {
00059             arr = (uint32_t)(SystemCoreClock/(mul*fSampling) + 0.5f);
00060             if (arr <= 65536) break;
00061             psc++;
00062             mul++;
00063             MBED_ASSERT(psc <= 65536);  // 標本化周波数が低すぎないかチェック
00064         }
00065         TIM->ARR = arr - 1;     // Auto-reload レジスタの設定
00066         TIM->PSC = psc;         // Prescaler の設定
00067         TIM->CR1 = TIM_CR1_CEN; // TIM8 を有効にする
00068     }
00069 
00070     // AD 変換器の初期設定
00071     void DspAdcDualBase::Initialize(ADC_TypeDef* adc, PinName pin)
00072     {
00073         // 一つの ADC につき,1 チャンネルのみ使用の設定
00074         adc->SQR1 &= ~ADC_SQR1_L;
00075 
00076         // pin に対応するチャンネルを使うための設定
00077         adc->SQR3 = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_ADC));
00078         // pinmap_function() のヘッダファイル: mbed\hal\pinmap.h
00079         // pinmap_function() が定義されているファイル: mbed-dev\hal\mbed_pinmap_common.c
00080         // STM_PIN_CHANNEL() の定義:mbed\TARGET_NUCLEO_F446RE\TOOLCHAIN_ARM_STD\
00081         //                           PinNamesTypes.h
00082 
00083         // ADC の CR1 の設定
00084         adc->CR1 = 0x0;  // 12bit, 非Scan モード,AD 変換終了割込みを禁止
00085 
00086         // ADC の CR2 の設定
00087         adc->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING  // 外部トリガの立ち上がりで開始される
00088                  | ADC_EXTERNALTRIGCONV_T8_TRGO     // 外部トリガ: Timer8 TRGO event
00089                  | ADC_CR2_ADON;                    // ADC を有効にする
00090     }
00091 
00092     //  pin に対応する AD 変換器が存在することを確認する
00093     //      pin     A0, PA_0 など
00094     //      adc     ADC1 など
00095     bool DspAdcDualBase::PinmapMatch(PinName pin, ADC_TypeDef* const adc)
00096     {
00097         for (int n=0; PinMap_ADC[n].pin != NC; n++)
00098             if ( ((PinMap_ADC[n].pin & 0xFF) == pin) &
00099                  (PinMap_ADC[n].peripheral == (uint32_t)adc) ) return true;
00100         return false;
00101     }
00102 }