Skip to content

Commit bbe5abf

Browse files
committed
Fixing VDDA setting
1 parent bb214b6 commit bbe5abf

File tree

1 file changed

+93
-85
lines changed

1 file changed

+93
-85
lines changed

src/adc.rs

Lines changed: 93 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ pub mod config {
381381
pub(crate) dma: Dma,
382382
pub(crate) end_of_conversion_interrupt: Eoc,
383383
pub(crate) default_sample_time: SampleTime,
384+
pub(crate) vdda: Option<u32>,
384385
}
385386

386387
impl AdcConfig {
@@ -433,6 +434,19 @@ pub mod config {
433434
self.default_sample_time = default_sample_time;
434435
self
435436
}
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+
}
436450
}
437451

438452
impl Default for AdcConfig {
@@ -447,6 +461,7 @@ pub mod config {
447461
dma: Dma::Disabled,
448462
end_of_conversion_interrupt: Eoc::Disabled,
449463
default_sample_time: SampleTime::Cycles_480,
464+
vdda: None,
450465
}
451466
}
452467
}
@@ -606,9 +621,82 @@ impl<ADC> fmt::Debug for Adc<ADC> {
606621
}
607622

608623
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+
609694
($($adc_type:ident => ($constructor_fn_name:ident, $common_type:ident, $en_bit: expr)),+ $(,)*) => {
610695
$(
611696
impl Adc<pac::$adc_type> {
697+
698+
adc!(additionals: $adc_type => ($common_type));
699+
612700
/// Enables the ADC clock, resets the peripheral (optionally), runs calibration and applies the supplied config
613701
/// # Arguments
614702
/// * `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 {
628716
}
629717
}
630718

719+
let vdda = if let Some(vdda) = config.vdda { vdda } else { VDDA_CALIB };
720+
631721
let mut s = Self {
632722
config,
633723
adc_reg: adc,
634-
calibrated_vdda: VDDA_CALIB,
724+
calibrated_vdda: vdda,
635725
max_sample: 0,
636726
};
637727

@@ -656,67 +746,9 @@ macro_rules! adc {
656746
self.set_dma(config.dma);
657747
self.set_end_of_conversion_interrupt(config.end_of_conversion_interrupt);
658748
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();
665749

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;
720752
}
721753
}
722754

@@ -1365,14 +1397,8 @@ adc_pins!(
13651397
gpioc::PC5<Analog> => (ADC1, 15),
13661398
gpioc::PC5<Analog> => (ADC2, 15),
13671399
Temperature => (ADC1, 18),
1368-
Temperature => (ADC2, 18),
1369-
Temperature => (ADC3, 18),
13701400
Vbat => (ADC1, 18),
1371-
Vbat => (ADC2, 18),
1372-
Vbat => (ADC3, 18),
13731401
Vref => (ADC1, 17),
1374-
Vref => (ADC2, 17),
1375-
Vref => (ADC3, 17),
13761402
);
13771403

13781404
// Not available on V variant
@@ -1436,14 +1462,8 @@ adc_pins!(
14361462
gpioc::PC5<Analog> => (ADC1, 15),
14371463
gpioc::PC5<Analog> => (ADC2, 15),
14381464
Temperature => (ADC1, 18),
1439-
Temperature => (ADC2, 18),
1440-
Temperature => (ADC3, 18),
14411465
Vbat => (ADC1, 18),
1442-
Vbat => (ADC2, 18),
1443-
Vbat => (ADC3, 18),
14441466
Vref => (ADC1, 17),
1445-
Vref => (ADC2, 17),
1446-
Vref => (ADC3, 17),
14471467
);
14481468

14491469
// Not available on V variant
@@ -1502,14 +1522,8 @@ adc_pins!(
15021522
gpioc::PC4<Analog> => (ADC1, 14),
15031523
gpioc::PC4<Analog> => (ADC2, 14),
15041524
Temperature => (ADC1, 18),
1505-
Temperature => (ADC2, 18),
1506-
Temperature => (ADC3, 18),
15071525
Vbat => (ADC1, 18),
1508-
Vbat => (ADC2, 18),
1509-
Vbat => (ADC3, 18),
15101526
Vref => (ADC1, 17),
1511-
Vref => (ADC2, 17),
1512-
Vref => (ADC3, 17),
15131527
);
15141528

15151529
// Not available on M variant
@@ -1569,14 +1583,8 @@ adc_pins!(
15691583
gpioc::PC1<Analog> => (ADC2, 11),
15701584
gpioc::PC1<Analog> => (ADC3, 11),
15711585
Temperature => (ADC1, 18),
1572-
Temperature => (ADC2, 18),
1573-
Temperature => (ADC3, 18),
15741586
Vbat => (ADC1, 18),
1575-
Vbat => (ADC2, 18),
1576-
Vbat => (ADC3, 18),
15771587
Vref => (ADC1, 17),
1578-
Vref => (ADC2, 17),
1579-
Vref => (ADC3, 17),
15801588
);
15811589

15821590
// Not available on A variant

0 commit comments

Comments
 (0)