Nucleo-F446RE 内蔵の AD/DA を使うためのライブラリ.DA からの出力は,標本化周波数の4倍のレートで行う. このライブラリを登録した際のプログラム: Demo_F446_AD_DA_Multirate. Library for built-in ADC and DAC in Nucleo-F446RE. Sampling rate for DAC is four times of that for ADC.
Dependents: F446_UpSampling_GraphicEqualizer F446_UpSampling_ReverbSystem F446_UpSampling_FrqShifter_Weaver Demo_F446_AD_DA_Multirate ... more
Diff: F446_ADC.cpp
- Revision:
- 0:2447a7d225b1
- Child:
- 3:285cebe5823c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/F446_ADC.cpp Wed May 16 01:40:50 2018 +0000 @@ -0,0 +1,91 @@ +//---------------------------------------------------------------- +// AD Conversion by interrupt using ADC2 or ADC3 on STM32F446 +// +// STM32F446 の ADC2 または ADC3 を使って割込みによりアナログ信号を +// 入力するクラス ― マルチ・レート処理用 +// +// 2018/04/18, Copyright (c) 2018 MIKAMI, Naoki +//---------------------------------------------------------------- + +#include "F446_ADC.hpp" + +namespace Mikami +{ + AdcF446::AdcF446(int frequency, PinName pin) + { + if ( (pin != A0) && (pin != A1) ) + { + fprintf(stderr, "Invalid pin name\r\n"); + while (true) {} + } + + // PA0 または PA1 を ADC 入力として使うための設定 + __HAL_RCC_GPIOA_CLK_ENABLE(); + GPIO_InitTypeDef gpioInit; + gpioInit.Pin = (pin == A0) ? GPIO_PIN_0 : GPIO_PIN_1; + gpioInit.Mode = GPIO_MODE_ANALOG; + gpioInit.Pull = GPIO_NOPULL; + gpioInit.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + HAL_GPIO_Init(GPIOA, &gpioInit); + + if (pin == A0) // ADC2 の設定 (入力ポート:PA0) + { + __HAL_RCC_ADC2_CLK_ENABLE(); + adc_ = ADC2; + adc_->SQR3 = 0x0; // CH0 を使う + } + else // ADC3 の設定 (入力ポート:PA1) + { + __HAL_RCC_ADC3_CLK_ENABLE(); + adc_ = ADC3; + adc_->SQR3 = 0x1; // CH1 を使う + } + adc_->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING // 外部トリガの立ち上がりで開始される + | ADC_EXTERNALTRIGCONV_T8_TRGO // 外部トリガ: Timer8 TRGO event + | ADC_CR2_ADON; // ADC を有効にする + adc_->CR1 = ADC_CR1_EOCIE; // ADC の変換終了割り込みを有効にする + + // ADC 共通の設定 + ADC->CCR = 0x0; // 念のため + + // AD 変換器の外部トリガに使うタイマ (TIM8) の設定 + // 標本化周波数としてアップサンプリングに対応する値を設定する + SetTim8(frequency); + } + + // 割込みベクタを設定し,ADC 割込みを有効にする + void AdcF446::SetIntrVec(void (*Func)()) + { + NVIC_SetVector(ADC_IRQn, (uint32_t)Func); // "cmsis_nvic.h" 参照 + NVIC_EnableIRQ(ADC_IRQn); // "core_cm4.h" 参照 + } + + + void AdcF446::SetTim8(int frequency) + { + __HAL_RCC_TIM8_CLK_ENABLE(); // クロック供給. "stm32f4xx_hal_rcc.h" 参照 + SystemCoreClockUpdate(); // クロックの更新. See "system_stm32f4xx.h" 参照 + TIM_TypeDef* const myTim = TIM8; + + myTim->CR2 = TIM_CR2_MMS_1; // Update event を TRGO (trigger output) とする + + uint32_t psc = 0; + uint16_t mul = 1; + uint32_t arr; + while (true) + { + arr = SystemCoreClock/(mul*frequency); + if (arr <= 65536) break; + psc++; + mul++; + if (psc > 65535) + { + fprintf(stderr, "Sampling frequency: too low.\r\n"); + while (true) {} + } + } + myTim->ARR = arr - 1; // Auto-reload レジスタの設定 + myTim->PSC = psc; // Prescaler の設定 + myTim->CR1 = TIM_CR1_CEN; // TIM8 を有効にする + } +}