diff options
| -rw-r--r-- | embassy-stm32/src/adc/v2.rs | 46 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/adc.rs | 26 |
2 files changed, 70 insertions, 2 deletions
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index d2429b111..ab71c0f52 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | use crate::adc::{AdcPin, Instance}; | 1 | use crate::adc::{AdcPin, Instance}; |
| 2 | use crate::time::Hertz; | ||
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use embassy::util::Unborrow; | 4 | use embassy::util::Unborrow; |
| 4 | use embassy_hal_common::unborrow; | 5 | use embassy_hal_common::unborrow; |
| @@ -6,12 +7,12 @@ use embedded_hal_02::blocking::delay::DelayUs; | |||
| 6 | 7 | ||
| 7 | pub const VDDA_CALIB_MV: u32 = 3000; | 8 | pub const VDDA_CALIB_MV: u32 = 3000; |
| 8 | 9 | ||
| 9 | #[cfg(not(rcc_f4))] | 10 | #[cfg(not(any(rcc_f4, rcc_f7)))] |
| 10 | fn enable() { | 11 | fn enable() { |
| 11 | todo!() | 12 | todo!() |
| 12 | } | 13 | } |
| 13 | 14 | ||
| 14 | #[cfg(rcc_f4)] | 15 | #[cfg(any(rcc_f4, rcc_f7))] |
| 15 | fn enable() { | 16 | fn enable() { |
| 16 | critical_section::with(|_| unsafe { | 17 | critical_section::with(|_| unsafe { |
| 17 | // TODO do not enable all adc clocks if not needed | 18 | // TODO do not enable all adc clocks if not needed |
| @@ -114,6 +115,39 @@ impl Default for SampleTime { | |||
| 114 | } | 115 | } |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 118 | enum Prescaler { | ||
| 119 | Div2, | ||
| 120 | Div4, | ||
| 121 | Div6, | ||
| 122 | Div8, | ||
| 123 | } | ||
| 124 | |||
| 125 | impl Prescaler { | ||
| 126 | fn from_pclk2(freq: Hertz) -> Self { | ||
| 127 | // Datasheet for both F4 and F7 specifies min frequency 0.6 MHz, typ freq. 30 MHz and max 36 MHz. | ||
| 128 | const MAX_FREQUENCY: Hertz = Hertz(36_000_000); | ||
| 129 | let raw_div = freq.0 / MAX_FREQUENCY.0; | ||
| 130 | match raw_div { | ||
| 131 | 0..=1 => Self::Div2, | ||
| 132 | 2..=3 => Self::Div4, | ||
| 133 | 4..=5 => Self::Div6, | ||
| 134 | 6..=7 => Self::Div8, | ||
| 135 | _ => panic!( | ||
| 136 | "Selected PCLK2 frequency is too high for ADC with largest possible prescaler." | ||
| 137 | ), | ||
| 138 | } | ||
| 139 | } | ||
| 140 | |||
| 141 | fn adcpre(&self) -> crate::pac::adccommon::vals::Adcpre { | ||
| 142 | match self { | ||
| 143 | Prescaler::Div2 => crate::pac::adccommon::vals::Adcpre::DIV2, | ||
| 144 | Prescaler::Div4 => crate::pac::adccommon::vals::Adcpre::DIV4, | ||
| 145 | Prescaler::Div6 => crate::pac::adccommon::vals::Adcpre::DIV6, | ||
| 146 | Prescaler::Div8 => crate::pac::adccommon::vals::Adcpre::DIV8, | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 117 | pub struct Adc<'d, T: Instance> { | 151 | pub struct Adc<'d, T: Instance> { |
| 118 | sample_time: SampleTime, | 152 | sample_time: SampleTime, |
| 119 | calibrated_vdda: u32, | 153 | calibrated_vdda: u32, |
| @@ -128,6 +162,14 @@ where | |||
| 128 | pub fn new(_peri: impl Unborrow<Target = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { | 162 | pub fn new(_peri: impl Unborrow<Target = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { |
| 129 | unborrow!(_peri); | 163 | unborrow!(_peri); |
| 130 | enable(); | 164 | enable(); |
| 165 | |||
| 166 | let presc = unsafe { Prescaler::from_pclk2(crate::rcc::get_freqs().apb2) }; | ||
| 167 | unsafe { | ||
| 168 | T::common_regs() | ||
| 169 | .ccr() | ||
| 170 | .modify(|w| w.set_adcpre(presc.adcpre())); | ||
| 171 | } | ||
| 172 | |||
| 131 | unsafe { | 173 | unsafe { |
| 132 | // disable before config is set | 174 | // disable before config is set |
| 133 | T::regs().cr2().modify(|reg| { | 175 | T::regs().cr2().modify(|reg| { |
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs new file mode 100644 index 000000000..87f5d30dd --- /dev/null +++ b/examples/stm32f7/src/bin/adc.rs | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt_rtt as _; // global logger | ||
| 6 | use panic_probe as _; | ||
| 7 | |||
| 8 | use defmt::*; | ||
| 9 | use embassy::executor::Spawner; | ||
| 10 | use embassy::time::{Delay, Duration, Timer}; | ||
| 11 | use embassy_stm32::adc::Adc; | ||
| 12 | use embassy_stm32::Peripherals; | ||
| 13 | |||
| 14 | #[embassy::main] | ||
| 15 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 16 | info!("Hello World!"); | ||
| 17 | |||
| 18 | let mut adc = Adc::new(p.ADC1, &mut Delay); | ||
| 19 | let mut pin = p.PA3; | ||
| 20 | |||
| 21 | loop { | ||
| 22 | let v = adc.read(&mut pin); | ||
| 23 | info!("--> {} - {} mV", v, adc.to_millivolts(v)); | ||
| 24 | Timer::after(Duration::from_millis(100)).await; | ||
| 25 | } | ||
| 26 | } | ||
