diff options
author | mux <freelancer.c@gmail.com> | 2014-01-14 22:32:53 +0200 |
---|---|---|
committer | mux <freelancer.c@gmail.com> | 2014-01-14 22:32:53 +0200 |
commit | 8c10240722951e19b13f35e5bec289060b531cd9 (patch) | |
tree | 7825428c0b740322fd025e1b7d996237056c2533 | |
parent | 3591285091c781f8c25115660d53873af04e3bf6 (diff) | |
download | micropython-8c10240722951e19b13f35e5bec289060b531cd9.tar.gz micropython-8c10240722951e19b13f35e5bec289060b531cd9.zip |
Add ADC support for internal TEMP/VBAT/VREF
* Add ADC support for reading internal temperature sensor.
* Add ADC support for reading internal VREF/VBAT monitor.
-rw-r--r-- | stm/adc.c | 145 |
1 files changed, 143 insertions, 2 deletions
@@ -13,6 +13,28 @@ #define ADCx_CLK (RCC_APB2Periph_ADC1) #define ADC_NUM_CHANNELS (16) +/* Internally connected ADC channels Temp/VBAT/VREF*/ +#if defined (STM32F40XX) || defined(STM32F41XX) +#define ADC_TEMP_CHANNEL (16) +#define ADC_VBAT_CHANNEL (18) +#define ADC_VREF_CHANNEL (17) +#elif defined (STM32F42XX) || defined(STM32F43XX) +#define ADC_TEMP_CHANNEL (18) +#define ADC_VBAT_CHANNEL (18) /* same channel as TEMP */ +#define ADC_VREF_CHANNEL (17) +#endif + +/* Core temperature sensor definitions */ +#define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */ +#define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */ + +/* VBAT divider */ +#if defined (STM32F40XX) || defined(STM32F41XX) +#define VBAT_DIV (2) +#elif defined (STM32F42XX) || defined(STM32F43XX) +#define VBAT_DIV (4) +#endif + /* GPIO struct */ typedef struct { GPIO_TypeDef* port; @@ -82,6 +104,12 @@ void adc_init(uint32_t resolution) { /* Enable ADCx */ ADC_Cmd(ADCx, ENABLE); + + /* Enable VBAT/VREF monitor */ + ADC_VBATCmd(ENABLE); + + /* Enable temperature sensor */ + ADC_TempSensorVrefintCmd(ENABLE); } uint32_t adc_read_channel(int channel) @@ -93,7 +121,7 @@ uint32_t adc_read_channel(int channel) } /* ADC regular channel config ADC/Channel/SEQ Rank/Sample time */ - ADC_RegularChannelConfig(ADCx, channel, 1, ADC_SampleTime_3Cycles); + ADC_RegularChannelConfig(ADCx, channel, 1, ADC_SampleTime_15Cycles); /* Start ADC single conversion */ ADC_SoftwareStartConv(ADCx); @@ -102,7 +130,7 @@ uint32_t adc_read_channel(int channel) while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) { } - /* ADC conversion timed out */ + /* ADC conversion timed out */ if (timeout == 0) { return 0; } @@ -111,6 +139,80 @@ uint32_t adc_read_channel(int channel) return ADC_GetConversionValue(ADCx); } +int adc_read_core_temp() +{ + int timeout = 10000; + + /* ADC temperature sensor channel config ADC/Channel/SEQ Rank/Sample time */ + /* Note: sample time must be higher than minimum sample time */ + ADC_RegularChannelConfig(ADCx, ADC_TEMP_CHANNEL, 1, ADC_SampleTime_480Cycles); + + /* Start ADC single conversion */ + ADC_SoftwareStartConv(ADCx); + + /* Wait for conversion to be complete*/ + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) { + } + + /* ADC conversion timed out */ + if (timeout == 0) { + return 0; + } + + /* Convert ADC reading to temperature */ + /* Temperature formula from datasheet P.411 */ + return ((ADC_GetConversionValue(ADCx) - CORE_TEMP_V25) / CORE_TEMP_AVG_SLOPE) + 25; +} + +float adc_read_core_vbat() +{ + int timeout = 10000; + + /* ADC VBAT channel config ADC/Channel/SEQ Rank/Sample time */ + /* Note: sample time must be higher than minimum sample time */ + ADC_RegularChannelConfig(ADCx, ADC_VBAT_CHANNEL, 1, ADC_SampleTime_144Cycles); + + /* Start ADC single conversion */ + ADC_SoftwareStartConv(ADCx); + + /* Wait for conversion to be complete */ + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) { + } + + /* ADC conversion timed out */ + if (timeout == 0) { + return 0; + } + + /* Convert ADC reading to voltage, VBAT pin is + internally connected to a bridge divider by VBAT_DIV */ + return ADC_GetConversionValue(ADCx)*VBAT_DIV/4096.0f*3.3f; +} + +float adc_read_core_vref() +{ + int timeout = 10000; + + /* ADC VBAT channel config ADC/Channel/SEQ Rank/Sample time */ + /* Note: sample time must be higher than minimum sample time */ + ADC_RegularChannelConfig(ADCx, ADC_VREF_CHANNEL, 1, ADC_SampleTime_112Cycles); + + /* Start ADC single conversion */ + ADC_SoftwareStartConv(ADCx); + + /* Wait for conversion to be complete*/ + while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) { + } + + /* ADC conversion timed out */ + if (timeout == 0) { + return 0; + } + + /* Convert ADC reading to voltage */ + return ADC_GetConversionValue(ADCx)/4096.0f*3.3f; +} + /******************************************************************************/ /* Micro Python bindings */ @@ -132,15 +234,54 @@ static mp_obj_t adc_obj_read_channel(mp_obj_t self_in, mp_obj_t channel) { return ret; } +static mp_obj_t adc_obj_read_core_temp(mp_obj_t self_in) { + mp_obj_t ret = mp_const_none; + pyb_adc_obj_t *self = self_in; + + if (self->is_enabled) { + int data = adc_read_core_temp(); + ret = mp_obj_new_int(data); + } + return ret; +} + +static mp_obj_t adc_obj_read_core_vbat(mp_obj_t self_in) { + mp_obj_t ret = mp_const_none; + pyb_adc_obj_t *self = self_in; + + if (self->is_enabled) { + float data = adc_read_core_vbat(); + ret = mp_obj_new_float(data); + } + return ret; +} + +static mp_obj_t adc_obj_read_core_vref(mp_obj_t self_in) { + mp_obj_t ret = mp_const_none; + pyb_adc_obj_t *self = self_in; + + if (self->is_enabled) { + float data = adc_read_core_vref(); + ret = mp_obj_new_float(data); + } + return ret; +} + static void adc_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) { pyb_adc_obj_t *self = self_in; print(env, "<ADC %lu>", self->adc_id); } static MP_DEFINE_CONST_FUN_OBJ_2(adc_obj_read_channel_obj, adc_obj_read_channel); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_temp_obj, adc_obj_read_core_temp); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vbat_obj, adc_obj_read_core_vbat); +static MP_DEFINE_CONST_FUN_OBJ_1(adc_obj_read_core_vref_obj, adc_obj_read_core_vref); static const mp_method_t adc_methods[] = { { "read_channel", &adc_obj_read_channel_obj}, + { "read_core_temp", &adc_obj_read_core_temp_obj}, + { "read_core_vbat", &adc_obj_read_core_vbat_obj}, + { "read_core_vref", &adc_obj_read_core_vref_obj}, { NULL, NULL }, }; |