1
1
//! # Analog to Digital converter
2
+ use core:: ptr;
3
+
2
4
use crate :: gpio:: * ;
3
5
use crate :: rcc:: Rcc ;
4
6
use crate :: stm32:: ADC ;
@@ -104,6 +106,7 @@ pub struct Adc {
104
106
sample_time : SampleTime ,
105
107
align : Align ,
106
108
precision : Precision ,
109
+ vdda_mv : Option < u32 > ,
107
110
}
108
111
109
112
/// Contains the calibration factors for the ADC which can be reused with [`Adc::set_calibration()`]
@@ -121,6 +124,7 @@ impl Adc {
121
124
sample_time : SampleTime :: T_2 ,
122
125
align : Align :: Right ,
123
126
precision : Precision :: B_12 ,
127
+ vdda_mv : None ,
124
128
}
125
129
}
126
130
@@ -223,6 +227,41 @@ impl Adc {
223
227
self . rb . ier . modify ( |_, w| w. eocie ( ) . clear_bit ( ) ) ; // end of sequence interupt disable
224
228
}
225
229
230
+ pub fn read_voltage < PIN : Channel < Adc , ID = u8 > > (
231
+ & mut self ,
232
+ pin : & mut PIN ,
233
+ ) -> nb:: Result < u16 , ( ) > {
234
+ let vdda_mv = if let Some ( vdda_mv) = self . vdda_mv {
235
+ vdda_mv
236
+ } else {
237
+ let mut vref = VRef :: new ( ) ;
238
+ let vref_val: u32 = if vref. enabled ( self ) {
239
+ self . read ( & mut vref) ?
240
+ } else {
241
+ vref. enable ( self ) ;
242
+ let vref_val = self . read ( & mut vref) ?;
243
+ vref. disable ( self ) ;
244
+ vref_val
245
+ } ;
246
+
247
+ let vref_cal: u32 = unsafe {
248
+ // DS12766 3.13.2
249
+ ptr:: read_volatile ( 0x1FFF_75AA as * const u16 ) as u32
250
+ } ;
251
+
252
+ // RM0454 14.9 Calculating the actual VDDA voltage using the internal reference voltage
253
+ // V_DDA = 3 V x VREFINT_CAL / VREFINT_DATA
254
+ let vdda_mv = vref_cal * 3_000_u32 / vref_val;
255
+ self . vdda_mv = Some ( vdda_mv) ;
256
+ vdda_mv
257
+ } ;
258
+
259
+ self . read ( pin) . map ( |raw : u32 | {
260
+ let adc_mv = ( vdda_mv * raw) >> 12 ;
261
+ adc_mv as u16
262
+ } )
263
+ }
264
+
226
265
pub fn release ( self ) -> ADC {
227
266
self . rb
228
267
}
@@ -375,6 +414,10 @@ macro_rules! int_adc {
375
414
pub fn disable( & mut self , adc: & mut Adc ) {
376
415
adc. rb. ccr. modify( |_, w| w. $en( ) . clear_bit( ) ) ;
377
416
}
417
+
418
+ pub fn enabled( & self , adc: & Adc ) -> bool {
419
+ adc. rb. ccr. read( ) . $en( ) . bit_is_set( )
420
+ }
378
421
}
379
422
380
423
impl Default for $Chan {
@@ -394,6 +437,12 @@ macro_rules! int_adc {
394
437
} ;
395
438
}
396
439
440
+ int_adc ! {
441
+ VTemp : ( 12 , tsen) ,
442
+ VRef : ( 13 , vrefen) ,
443
+ VBat : ( 14 , vbaten) ,
444
+ }
445
+
397
446
macro_rules! adc_pin {
398
447
( $( $Chan: ty: ( $pin: ty, $chan: expr) ) ,+ $( , ) * ) => {
399
448
$(
@@ -406,12 +455,6 @@ macro_rules! adc_pin {
406
455
} ;
407
456
}
408
457
409
- int_adc ! {
410
- VTemp : ( 12 , tsen) ,
411
- VRef : ( 13 , vrefen) ,
412
- VBat : ( 14 , vbaten) ,
413
- }
414
-
415
458
adc_pin ! {
416
459
Channel0 : ( gpioa:: PA0 <Analog >, 0u8 ) ,
417
460
Channel1 : ( gpioa:: PA1 <Analog >, 1u8 ) ,
0 commit comments