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.
This commit is contained in:
parent
3591285091
commit
8c10240722
145
stm/adc.c
145
stm/adc.c
|
@ -13,6 +13,28 @@
|
||||||
#define ADCx_CLK (RCC_APB2Periph_ADC1)
|
#define ADCx_CLK (RCC_APB2Periph_ADC1)
|
||||||
#define ADC_NUM_CHANNELS (16)
|
#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 */
|
/* GPIO struct */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GPIO_TypeDef* port;
|
GPIO_TypeDef* port;
|
||||||
|
@ -82,6 +104,12 @@ void adc_init(uint32_t resolution) {
|
||||||
|
|
||||||
/* Enable ADCx */
|
/* Enable ADCx */
|
||||||
ADC_Cmd(ADCx, ENABLE);
|
ADC_Cmd(ADCx, ENABLE);
|
||||||
|
|
||||||
|
/* Enable VBAT/VREF monitor */
|
||||||
|
ADC_VBATCmd(ENABLE);
|
||||||
|
|
||||||
|
/* Enable temperature sensor */
|
||||||
|
ADC_TempSensorVrefintCmd(ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t adc_read_channel(int channel)
|
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 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 */
|
/* Start ADC single conversion */
|
||||||
ADC_SoftwareStartConv(ADCx);
|
ADC_SoftwareStartConv(ADCx);
|
||||||
|
@ -102,7 +130,7 @@ uint32_t adc_read_channel(int channel)
|
||||||
while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) {
|
while(!ADC_GetFlagStatus(ADCx, ADC_FLAG_EOC) && --timeout >0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ADC conversion timed out */
|
/* ADC conversion timed out */
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -111,6 +139,80 @@ uint32_t adc_read_channel(int channel)
|
||||||
return ADC_GetConversionValue(ADCx);
|
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 */
|
/* 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;
|
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) {
|
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;
|
pyb_adc_obj_t *self = self_in;
|
||||||
print(env, "<ADC %lu>", self->adc_id);
|
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_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[] = {
|
static const mp_method_t adc_methods[] = {
|
||||||
{ "read_channel", &adc_obj_read_channel_obj},
|
{ "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 },
|
{ NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue