1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/cpu/stm32f2/periph/adc.c
2015-12-13 11:00:06 +01:00

186 lines
3.9 KiB
C

/*
* Copyright (C) 2015 Engineering-Spirit
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup cpu_stm32f2
* @{
*
* @file
* @brief Low-level ADC driver implementation
*
* @author Nick v. IJzendoorn <nijzendoorn@engineering-spirit.nl>
*
* @}
*/
#include "cpu.h"
#include "periph/adc.h"
#include "periph_conf.h"
/* guard in case that no ADC device is defined */
#if ADC_NUMOF
typedef struct {
int max_value;
} adc_config_t;
adc_config_t adc_config[ADC_NUMOF];
int adc_init(adc_t dev, adc_precision_t precision)
{
ADC_TypeDef *adc = 0;
adc_poweron(dev);
switch (dev) {
#if ADC_0_EN
case ADC_0:
adc = ADC_0_DEV;
ADC_0_PORT_CLKEN();
ADC_0_PORT->MODER |= (3 << (ADC_0_CH0_PIN * 2) | 3 << (ADC_0_CH1_PIN * 2));
break;
#endif
#if ADC_1_EN
case ADC_1:
adc = ADC_1_DEV;
ADC_1_PORT_CLKEN();
ADC_1_PORT->MODER |= (3 << (ADC_1_CH0_PIN * 2) | 3 << (ADC_1_CH1_PIN * 2));
break;
#endif
default:
return -1;
}
/* reset control registers */
adc->CR1 = 0;
adc->CR2 = 0;
adc->SQR1 = 0;
/* set precision */
switch (precision) {
case ADC_RES_6BIT:
adc->CR1 |= ADC_CR1_RES_0 | ADC_CR1_RES_1;
adc_config[dev].max_value = 0x3f;
break;
case ADC_RES_8BIT:
adc->CR1 |= ADC_CR1_RES_1;
adc_config[dev].max_value = 0xff;
break;
case ADC_RES_10BIT:
adc->CR1 |= ADC_CR1_RES_0;
adc_config[dev].max_value = 0x3ff;
break;
case ADC_RES_12BIT:
adc_config[dev].max_value = 0xfff;
break;
case ADC_RES_14BIT:
case ADC_RES_16BIT:
adc_poweroff(dev);
return -1;
break;
}
/* set clock prescaler */
ADC->CCR = (3 << 16); /* ADC clock = 10,5MHz */
/* enable the ADC module */
adc->CR2 |= ADC_CR2_ADON;
return 0;
}
int adc_sample(adc_t dev, int channel)
{
ADC_TypeDef *adc = 0;
switch (dev) {
#if ADC_0_EN
case ADC_0:
adc = ADC_0_DEV;
switch (channel) {
case 0:
adc->SQR3 = ADC_0_CH0 & 0x1f;
break;
case 1:
adc->SQR3 = ADC_0_CH1 & 0x1f;
break;
default:
return -1;
}
break;
#endif
#if ADC_1_EN
case ADC_1:
adc = ADC_1_DEV;
switch (channel) {
case 0:
adc->SQR3 = ADC_1_CH0 & 0x1f;
break;
case 1:
adc->SQR3 = ADC_1_CH1 & 0x1f;
break;
default:
return -1;
}
break;
#endif
}
/* start single conversion */
adc->CR2 |= ADC_CR2_SWSTART;
/* wait until conversion is complete */
while (!(adc->SR & ADC_SR_EOC));
/* read and return result */
return (int)adc->DR;
}
void adc_poweron(adc_t dev)
{
switch (dev) {
#if ADC_0_EN
case ADC_0:
ADC_0_CLKEN();
break;
#endif
#if ADC_1_EN
case ADC_1:
ADC_1_CLKEN();
break;
#endif
}
}
void adc_poweroff(adc_t dev)
{
switch (dev) {
#if ADC_0_EN
case ADC_0:
ADC_0_CLKDIS();
break;
#endif
#if ADC_1_EN
case ADC_1:
ADC_1_CLKDIS();
break;
#endif
}
}
int adc_map(adc_t dev, int value, int min, int max)
{
return (int)adc_mapf(dev, value, (float)min, (float)max);
}
float adc_mapf(adc_t dev, int value, float min, float max)
{
return ((max - min) / ((float)adc_config[dev].max_value)) * value;
}
#endif /* ADC_NUMOF */