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