/* ***************************************************************************** * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * Created: 12/18/09 02:34:47 * Copyright (c) 2009 Perry L. Hung. All rights reserved. * * ****************************************************************************/ /** * @file adc.c * * @brief Analog to digital converter routines */ #include "stm32f10x_rcc.h" #include "adc.h" #include #include /* The ADC input clock is generated from PCLK2/APB2 divided by a prescaler * and it must not exceed 14MHz. * * ADC1 and ADC2 are clocked by APB2 * * 1) Power on by setting ADON in ADC_CR2 * Conversion starts when ADON is set for a second time after some * time t > t_stab. * * Up to 16 selected conversion must be selected in ADC_SQRx * * Single conversion mode: * Set the ADON bit in the ADC_CR2 register * Once the conversion is complete: * Converted data is stored in ADC_DR * EOC flag is set * Interrupt is generated if EOCIE is set * * Calibration: * Calibration is started by setting the CAL bit in the ADC_CR2 register. * Once calibration is over, the CAL bit is reset by hardware and normal * conversion can be performed. Calibrate at power-on. * * ALIGN in ADC_CR2 selects the alignment of data * * IMPORTANT: maximum external impedance must be below 0.4kOhms for 1.5 * sample conversion time. * * At 55.5 cycles/sample, the external input impedance < 50kOhms*/ void adc_init(void) { /* PCLK2 is the APB2 clock */ RCC_ADCCLKConfig(RCC_PCLK2_Div6); /* Enable ADC1 clock so that we can talk to it */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); /* Put everything back to power-on defaults */ RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE); ADC_CR1 = 0; ADC_CR2 = CR2_EXTSEL_SWSTART | CR2_EXTTRIG; // Software triggers conversions ADC_SQR1 = 0; /* Up the sample conversion time to 55.5 cycles/sec, see note above */ /* TODO: fix magic numbers */ ADC_SMPR1 = 0xB6DB6D; ADC_SMPR2 = 0x2DB6DB6D; /* Enable the ADC */ CR2_ADON_BIT = 1; /* Reset the calibration registers and then perform a reset */ CR2_RSTCAL_BIT = 1; while(CR2_RSTCAL_BIT) ; CR2_CAL_BIT = 1; while(CR2_CAL_BIT) ; } void adc_disable(void) { CR2_ADON_BIT = 0; }