@@ -106,7 +106,7 @@ pub struct Adc {
106106 sample_time : SampleTime ,
107107 align : Align ,
108108 precision : Precision ,
109- vdda_mv : Option < u32 > ,
109+ vref_cache : Option < u16 > ,
110110}
111111
112112/// Contains the calibration factors for the ADC which can be reused with [`Adc::set_calibration()`]
@@ -125,7 +125,7 @@ impl Adc {
125125 sample_time : SampleTime :: T_2 ,
126126 align : Align :: Right ,
127127 precision : Precision :: B_12 ,
128- vdda_mv : None ,
128+ vref_cache : None ,
129129 }
130130 }
131131
@@ -228,41 +228,81 @@ impl Adc {
228228 self . rb . ier . modify ( |_, w| w. eocie ( ) . clear_bit ( ) ) ; // end of sequence interupt disable
229229 }
230230
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+
231270 pub fn read_voltage < PIN : Channel < Adc , ID = u8 > > (
232271 & mut self ,
233272 pin : & mut PIN ,
234273 ) -> 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 ( ) ?;
259275
260276 self . read ( pin) . map ( |raw : u32 | {
261- let adc_mv = ( vdda_mv * raw) >> 12 ;
277+ let adc_mv = ( vref as u32 * raw) >> 12 ;
262278 adc_mv as u16
263279 } )
264280 }
265281
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+
266306 pub fn release ( self ) -> ADC {
267307 self . rb
268308 }
@@ -453,21 +493,33 @@ macro_rules! adc_pin {
453493}
454494
455495adc_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 ) ,
473525}
0 commit comments