aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/adc/v2.rs46
-rw-r--r--examples/stm32f7/src/bin/adc.rs26
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 @@
1use crate::adc::{AdcPin, Instance}; 1use crate::adc::{AdcPin, Instance};
2use crate::time::Hertz;
2use core::marker::PhantomData; 3use core::marker::PhantomData;
3use embassy::util::Unborrow; 4use embassy::util::Unborrow;
4use embassy_hal_common::unborrow; 5use embassy_hal_common::unborrow;
@@ -6,12 +7,12 @@ use embedded_hal_02::blocking::delay::DelayUs;
6 7
7pub const VDDA_CALIB_MV: u32 = 3000; 8pub const VDDA_CALIB_MV: u32 = 3000;
8 9
9#[cfg(not(rcc_f4))] 10#[cfg(not(any(rcc_f4, rcc_f7)))]
10fn enable() { 11fn enable() {
11 todo!() 12 todo!()
12} 13}
13 14
14#[cfg(rcc_f4)] 15#[cfg(any(rcc_f4, rcc_f7))]
15fn enable() { 16fn 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
118enum Prescaler {
119 Div2,
120 Div4,
121 Div6,
122 Div8,
123}
124
125impl 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
117pub struct Adc<'d, T: Instance> { 151pub 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
5use defmt_rtt as _; // global logger
6use panic_probe as _;
7
8use defmt::*;
9use embassy::executor::Spawner;
10use embassy::time::{Delay, Duration, Timer};
11use embassy_stm32::adc::Adc;
12use embassy_stm32::Peripherals;
13
14#[embassy::main]
15async 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}