1313#define ADCx_CLK (RCC_APB2Periph_ADC1)
1414#define ADC_NUM_CHANNELS (16)
1515
16+ /* Internally connected ADC channels Temp/VBAT/VREF*/
17+ #if defined (STM32F40XX ) || defined(STM32F41XX )
18+ #define ADC_TEMP_CHANNEL (16)
19+ #define ADC_VBAT_CHANNEL (18)
20+ #define ADC_VREF_CHANNEL (17)
21+ #elif defined (STM32F42XX ) || defined(STM32F43XX )
22+ #define ADC_TEMP_CHANNEL (18)
23+ #define ADC_VBAT_CHANNEL (18) /* same channel as TEMP */
24+ #define ADC_VREF_CHANNEL (17)
25+ #endif
26+
27+ /* Core temperature sensor definitions */
28+ #define CORE_TEMP_V25 (943) /* (0.76v/3.3v)*(2^ADC resoultion) */
29+ #define CORE_TEMP_AVG_SLOPE (3) /* (2.5mv/3.3v)*(2^ADC resoultion) */
30+
31+ /* VBAT divider */
32+ #if defined (STM32F40XX ) || defined(STM32F41XX )
33+ #define VBAT_DIV (2)
34+ #elif defined (STM32F42XX ) || defined(STM32F43XX )
35+ #define VBAT_DIV (4)
36+ #endif
37+
1638/* GPIO struct */
1739typedef struct {
1840 GPIO_TypeDef * port ;
@@ -82,6 +104,12 @@ void adc_init(uint32_t resolution) {
82104
83105 /* Enable ADCx */
84106 ADC_Cmd (ADCx , ENABLE );
107+
108+ /* Enable VBAT/VREF monitor */
109+ ADC_VBATCmd (ENABLE );
110+
111+ /* Enable temperature sensor */
112+ ADC_TempSensorVrefintCmd (ENABLE );
85113}
86114
87115uint32_t adc_read_channel (int channel )
@@ -93,7 +121,7 @@ uint32_t adc_read_channel(int channel)
93121 }
94122
95123 /* ADC regular channel config ADC/Channel/SEQ Rank/Sample time */
96- ADC_RegularChannelConfig (ADCx , channel , 1 , ADC_SampleTime_3Cycles );
124+ ADC_RegularChannelConfig (ADCx , channel , 1 , ADC_SampleTime_15Cycles );
97125
98126 /* Start ADC single conversion */
99127 ADC_SoftwareStartConv (ADCx );
@@ -102,7 +130,7 @@ uint32_t adc_read_channel(int channel)
102130 while (!ADC_GetFlagStatus (ADCx , ADC_FLAG_EOC ) && -- timeout > 0 ) {
103131 }
104132
105- /* ADC conversion timed out */
133+ /* ADC conversion timed out */
106134 if (timeout == 0 ) {
107135 return 0 ;
108136 }
@@ -111,6 +139,80 @@ uint32_t adc_read_channel(int channel)
111139 return ADC_GetConversionValue (ADCx );
112140}
113141
142+ int adc_read_core_temp ()
143+ {
144+ int timeout = 10000 ;
145+
146+ /* ADC temperature sensor channel config ADC/Channel/SEQ Rank/Sample time */
147+ /* Note: sample time must be higher than minimum sample time */
148+ ADC_RegularChannelConfig (ADCx , ADC_TEMP_CHANNEL , 1 , ADC_SampleTime_480Cycles );
149+
150+ /* Start ADC single conversion */
151+ ADC_SoftwareStartConv (ADCx );
152+
153+ /* Wait for conversion to be complete*/
154+ while (!ADC_GetFlagStatus (ADCx , ADC_FLAG_EOC ) && -- timeout > 0 ) {
155+ }
156+
157+ /* ADC conversion timed out */
158+ if (timeout == 0 ) {
159+ return 0 ;
160+ }
161+
162+ /* Convert ADC reading to temperature */
163+ /* Temperature formula from datasheet P.411 */
164+ return ((ADC_GetConversionValue (ADCx ) - CORE_TEMP_V25 ) / CORE_TEMP_AVG_SLOPE ) + 25 ;
165+ }
166+
167+ float adc_read_core_vbat ()
168+ {
169+ int timeout = 10000 ;
170+
171+ /* ADC VBAT channel config ADC/Channel/SEQ Rank/Sample time */
172+ /* Note: sample time must be higher than minimum sample time */
173+ ADC_RegularChannelConfig (ADCx , ADC_VBAT_CHANNEL , 1 , ADC_SampleTime_144Cycles );
174+
175+ /* Start ADC single conversion */
176+ ADC_SoftwareStartConv (ADCx );
177+
178+ /* Wait for conversion to be complete */
179+ while (!ADC_GetFlagStatus (ADCx , ADC_FLAG_EOC ) && -- timeout > 0 ) {
180+ }
181+
182+ /* ADC conversion timed out */
183+ if (timeout == 0 ) {
184+ return 0 ;
185+ }
186+
187+ /* Convert ADC reading to voltage, VBAT pin is
188+ internally connected to a bridge divider by VBAT_DIV */
189+ return ADC_GetConversionValue (ADCx )* VBAT_DIV /4096.0f * 3.3f ;
190+ }
191+
192+ float adc_read_core_vref ()
193+ {
194+ int timeout = 10000 ;
195+
196+ /* ADC VBAT channel config ADC/Channel/SEQ Rank/Sample time */
197+ /* Note: sample time must be higher than minimum sample time */
198+ ADC_RegularChannelConfig (ADCx , ADC_VREF_CHANNEL , 1 , ADC_SampleTime_112Cycles );
199+
200+ /* Start ADC single conversion */
201+ ADC_SoftwareStartConv (ADCx );
202+
203+ /* Wait for conversion to be complete*/
204+ while (!ADC_GetFlagStatus (ADCx , ADC_FLAG_EOC ) && -- timeout > 0 ) {
205+ }
206+
207+ /* ADC conversion timed out */
208+ if (timeout == 0 ) {
209+ return 0 ;
210+ }
211+
212+ /* Convert ADC reading to voltage */
213+ return ADC_GetConversionValue (ADCx )/4096.0f * 3.3f ;
214+ }
215+
114216/******************************************************************************/
115217/* Micro Python bindings */
116218
@@ -132,15 +234,54 @@ static mp_obj_t adc_obj_read_channel(mp_obj_t self_in, mp_obj_t channel) {
132234 return ret ;
133235}
134236
237+ static mp_obj_t adc_obj_read_core_temp (mp_obj_t self_in ) {
238+ mp_obj_t ret = mp_const_none ;
239+ pyb_adc_obj_t * self = self_in ;
240+
241+ if (self -> is_enabled ) {
242+ int data = adc_read_core_temp ();
243+ ret = mp_obj_new_int (data );
244+ }
245+ return ret ;
246+ }
247+
248+ static mp_obj_t adc_obj_read_core_vbat (mp_obj_t self_in ) {
249+ mp_obj_t ret = mp_const_none ;
250+ pyb_adc_obj_t * self = self_in ;
251+
252+ if (self -> is_enabled ) {
253+ float data = adc_read_core_vbat ();
254+ ret = mp_obj_new_float (data );
255+ }
256+ return ret ;
257+ }
258+
259+ static mp_obj_t adc_obj_read_core_vref (mp_obj_t self_in ) {
260+ mp_obj_t ret = mp_const_none ;
261+ pyb_adc_obj_t * self = self_in ;
262+
263+ if (self -> is_enabled ) {
264+ float data = adc_read_core_vref ();
265+ ret = mp_obj_new_float (data );
266+ }
267+ return ret ;
268+ }
269+
135270static void adc_obj_print (void (* print )(void * env , const char * fmt , ...), void * env , mp_obj_t self_in ) {
136271 pyb_adc_obj_t * self = self_in ;
137272 print (env , "<ADC %lu>" , self -> adc_id );
138273}
139274
140275static MP_DEFINE_CONST_FUN_OBJ_2 (adc_obj_read_channel_obj , adc_obj_read_channel ) ;
276+ static MP_DEFINE_CONST_FUN_OBJ_1 (adc_obj_read_core_temp_obj , adc_obj_read_core_temp ) ;
277+ static MP_DEFINE_CONST_FUN_OBJ_1 (adc_obj_read_core_vbat_obj , adc_obj_read_core_vbat ) ;
278+ static MP_DEFINE_CONST_FUN_OBJ_1 (adc_obj_read_core_vref_obj , adc_obj_read_core_vref ) ;
141279
142280static const mp_method_t adc_methods [] = {
143281 { "read_channel" , & adc_obj_read_channel_obj },
282+ { "read_core_temp" , & adc_obj_read_core_temp_obj },
283+ { "read_core_vbat" , & adc_obj_read_core_vbat_obj },
284+ { "read_core_vref" , & adc_obj_read_core_vref_obj },
144285 { NULL , NULL },
145286};
146287
0 commit comments