@@ -381,6 +381,7 @@ pub mod config {
381
381
pub ( crate ) dma : Dma ,
382
382
pub ( crate ) end_of_conversion_interrupt : Eoc ,
383
383
pub ( crate ) default_sample_time : SampleTime ,
384
+ pub ( crate ) vdda : Option < u32 > ,
384
385
}
385
386
386
387
impl AdcConfig {
@@ -433,6 +434,19 @@ pub mod config {
433
434
self . default_sample_time = default_sample_time;
434
435
self
435
436
}
437
+
438
+ /// Specify the reference voltage for the ADC.
439
+ ///
440
+ /// # Args
441
+ /// * `vdda_mv` - The ADC reference voltage in millivolts.
442
+ ///
443
+ /// # Note
444
+ /// Reference voltage configuration will be overridden for ADC1 by an internal calibration
445
+ /// routine.
446
+ pub fn reference_voltage ( mut self , vdda_mv : u32 ) -> Self {
447
+ self . vdda = Some ( vdda_mv) ;
448
+ self
449
+ }
436
450
}
437
451
438
452
impl Default for AdcConfig {
@@ -447,6 +461,7 @@ pub mod config {
447
461
dma : Dma :: Disabled ,
448
462
end_of_conversion_interrupt : Eoc :: Disabled ,
449
463
default_sample_time : SampleTime :: Cycles_480 ,
464
+ vdda : None ,
450
465
}
451
466
}
452
467
}
@@ -606,9 +621,82 @@ impl<ADC> fmt::Debug for Adc<ADC> {
606
621
}
607
622
608
623
macro_rules! adc {
624
+ // Note that only ADC1 supports measurement of VREF, VBAT, and the internal temperature sensor.
625
+ ( additionals: ADC1 => ( $common_type: ident) ) => {
626
+ /// Calculates the system VDDA by sampling the internal VREF channel and comparing
627
+ /// the result with the value stored at the factory.
628
+ pub fn calibrate( & mut self ) {
629
+ self . enable( ) ;
630
+
631
+ let vref_en = self . temperature_and_vref_enabled( ) ;
632
+ if !vref_en {
633
+ self . enable_temperature_and_vref( ) ;
634
+ }
635
+
636
+ let vref_cal = VrefCal :: get( ) . read( ) ;
637
+ let vref_samp = self . read( & mut Vref ) . unwrap( ) ; //This can't actually fail, it's just in a result to satisfy hal trait
638
+
639
+ self . calibrated_vdda = ( VDDA_CALIB * u32 :: from( vref_cal) ) / u32 :: from( vref_samp) ;
640
+ if !vref_en {
641
+ self . disable_temperature_and_vref( ) ;
642
+ }
643
+ }
644
+
645
+ /// Enables the vbat internal channel
646
+ pub fn enable_vbat( & self ) {
647
+ unsafe {
648
+ let common = & ( * pac:: $common_type:: ptr( ) ) ;
649
+ common. ccr. modify( |_, w| w. vbate( ) . set_bit( ) ) ;
650
+ }
651
+ }
652
+
653
+ /// Enables the vbat internal channel
654
+ pub fn disable_vbat( & self ) {
655
+ unsafe {
656
+ let common = & ( * pac:: $common_type:: ptr( ) ) ;
657
+ common. ccr. modify( |_, w| w. vbate( ) . clear_bit( ) ) ;
658
+ }
659
+ }
660
+
661
+ /// Enables the temp and vref internal channels.
662
+ /// They can't work while vbat is also enabled so this method also disables vbat.
663
+ pub fn enable_temperature_and_vref( & mut self ) {
664
+ //VBAT prevents TS and VREF from being sampled
665
+ self . disable_vbat( ) ;
666
+ unsafe {
667
+ let common = & ( * pac:: $common_type:: ptr( ) ) ;
668
+ common. ccr. modify( |_, w| w. tsvrefe( ) . set_bit( ) ) ;
669
+ }
670
+ }
671
+
672
+ /// Disables the temp and vref internal channels
673
+ pub fn disable_temperature_and_vref( & mut self ) {
674
+ unsafe {
675
+ let common = & ( * pac:: $common_type:: ptr( ) ) ;
676
+ common. ccr. modify( |_, w| w. tsvrefe( ) . clear_bit( ) ) ;
677
+ }
678
+ }
679
+
680
+ /// Returns if the temp and vref internal channels are enabled
681
+ pub fn temperature_and_vref_enabled( & mut self ) -> bool {
682
+ unsafe {
683
+ let common = & ( * pac:: $common_type:: ptr( ) ) ;
684
+ common. ccr. read( ) . tsvrefe( ) . bit_is_set( )
685
+ }
686
+ }
687
+ } ;
688
+
689
+ // Provide a stub implementation for ADCs that do not have a means of sampling VREF.
690
+ ( additionals: $adc_type: ident => ( $common_type: ident) ) => {
691
+ fn calibrate( & mut self ) { }
692
+ } ;
693
+
609
694
( $( $adc_type: ident => ( $constructor_fn_name: ident, $common_type: ident, $en_bit: expr) ) ,+ $( , ) * ) => {
610
695
$(
611
696
impl Adc <pac:: $adc_type> {
697
+
698
+ adc!( additionals: $adc_type => ( $common_type) ) ;
699
+
612
700
/// Enables the ADC clock, resets the peripheral (optionally), runs calibration and applies the supplied config
613
701
/// # Arguments
614
702
/// * `reset` - should a reset be performed. This is provided because on some devices multiple ADCs share the same common reset
@@ -628,10 +716,12 @@ macro_rules! adc {
628
716
}
629
717
}
630
718
719
+ let vdda = if let Some ( vdda) = config. vdda { vdda } else { VDDA_CALIB } ;
720
+
631
721
let mut s = Self {
632
722
config,
633
723
adc_reg: adc,
634
- calibrated_vdda: VDDA_CALIB ,
724
+ calibrated_vdda: vdda ,
635
725
max_sample: 0 ,
636
726
} ;
637
727
@@ -656,67 +746,9 @@ macro_rules! adc {
656
746
self . set_dma( config. dma) ;
657
747
self . set_end_of_conversion_interrupt( config. end_of_conversion_interrupt) ;
658
748
self . set_default_sample_time( config. default_sample_time) ;
659
- }
660
-
661
- /// Calculates the system VDDA by sampling the internal VREF channel and comparing
662
- /// the result with the value stored at the factory.
663
- pub fn calibrate( & mut self ) {
664
- self . enable( ) ;
665
749
666
- let vref_en = self . temperature_and_vref_enabled( ) ;
667
- if !vref_en {
668
- self . enable_temperature_and_vref( ) ;
669
- }
670
-
671
- let vref_cal = VrefCal :: get( ) . read( ) ;
672
- let vref_samp = self . read( & mut Vref ) . unwrap( ) ; //This can't actually fail, it's just in a result to satisfy hal trait
673
-
674
- self . calibrated_vdda = ( VDDA_CALIB * u32 :: from( vref_cal) ) / u32 :: from( vref_samp) ;
675
- if !vref_en {
676
- self . disable_temperature_and_vref( ) ;
677
- }
678
- }
679
-
680
- /// Enables the vbat internal channel
681
- pub fn enable_vbat( & self ) {
682
- unsafe {
683
- let common = & ( * pac:: $common_type:: ptr( ) ) ;
684
- common. ccr. modify( |_, w| w. vbate( ) . set_bit( ) ) ;
685
- }
686
- }
687
-
688
- /// Enables the vbat internal channel
689
- pub fn disable_vbat( & self ) {
690
- unsafe {
691
- let common = & ( * pac:: $common_type:: ptr( ) ) ;
692
- common. ccr. modify( |_, w| w. vbate( ) . clear_bit( ) ) ;
693
- }
694
- }
695
-
696
- /// Enables the temp and vref internal channels.
697
- /// They can't work while vbat is also enabled so this method also disables vbat.
698
- pub fn enable_temperature_and_vref( & mut self ) {
699
- //VBAT prevents TS and VREF from being sampled
700
- self . disable_vbat( ) ;
701
- unsafe {
702
- let common = & ( * pac:: $common_type:: ptr( ) ) ;
703
- common. ccr. modify( |_, w| w. tsvrefe( ) . set_bit( ) ) ;
704
- }
705
- }
706
-
707
- /// Disables the temp and vref internal channels
708
- pub fn disable_temperature_and_vref( & mut self ) {
709
- unsafe {
710
- let common = & ( * pac:: $common_type:: ptr( ) ) ;
711
- common. ccr. modify( |_, w| w. tsvrefe( ) . clear_bit( ) ) ;
712
- }
713
- }
714
-
715
- /// Returns if the temp and vref internal channels are enabled
716
- pub fn temperature_and_vref_enabled( & mut self ) -> bool {
717
- unsafe {
718
- let common = & ( * pac:: $common_type:: ptr( ) ) ;
719
- common. ccr. read( ) . tsvrefe( ) . bit_is_set( )
750
+ if let Some ( vdda) = config. vdda {
751
+ self . calibrated_vdda = vdda;
720
752
}
721
753
}
722
754
@@ -1365,14 +1397,8 @@ adc_pins!(
1365
1397
gpioc:: PC5 <Analog > => ( ADC1 , 15 ) ,
1366
1398
gpioc:: PC5 <Analog > => ( ADC2 , 15 ) ,
1367
1399
Temperature => ( ADC1 , 18 ) ,
1368
- Temperature => ( ADC2 , 18 ) ,
1369
- Temperature => ( ADC3 , 18 ) ,
1370
1400
Vbat => ( ADC1 , 18 ) ,
1371
- Vbat => ( ADC2 , 18 ) ,
1372
- Vbat => ( ADC3 , 18 ) ,
1373
1401
Vref => ( ADC1 , 17 ) ,
1374
- Vref => ( ADC2 , 17 ) ,
1375
- Vref => ( ADC3 , 17 ) ,
1376
1402
) ;
1377
1403
1378
1404
// Not available on V variant
@@ -1436,14 +1462,8 @@ adc_pins!(
1436
1462
gpioc:: PC5 <Analog > => ( ADC1 , 15 ) ,
1437
1463
gpioc:: PC5 <Analog > => ( ADC2 , 15 ) ,
1438
1464
Temperature => ( ADC1 , 18 ) ,
1439
- Temperature => ( ADC2 , 18 ) ,
1440
- Temperature => ( ADC3 , 18 ) ,
1441
1465
Vbat => ( ADC1 , 18 ) ,
1442
- Vbat => ( ADC2 , 18 ) ,
1443
- Vbat => ( ADC3 , 18 ) ,
1444
1466
Vref => ( ADC1 , 17 ) ,
1445
- Vref => ( ADC2 , 17 ) ,
1446
- Vref => ( ADC3 , 17 ) ,
1447
1467
) ;
1448
1468
1449
1469
// Not available on V variant
@@ -1502,14 +1522,8 @@ adc_pins!(
1502
1522
gpioc:: PC4 <Analog > => ( ADC1 , 14 ) ,
1503
1523
gpioc:: PC4 <Analog > => ( ADC2 , 14 ) ,
1504
1524
Temperature => ( ADC1 , 18 ) ,
1505
- Temperature => ( ADC2 , 18 ) ,
1506
- Temperature => ( ADC3 , 18 ) ,
1507
1525
Vbat => ( ADC1 , 18 ) ,
1508
- Vbat => ( ADC2 , 18 ) ,
1509
- Vbat => ( ADC3 , 18 ) ,
1510
1526
Vref => ( ADC1 , 17 ) ,
1511
- Vref => ( ADC2 , 17 ) ,
1512
- Vref => ( ADC3 , 17 ) ,
1513
1527
) ;
1514
1528
1515
1529
// Not available on M variant
@@ -1569,14 +1583,8 @@ adc_pins!(
1569
1583
gpioc:: PC1 <Analog > => ( ADC2 , 11 ) ,
1570
1584
gpioc:: PC1 <Analog > => ( ADC3 , 11 ) ,
1571
1585
Temperature => ( ADC1 , 18 ) ,
1572
- Temperature => ( ADC2 , 18 ) ,
1573
- Temperature => ( ADC3 , 18 ) ,
1574
1586
Vbat => ( ADC1 , 18 ) ,
1575
- Vbat => ( ADC2 , 18 ) ,
1576
- Vbat => ( ADC3 , 18 ) ,
1577
1587
Vref => ( ADC1 , 17 ) ,
1578
- Vref => ( ADC2 , 17 ) ,
1579
- Vref => ( ADC3 , 17 ) ,
1580
1588
) ;
1581
1589
1582
1590
// Not available on A variant
0 commit comments