@@ -106,7 +106,7 @@ pub struct Adc {
106
106
sample_time : SampleTime ,
107
107
align : Align ,
108
108
precision : Precision ,
109
- vdda_mv : Option < u32 > ,
109
+ vref_cache : Option < u16 > ,
110
110
}
111
111
112
112
/// Contains the calibration factors for the ADC which can be reused with [`Adc::set_calibration()`]
@@ -125,7 +125,7 @@ impl Adc {
125
125
sample_time : SampleTime :: T_2 ,
126
126
align : Align :: Right ,
127
127
precision : Precision :: B_12 ,
128
- vdda_mv : None ,
128
+ vref_cache : None ,
129
129
}
130
130
}
131
131
@@ -228,41 +228,81 @@ impl Adc {
228
228
self . rb . ier . modify ( |_, w| w. eocie ( ) . clear_bit ( ) ) ; // end of sequence interupt disable
229
229
}
230
230
231
+ /// Read actual VREF voltage using the internal reference
232
+ ///
233
+ /// If oversampling is enabled, the return value is scaled down accordingly.
234
+ /// The product of the return value and any ADC reading always gives correct voltage in 4096ths of mV
235
+ /// regardless of oversampling and shift settings provided that these settings remain the same.
236
+ pub fn read_vref ( & mut self ) -> nb:: Result < u16 , ( ) > {
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 vref = ( vref_cal * 3_000_u32 / vref_val) as u16 ;
255
+ self . vref_cache = Some ( vref) ;
256
+ Ok ( vref)
257
+ }
258
+
259
+ /// Get VREF value using cached value if possible
260
+ ///
261
+ /// See `read_vref` for more details.
262
+ pub fn get_vref_cached ( & mut self ) -> nb:: Result < u16 , ( ) > {
263
+ if let Some ( vref) = self . vref_cache {
264
+ Ok ( vref)
265
+ } else {
266
+ self . read_vref ( )
267
+ }
268
+ }
269
+
231
270
pub fn read_voltage < PIN : Channel < Adc , ID = u8 > > (
232
271
& mut self ,
233
272
pin : & mut PIN ,
234
273
) -> nb:: Result < u16 , ( ) > {
235
- let vdda_mv = if let Some ( vdda_mv) = self . vdda_mv {
236
- vdda_mv
237
- } else {
238
- let mut vref = VRef :: new ( ) ;
239
- let vref_val: u32 = if vref. enabled ( self ) {
240
- self . read ( & mut vref) ?
241
- } else {
242
- vref. enable ( self ) ;
243
- let vref_val = self . read ( & mut vref) ?;
244
- vref. disable ( self ) ;
245
- vref_val
246
- } ;
247
-
248
- let vref_cal: u32 = unsafe {
249
- // DS12766 3.13.2
250
- ptr:: read_volatile ( 0x1FFF_75AA as * const u16 ) as u32
251
- } ;
252
-
253
- // RM0454 14.9 Calculating the actual VDDA voltage using the internal reference voltage
254
- // V_DDA = 3 V x VREFINT_CAL / VREFINT_DATA
255
- let vdda_mv = vref_cal * 3_000_u32 / vref_val;
256
- self . vdda_mv = Some ( vdda_mv) ;
257
- vdda_mv
258
- } ;
274
+ let vref = self . get_vref_cached ( ) ?;
259
275
260
276
self . read ( pin) . map ( |raw : u32 | {
261
- let adc_mv = ( vdda_mv * raw) >> 12 ;
277
+ let adc_mv = ( vref as u32 * raw) >> 12 ;
262
278
adc_mv as u16
263
279
} )
264
280
}
265
281
282
+ pub fn read_temperature ( & mut self ) -> nb:: Result < i16 , ( ) > {
283
+ let mut vtemp = VTemp :: new ( ) ;
284
+ let vtemp_voltage: u16 = if vtemp. enabled ( self ) {
285
+ self . read_voltage ( & mut vtemp) ?
286
+ } else {
287
+ vtemp. enable ( self ) ;
288
+ let vtemp_voltage = self . read_voltage ( & mut vtemp) ?;
289
+ vtemp. disable ( self ) ;
290
+ vtemp_voltage
291
+ } ;
292
+
293
+ let ts_cal1: u32 = unsafe {
294
+ // DS12991 3.14.1
295
+ // at 3000 mV Vref+ and 30 degC
296
+ ptr:: read_volatile ( 0x1FFF_75A8 as * const u16 ) as u32
297
+ } ;
298
+
299
+ let v30 = ( 3000_u32 * ts_cal1) >> 12 ; // mV
300
+ // 2.5 mV/degC
301
+ let t = 30 + ( vtemp_voltage as i32 - v30 as i32 ) * 10 / 25 ;
302
+
303
+ Ok ( t as i16 )
304
+ }
305
+
266
306
pub fn release ( self ) -> ADC {
267
307
self . rb
268
308
}
@@ -453,21 +493,33 @@ macro_rules! adc_pin {
453
493
}
454
494
455
495
adc_pin ! {
456
- Channel0 : ( PA0 <Analog >, 0u8 ) ,
457
- Channel1 : ( PA1 <Analog >, 1u8 ) ,
458
- Channel2 : ( PA2 <Analog >, 2u8 ) ,
459
- Channel3 : ( PA3 <Analog >, 3u8 ) ,
460
- Channel4 : ( PA4 <Analog >, 4u8 ) ,
461
- Channel5 : ( PA5 <Analog >, 5u8 ) ,
462
- Channel6 : ( PA6 <Analog >, 6u8 ) ,
463
- Channel7 : ( PA7 <Analog >, 7u8 ) ,
464
- Channel8 : ( PB0 <Analog >, 8u8 ) ,
465
- Channel9 : ( PB1 <Analog >, 9u8 ) ,
466
- Channel10 : ( PB2 <Analog >, 10u8 ) ,
467
- Channel11 : ( PB10 <Analog >, 11u8 ) ,
468
- Channel11 : ( PB7 <Analog >, 11u8 ) ,
469
- Channel15 : ( PB11 <Analog >, 15u8 ) ,
470
- Channel16 : ( PB12 <Analog >, 16u8 ) ,
471
- Channel17 : ( PC4 <Analog >, 17u8 ) ,
472
- Channel18 : ( PC5 <Analog >, 18u8 ) ,
496
+ Channel0 : ( gpioa:: PA0 <Analog >, 0u8 ) ,
497
+ Channel1 : ( gpioa:: PA1 <Analog >, 1u8 ) ,
498
+ Channel2 : ( gpioa:: PA2 <Analog >, 2u8 ) ,
499
+ Channel3 : ( gpioa:: PA3 <Analog >, 3u8 ) ,
500
+ Channel4 : ( gpioa:: PA4 <Analog >, 4u8 ) ,
501
+ Channel5 : ( gpioa:: PA5 <Analog >, 5u8 ) ,
502
+ Channel6 : ( gpioa:: PA6 <Analog >, 6u8 ) ,
503
+ Channel7 : ( gpioa:: PA7 <Analog >, 7u8 ) ,
504
+ Channel8 : ( gpiob:: PB0 <Analog >, 8u8 ) ,
505
+ Channel9 : ( gpiob:: PB1 <Analog >, 9u8 ) ,
506
+ Channel10 : ( gpiob:: PB2 <Analog >, 10u8 ) ,
507
+ Channel11 : ( gpiob:: PB10 <Analog >, 11u8 ) ,
508
+ Channel15 : ( gpiob:: PB11 <Analog >, 15u8 ) ,
509
+ Channel16 : ( gpiob:: PB12 <Analog >, 16u8 ) ,
510
+ }
511
+
512
+ #[ cfg( any( feature = "stm32g030" , feature = "stm32g031" , feature = "stm32g041" , ) ) ]
513
+ adc_pin ! {
514
+ Channel11 : ( gpiob:: PB7 <Analog >, 11u8 ) ,
515
+ Channel15 : ( gpioa:: PA11 <Analog >, 15u8 ) ,
516
+ Channel16 : ( gpioa:: PA12 <Analog >, 16u8 ) ,
517
+ Channel17 : ( gpioa:: PA13 <Analog >, 17u8 ) ,
518
+ Channel18 : ( gpioa:: PA14 <Analog >, 18u8 ) ,
519
+ }
520
+
521
+ #[ cfg( any( feature = "stm32g070" , feature = "stm32g071" , feature = "stm32g081" , ) ) ]
522
+ adc_pin ! {
523
+ Channel17 : ( gpioc:: PC4 <Analog >, 17u8 ) ,
524
+ Channel18 : ( gpioc:: PC5 <Analog >, 18u8 ) ,
473
525
}
0 commit comments