CQエレクトロニクス・セミナ「実習・マイコンを動かしながら学ぶディジタル・フィルタ」で使うプログラムを,入力として STM32F746 の内蔵 ADC を使うように変更したもの. http://seminar.cqpub.co.jp/ccm/ES18-0020

Dependencies:   mbed Array_Matrix BSP_DISCO_F746NG LCD_DISCO_F746NG TS_DISCO_F746NG

F764_Adc/F746_ADC.cpp

Committer:
MikamiUitOpen
Date:
2018-03-12
Revision:
2:dd48e1e59daa
Parent:
0:ab7a35d87173

File content as of revision 2:dd48e1e59daa:

//----------------------------------------------------------
//  Simultanuous AD Conversion by polling using
//  ADC1 and ADC3 on STM32F746
//
//  STM32F746 の ADC1, ADC3 を使って同時に AD 変換を開始し,
//  ポーリングによりアナログ信号を入力するクラス
//
//      PA_0  (DISCO-F746 の A0) :  ADC1 CH0
//      PF_10 (DISCO-F746 の A1) :  ADC3 CH8
//
//  2017/08/16, Copyright (c) 2017 MIKAMI, Naoki
//----------------------------------------------------------

#include "F746_ADC.hpp"

namespace Mikami
{
    AdcDual::AdcDual(int frequency)
    {
        GPIO_InitTypeDef gpioInit;
        // 以下の三つのメンバの値は共通
        gpioInit.Mode = GPIO_MODE_ANALOG;
        gpioInit.Pull = GPIO_NOPULL;
        gpioInit.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

        // PA0 を ADC 入力として使うための設定
        __HAL_RCC_GPIOA_CLK_ENABLE();
        HAL_GPIO_DeInit(GPIOA, 0);
        gpioInit.Pin = GPIO_PIN_0;
        HAL_GPIO_Init(GPIOA, &gpioInit);

        // PF10 を ADC 入力として使うための設定
        __HAL_RCC_GPIOF_CLK_ENABLE();
        HAL_GPIO_DeInit(GPIOF, 10);
        gpioInit.Pin = GPIO_PIN_10;
        HAL_GPIO_Init(GPIOF, &gpioInit);

        // ADC1 の設定 (PA0)
        __HAL_RCC_ADC1_CLK_ENABLE();
        ADC1->CR1 = 0x0;
        ADC1->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING // 外部トリガの立ち上がりで開始される
                  | ADC_EXTERNALTRIGCONV_T6_TRGO    // 外部トリガ: Timer6 TRGO event
                  | ADC_CR2_ADON;                   // ADC を有効にする
        ADC1->SQR3 = 0x0;                           // CH0 を使う

        // ADC3 の設定 (PF10)
        __HAL_RCC_ADC3_CLK_ENABLE();
        ADC3->CR1 = 0x0;
        ADC3->CR2 = ADC_EXTERNALTRIGCONVEDGE_RISING // 外部トリガの立ち上がりで開始される
                  | ADC_EXTERNALTRIGCONV_T6_TRGO    // 外部トリガ: Timer6 TRGO event
                  | ADC_CR2_ADON;                   // ADC を有効にする
        ADC3->SQR3 = 0x8;                           // CH8 を使う
        
        // ADC 共通の設定
        ADC->CCR = 0x0;     // 念のため

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

        // これを入れなければ動かない(理由は不明)
        __DAC_CLK_ENABLE();
        // 下記と同じ処理の別表現
        // RCC->APB1ENR |= RCC_APB1ENR_DACEN;
    }

    void AdcDual::Read(float &ad1, float &ad2)
    {
        WaitDone();
        ad1 = ToFloat(ADC1->DR);
        ad2 = ToFloat(ADC3->DR);
    }

    void AdcDual::Read(uint16_t &ad1, uint16_t &ad2)
    {
        WaitDone();
        ad1 = ADC1->DR;
        ad2 = ADC3->DR;
    }

    void AdcDual::SetTim6(int frequency)
    {
        __HAL_RCC_TIM6_CLK_ENABLE();    // Supply clock. See "stm32f7xx_hal_rcc_ex.h"
        SystemCoreClockUpdate();        // Update core clock. See "system_stm32f7xx.h"
       
        TIM_TypeDef* const myTim = TIM6;

        myTim->CR2 = TIM_CR2_MMS_1; // Update event: as trigger out
        
        uint32_t psc = 0;
        uint32_t arr;
        while (true)
        {
            // TIM6 の入力のクロックは RCC_DCKCFGR1 の TIMPRE ビットにより
            // 108/216 MHz のいずれかに設定される
            // (RM0385 Rev.2, Reference manual では RCC_DKCFGR1 となっている)
            if ((RCC->DCKCFGR1 & RCC_DCKCFGR1_TIMPRE) == RCC_DCKCFGR1_TIMPRE)
                arr = SystemCoreClock/((psc + 1)*frequency);
            else
                arr = (SystemCoreClock/2)/((psc + 1)*frequency);
            if (arr <= 65536) break;
            psc++;
        }
        myTim->ARR = arr - 1;       // Auto-reload
        myTim->PSC = psc;           // Prescaler
        myTim->CR1 = TIM_CR1_CEN;   // Enable TIM6
    }
}