Library for build-in ADC and DAC in STM32F446 mounted on Nucleo F446RE. For single channel. Nucleo F446RE に搭載されている STM32F446 の内蔵 ADC, DAC 用のライブラリ.1チャンネルで使う場合.

Dependents:   Demo_F446_AD_DA_Single F446ZE-mbed-devfiles

F446_ADC_Single.cpp

Committer:
MikamiUitOpen
Date:
2017-02-21
Revision:
0:2a5690e56a16

File content as of revision 0:2a5690e56a16:

//------------------------------------------------------------
//  AD Conversion by polling using ADC2 or ADC3 on STM32F446
//
//  STM32F446 の ADC2, ADC3 を使ってポーリングによりアナログ信号を
//  入力するクラス
//      A0 (PA_0) :  ADC2 CH0
//      A1 (PA_1) :  ADC3 CH1
//
//  2017/02/16, Copyright (c) 2017 MIKAMI, Naoki
//------------------------------------------------------------

#include "F446_ADC_Single.hpp"

namespace Mikami
{
    AdcSingle::AdcSingle(PinName pin, int frequency)
    {
        if ( (pin != A0) && (pin != A1) )
        {
        	fprintf(stderr, "Invalid pin name\r\n");
        	return;
        }
       
        // 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 を使う
	        fpWait = &AdcSingle::WaitDone2;
		}
		else			// ADC3 の設定 (入力ポート:PA1)
		{
    	    __HAL_RCC_ADC3_CLK_ENABLE();
    	    adc_ = ADC3;
	        adc_->SQR3 = 0x1;       // CH1 を使う
	        fpWait = &AdcSingle::WaitDone3;
        }
   	    adc_->CR1 = 0x0;
       	adc_->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING // 外部トリガの立ち上がりで開始される
           	      | ADC_EXTERNALTRIGCONV_T8_TRGO    // 外部トリガ: Timer8 TRGO event
               	  | ADC_CR2_ADON;                   // ADC を有効にする

        // ADC 共通の設定
        ADC->CCR = 0x0;     // 念のため

        // AD 変換器の外部トリガに使うタイマ (TIM8) の設定
        SetTim8(frequency);
    }

    float AdcSingle::Read()
    {
		(this->*fpWait)();
        return ToFloat(adc_->DR);
    }

    uint16_t AdcSingle::ReadUint()
    {
		(this->*fpWait)();
        return adc_->DR;
    }

    void AdcSingle::SetTim8(int frequency)
    {
        __HAL_RCC_TIM8_CLK_ENABLE();    // Supply clock. See "stm32f4xx_hal_rcc.h"
        SystemCoreClockUpdate();        // Update core clock. See "system_stm32f4xx.h"
        TIM_TypeDef* const myTim = TIM8;

        myTim->CR2 = TIM_CR2_MMS_1; // Update event: as trigger out

    	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;   // Enable TIM8
    }
}