stm32wlxx_hal/adc.rs
1//! Analog to digital converter
2//!
3//! Quickstart:
4//!
5//! * [`Adc::pin`] Sample an analog pin
6//! * [`Adc::temperature`] Sample the junction temperature
7//! * [`Adc::vbat`] Sample the battery voltage
8#![cfg_attr(feature = "stm32wl5x_cm0p", allow(rustdoc::broken_intra_doc_links))]
9#![cfg_attr(feature = "stm32wl5x_cm0p", allow(dead_code))]
10#![cfg_attr(feature = "stm32wl5x_cm0p", allow(unused_imports))]
11
12#[cfg(not(feature = "stm32wl5x_cm0p"))]
13pub use pac::adc::cfgr2::{OVSR_A as OversampleRatio, OVSS_A as OversampleShift};
14
15use crate::gpio;
16use crate::Ratio;
17
18use super::pac;
19use core::{ptr::read_volatile, time::Duration};
20
21use embedded_hal::blocking::delay::DelayUs;
22
23// DS13293 rev 1 table 12
24// TS ADC raw data acquired at 30 °C (± 5 °C),
25// VDDA = VREF+ = 3.3 V (± 10 mV)
26fn ts_cal1() -> u16 {
27 unsafe { read_volatile(0x1FFF_75A8 as *const u16) }
28}
29
30// DS13293 rev 1 table 12
31// TS ADC raw data acquired at 130 °C (± 5 °C),
32// VDDA = VREF+ = 3.3 V (± 10 mV)
33fn ts_cal2() -> u16 {
34 unsafe { read_volatile(0x1FFF_75C8 as *const u16) }
35}
36
37fn ts_cal() -> (u16, u16) {
38 (ts_cal1(), ts_cal2())
39}
40
41const TS_CAL1_TEMP: i16 = 30;
42const TS_CAL2_TEMP: i16 = 130;
43const TS_CAL_TEMP_DELTA: i16 = TS_CAL2_TEMP - TS_CAL1_TEMP;
44
45/// t<sub>S_temp</sub> temperature sensor minimum sampling time
46///
47/// Value from DS13293 Rev 1 page 121 table 83 "TS characteristics"
48pub const TS_MIN_SAMPLE: Duration = Duration::from_micros(5);
49/// t<sub>START</sub> temperature sensor typical startup time when entering
50/// continuous mode
51///
52/// Value from DS13293 Rev 1 page 121 table 83 "TS characteristics"
53pub const TS_START_TYP: Duration = Duration::from_micros(70);
54/// t<sub>START</sub> temperature sensor maximum startup time when entering
55/// continuous mode
56///
57/// Value from DS13293 Rev 1 page 121 table 83 "TS characteristics"
58pub const TS_START_MAX: Duration = Duration::from_micros(120);
59
60/// t<sub>ADCVREG_SETUP</sub> ADC voltage regulator maximum startup time
61///
62/// Value from DS13293 Rev 1 page 117 table 80 "ADC characteristics"
63pub const T_ADCVREG_SETUP: Duration = Duration::from_micros(20);
64
65/// [`T_ADCVREG_SETUP`] expressed in microseconds
66///
67/// # Example
68///
69/// ```
70/// use stm32wlxx_hal::adc::{T_ADCVREG_SETUP, T_ADCVREG_SETUP_MICROS};
71///
72/// assert_eq!(
73/// u128::from(T_ADCVREG_SETUP_MICROS),
74/// T_ADCVREG_SETUP.as_micros()
75/// );
76/// ```
77pub const T_ADCVREG_SETUP_MICROS: u8 = T_ADCVREG_SETUP.as_micros() as u8;
78
79/// Mask of all valid channels
80///
81/// Channels 0-17, but without 15 and 16 because they are reserved.
82const CH_MASK: u32 = 0x27FFF;
83
84/// Interrupt masks
85///
86/// Used for [`Adc::set_isr`] and [`Adc::set_ier`].
87pub mod irq {
88 /// Channel configuration ready
89 pub const CCRDY: u32 = 1 << 13;
90 /// End of calibration
91 pub const EOCAL: u32 = 1 << 11;
92 /// Analog watchdog 3
93 pub const AWD3: u32 = 1 << 9;
94 /// Analog watchdog 2
95 pub const AWD2: u32 = 1 << 8;
96 /// Analog watchdog 1
97 pub const AWD1: u32 = 1 << 7;
98 /// Overrun
99 pub const OVR: u32 = 1 << 4;
100 /// End of conversion sequence
101 pub const EOS: u32 = 1 << 3;
102 /// End of conversion
103 pub const EOC: u32 = 1 << 2;
104 /// End of sampling
105 pub const EOSMP: u32 = 1 << 1;
106 /// ADC ready
107 pub const ADRDY: u32 = 1;
108
109 /// All IRQs
110 pub const ALL: u32 = CCRDY | EOCAL | AWD3 | AWD2 | AWD1 | OVR | EOS | EOC | EOSMP | ADRDY;
111}
112
113/// Internal voltage reference ADC calibration
114///
115/// This is raw ADC data acquired at 30 °C (± 5 °C).
116///
117/// V<sub>DDA</sub> = V<sub>REF+</sub> = 3.3 V (± 10mV)
118pub fn vref_cal() -> u16 {
119 // DS13293 rev 1 table 13
120 unsafe { read_volatile(0x1FFF_75AA as *const u16) }
121}
122
123/// ADC clock mode
124///
125/// In all synchronous clock modes, there is no jitter in the delay from a
126/// timer trigger to the start of a conversion.
127#[derive(Debug, PartialEq, Eq, Clone, Copy)]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub enum Clk {
130 /// Asynchronous clock mode HSI16
131 RccHsi,
132 /// Asynchronous clock mode PLLP
133 RccPllP,
134 /// Asynchronous clock mode SYSCLK
135 RccSysClk,
136 /// Synchronous clock mode, pclk/2
137 PClkDiv2,
138 /// Synchronous clock mode, pclk/4
139 PClkDiv4,
140 /// Synchronous clock mode, pclk
141 ///
142 /// This configuration must be enabled only if PCLK has a 50% duty clock
143 /// cycle (APB prescaler configured inside the RCC must be bypassed and
144 /// the system clock must by 50% duty cycle)
145 PClk,
146}
147
148#[cfg(not(feature = "stm32wl5x_cm0p"))]
149impl Clk {
150 const fn ckmode(&self) -> pac::adc::cfgr2::CKMODE_A {
151 match self {
152 Clk::RccHsi | Clk::RccPllP | Clk::RccSysClk => pac::adc::cfgr2::CKMODE_A::Adclk,
153 Clk::PClkDiv2 => pac::adc::cfgr2::CKMODE_A::PclkDiv2,
154 Clk::PClkDiv4 => pac::adc::cfgr2::CKMODE_A::PclkDiv4,
155 Clk::PClk => pac::adc::cfgr2::CKMODE_A::Pclk,
156 }
157 }
158
159 const fn adcsel(&self) -> pac::rcc::ccipr::ADCSEL_A {
160 match self {
161 Clk::RccHsi => pac::rcc::ccipr::ADCSEL_A::Hsi16,
162 Clk::RccPllP => pac::rcc::ccipr::ADCSEL_A::Pllp,
163 Clk::RccSysClk => pac::rcc::ccipr::ADCSEL_A::Sysclk,
164 _ => pac::rcc::ccipr::ADCSEL_A::NoClock,
165 }
166 }
167}
168
169/// ADC sample times
170#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
171#[repr(u8)]
172pub enum Ts {
173 /// 1.5 ADC clock cycles
174 Cyc1 = 0,
175 /// 3.5 ADC clock cycles
176 Cyc3 = 1,
177 /// 7.5 ADC clock cycles
178 Cyc7 = 2,
179 /// 12.5 ADC clock cycles
180 Cyc12 = 3,
181 /// 19.5 ADC clock cycles
182 Cyc19 = 4,
183 /// 39.5 ADC clock cycles
184 Cyc39 = 5,
185 /// 79.5 ADC clock cycles
186 Cyc79 = 6,
187 /// 160.5 ADC clock cycles
188 Cyc160 = 7,
189}
190
191impl Default for Ts {
192 /// Reset value of the sample time.
193 fn default() -> Self {
194 Ts::Cyc1
195 }
196}
197
198impl Ts {
199 /// Maximum sample time, 160.5 ADC clock cycles.
200 ///
201 /// # Example
202 ///
203 /// ```
204 /// use stm32wlxx_hal::adc::Ts;
205 ///
206 /// assert_eq!(Ts::MAX, Ts::Cyc160);
207 /// ```
208 pub const MAX: Self = Self::Cyc160;
209
210 /// Minimum sample time, 1.5 ADC clock cycles.
211 ///
212 /// # Example
213 ///
214 /// ```
215 /// use stm32wlxx_hal::adc::Ts;
216 ///
217 /// assert_eq!(Ts::MIN, Ts::Cyc1);
218 /// ```
219 pub const MIN: Self = Self::Cyc1;
220
221 /// Number of cycles.
222 ///
223 /// # Example
224 ///
225 /// ```
226 /// use stm32wlxx_hal::adc::Ts;
227 ///
228 /// assert!(f32::from(Ts::Cyc1.cycles()) - 1.5 < 0.001);
229 /// assert!(f32::from(Ts::Cyc3.cycles()) - 3.5 < 0.001);
230 /// assert!(f32::from(Ts::Cyc7.cycles()) - 7.5 < 0.001);
231 /// assert!(f32::from(Ts::Cyc12.cycles()) - 12.5 < 0.001);
232 /// assert!(f32::from(Ts::Cyc19.cycles()) - 19.5 < 0.001);
233 /// assert!(f32::from(Ts::Cyc39.cycles()) - 39.5 < 0.001);
234 /// assert!(f32::from(Ts::Cyc79.cycles()) - 79.5 < 0.001);
235 /// assert!(f32::from(Ts::Cyc160.cycles()) - 160.5 < 0.001);
236 /// ```
237 pub const fn cycles(&self) -> Ratio<u16> {
238 match self {
239 Ts::Cyc1 => Ratio::new_raw(3, 2),
240 Ts::Cyc3 => Ratio::new_raw(7, 2),
241 Ts::Cyc7 => Ratio::new_raw(15, 2),
242 Ts::Cyc12 => Ratio::new_raw(25, 2),
243 Ts::Cyc19 => Ratio::new_raw(39, 2),
244 Ts::Cyc39 => Ratio::new_raw(79, 2),
245 Ts::Cyc79 => Ratio::new_raw(159, 2),
246 Ts::Cyc160 => Ratio::new_raw(321, 2),
247 }
248 }
249
250 /// Get the cycles as a duration.
251 ///
252 /// Fractional nano-seconds are rounded towards zero.
253 ///
254 /// You can get the ADC frequency with [`Adc::clock_hz`].
255 ///
256 /// # Example
257 ///
258 /// Assuming the ADC clock frequency is 16 MHz.
259 ///
260 /// ```
261 /// use core::time::Duration;
262 /// use stm32wlxx_hal::adc::Ts;
263 ///
264 /// const FREQ: u32 = 16_000_000;
265 ///
266 /// assert_eq!(Ts::Cyc1.as_duration(FREQ), Duration::from_nanos(93));
267 /// assert_eq!(Ts::Cyc3.as_duration(FREQ), Duration::from_nanos(218));
268 /// assert_eq!(Ts::Cyc7.as_duration(FREQ), Duration::from_nanos(468));
269 /// assert_eq!(Ts::Cyc12.as_duration(FREQ), Duration::from_nanos(781));
270 /// assert_eq!(Ts::Cyc19.as_duration(FREQ), Duration::from_nanos(1_218));
271 /// assert_eq!(Ts::Cyc39.as_duration(FREQ), Duration::from_nanos(2_468));
272 /// assert_eq!(Ts::Cyc79.as_duration(FREQ), Duration::from_nanos(4_968));
273 /// assert_eq!(Ts::Cyc160.as_duration(FREQ), Duration::from_nanos(10_031));
274 /// ```
275 ///
276 /// [`Adc::clock_hz`]: crate::adc::Adc::clock_hz
277 pub const fn as_duration(&self, hz: u32) -> Duration {
278 let numer: u64 = (*self.cycles().numer() as u64).saturating_mul(1_000_000_000);
279 let denom: u64 = (*self.cycles().denom() as u64).saturating_mul(hz as u64);
280 Duration::from_nanos(numer / denom)
281 }
282}
283
284impl From<Ts> for u8 {
285 fn from(ts: Ts) -> Self {
286 ts as u8
287 }
288}
289
290impl From<Ts> for u32 {
291 fn from(ts: Ts) -> Self {
292 ts as u32
293 }
294}
295
296/// ADC channels
297#[derive(Debug, PartialEq, Eq, Clone, Copy)]
298#[repr(u8)]
299pub enum Ch {
300 /// ADC input 0.
301 ///
302 /// Connected to [`B13`](crate::gpio::pins::B13).
303 In0 = 0,
304 /// ADC input 1.
305 ///
306 /// Connected to [`B14`](crate::gpio::pins::B14).
307 In1 = 1,
308 /// ADC input 2.
309 ///
310 /// Connected to [`B3`](crate::gpio::pins::B3).
311 In2 = 2,
312 /// ADC input 3.
313 ///
314 /// Connected to [`B4`](crate::gpio::pins::B4).
315 In3 = 3,
316 /// ADC input 4.
317 ///
318 /// Connected to [`B2`](crate::gpio::pins::B2).
319 In4 = 4,
320 /// ADC input 5.
321 ///
322 /// Connected to [`B1`](crate::gpio::pins::B1).
323 In5 = 5,
324 /// ADC input 6.
325 ///
326 /// Connected to [`A10`](crate::gpio::pins::A10).
327 In6 = 6,
328 /// ADC input 7.
329 ///
330 /// Connected to [`A11`](crate::gpio::pins::A11).
331 In7 = 7,
332 /// ADC input 8.
333 ///
334 /// Connected to [`A12`](crate::gpio::pins::A12).
335 In8 = 8,
336 /// ADC input 9.
337 ///
338 /// Connected to [`A13`](crate::gpio::pins::A13).
339 In9 = 9,
340 /// ADC input 10.
341 ///
342 /// Connected to [`A14`](crate::gpio::pins::A14).
343 In10 = 10,
344 /// ADC input 11.
345 ///
346 /// Connected to [`A15`](crate::gpio::pins::A15).
347 In11 = 11,
348 /// Junction temperature sensor.
349 Vts = 12,
350 /// Internal voltage reference.
351 Vref = 13,
352 /// Battery voltage divided by 3.
353 Vbat = 14,
354 // 15, 16 are reserved
355 /// Digital to analog converter output.
356 ///
357 /// The DAC outputs to this internal pin only when configured to output to
358 /// chip peripherals.
359 Dac = 17,
360}
361
362impl Ch {
363 /// Bitmask of the channel.
364 ///
365 /// # Example
366 ///
367 /// ```
368 /// use stm32wlxx_hal::adc::Ch;
369 ///
370 /// assert_eq!(Ch::In0.mask(), 0x001);
371 /// assert_eq!(Ch::In8.mask(), 0x100);
372 /// ```
373 pub const fn mask(self) -> u32 {
374 1 << (self as u8)
375 }
376}
377
378/// Analog to digital converter driver.
379#[derive(Debug)]
380#[cfg(not(feature = "stm32wl5x_cm0p"))]
381pub struct Adc {
382 adc: pac::ADC,
383}
384
385#[cfg(not(feature = "stm32wl5x_cm0p"))]
386impl Adc {
387 /// Create a new ADC driver from a ADC peripheral.
388 ///
389 /// This will enable the ADC clock and reset the ADC peripheral.
390 ///
391 /// **Note:** This will select the clock source, but you are responsible
392 /// for enabling that clock source.
393 ///
394 /// # Example
395 ///
396 /// Initialize the ADC with HSI16.
397 ///
398 /// ```no_run
399 /// use stm32wlxx_hal::{
400 /// adc::{self, Adc},
401 /// pac,
402 /// };
403 ///
404 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
405 ///
406 /// // enable the HSI16 source clock
407 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
408 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
409 ///
410 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
411 /// ```
412 ///
413 /// Initialize the ADC with PCLK/4.
414 ///
415 /// ```no_run
416 /// use stm32wlxx_hal::{
417 /// adc::{self, Adc},
418 /// pac,
419 /// };
420 ///
421 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
422 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
423 /// ```
424 #[inline]
425 pub fn new(adc: pac::ADC, clk: Clk, rcc: &mut pac::RCC) -> Self {
426 unsafe { Self::pulse_reset(rcc) };
427 Self::enable_clock(rcc);
428 let mut adc: Self = Self { adc };
429 adc.set_clock_source(clk, rcc);
430 adc
431 }
432
433 /// Create a new ADC driver from an ADC peripheral without initialization.
434 ///
435 /// This is a slightly safer version of [`steal`](Self::steal).
436 ///
437 /// # Safety
438 ///
439 /// 1. Reset the ADC peripheral if determinism is required.
440 /// 2. Enable the ADC peripheral clock before using the ADC.
441 /// 3. Select the clock source if a non-default clock is required.
442 ///
443 /// # Example
444 ///
445 /// ```no_run
446 /// use stm32wlxx_hal::{
447 /// adc::{self, Adc},
448 /// pac,
449 /// };
450 ///
451 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
452 ///
453 /// // safety: nothing is using the peripheral
454 /// unsafe { Adc::pulse_reset(&mut dp.RCC) };
455 ///
456 /// Adc::enable_clock(&mut dp.RCC);
457 ///
458 /// // safety: ADC peripheral has been reset and clocks are enabled
459 /// let mut adc: Adc = unsafe { Adc::new_no_init(dp.ADC) };
460 ///
461 /// // select the ADC clock, optional
462 /// adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
463 /// ```
464 #[inline]
465 pub const unsafe fn new_no_init(adc: pac::ADC) -> Self {
466 Self { adc }
467 }
468
469 /// Free the ADC peripheral from the driver.
470 ///
471 /// # Example
472 ///
473 /// ```no_run
474 /// use stm32wlxx_hal::{
475 /// adc::{self, Adc},
476 /// pac,
477 /// };
478 ///
479 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
480 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
481 /// // ... use ADC
482 /// let adc: pac::ADC = adc.free();
483 /// ```
484 #[inline]
485 pub fn free(self) -> pac::ADC {
486 self.adc
487 }
488
489 /// Steal the ADC peripheral from whatever is currently using it.
490 ///
491 /// This will **not** initialize the ADC (unlike [`new`]).
492 ///
493 /// # Safety
494 ///
495 /// 1. Ensure that the code stealing the ADC has exclusive access to the
496 /// peripheral. Singleton checks are bypassed with this method.
497 /// 2. Reset the ADC peripheral if determinism is required.
498 /// 3. Enable the ADC peripheral clock before using the ADC.
499 /// 4. Select the clock source if a non-default clock is required.
500 ///
501 /// # Example
502 ///
503 /// ```no_run
504 /// use stm32wlxx_hal::{
505 /// adc::{self, Adc},
506 /// pac,
507 /// };
508 ///
509 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
510 /// let _: pac::ADC = dp.ADC;
511 ///
512 /// unsafe { Adc::pulse_reset(&mut dp.RCC) };
513 ///
514 /// Adc::enable_clock(&mut dp.RCC);
515 ///
516 /// let mut adc: Adc = unsafe { Adc::steal() };
517 ///
518 /// // select the ADC clock, optional
519 /// adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
520 /// ```
521 ///
522 /// [`new`]: Adc::new
523 #[inline]
524 pub unsafe fn steal() -> Adc {
525 Adc {
526 adc: pac::Peripherals::steal().ADC,
527 }
528 }
529
530 /// Set the ADC clock source.
531 ///
532 /// # Panics
533 ///
534 /// * (debug) ADC is enabled
535 ///
536 /// # Example
537 ///
538 /// ```no_run
539 /// use stm32wlxx_hal::{
540 /// adc::{self, Adc},
541 /// pac,
542 /// };
543 ///
544 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
545 /// let mut adc: Adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
546 ///
547 /// // change the clock source
548 /// adc.disable();
549 /// adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
550 /// ```
551 #[inline]
552 pub fn set_clock_source(&mut self, clk: Clk, rcc: &mut pac::RCC) {
553 debug_assert!(!self.is_enabled());
554 self.adc
555 .cfgr2
556 .modify(|_, w| w.ckmode().variant(clk.ckmode()));
557 rcc.ccipr.modify(|_, w| w.adcsel().variant(clk.adcsel()));
558 }
559
560 /// Get the ADC clock source.
561 ///
562 /// Returns `None` if the ADC is configured for an asynchronous clock,
563 /// but no asynchronous clock is selected.
564 ///
565 /// # Example
566 ///
567 /// ```no_run
568 /// use stm32wlxx_hal::{
569 /// adc::{self, Adc},
570 /// pac,
571 /// };
572 ///
573 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
574 /// let mut adc: Adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
575 ///
576 /// assert_eq!(adc.clock_source(&dp.RCC), Some(adc::Clk::PClkDiv4));
577 /// ```
578 pub fn clock_source(&self, rcc: &pac::RCC) -> Option<Clk> {
579 use pac::{adc::cfgr2::CKMODE_A, rcc::ccipr::ADCSEL_A};
580
581 match self.adc.cfgr2.read().ckmode().variant() {
582 CKMODE_A::Adclk => match rcc.ccipr.read().adcsel().variant() {
583 ADCSEL_A::NoClock => None,
584 ADCSEL_A::Hsi16 => Some(Clk::RccHsi),
585 ADCSEL_A::Pllp => Some(Clk::RccPllP),
586 ADCSEL_A::Sysclk => Some(Clk::RccSysClk),
587 },
588 CKMODE_A::PclkDiv2 => Some(Clk::PClkDiv2),
589 CKMODE_A::PclkDiv4 => Some(Clk::PClkDiv4),
590 CKMODE_A::Pclk => Some(Clk::PClk),
591 }
592 }
593
594 /// Disable the ADC clock.
595 ///
596 /// # Safety
597 ///
598 /// 1. Ensure nothing is using the ADC before disabling the clock.
599 /// 2. You are responsible for re-enabling the clock before using the ADC.
600 #[inline]
601 pub unsafe fn disable_clock(rcc: &mut pac::RCC) {
602 rcc.apb2enr.modify(|_, w| w.adcen().disabled());
603 }
604
605 /// Enable the ADC clock.
606 ///
607 /// [`new`](crate::adc::Adc::new) will enable clocks for you.
608 #[inline]
609 pub fn enable_clock(rcc: &mut pac::RCC) {
610 rcc.apb2enr.modify(|_, w| w.adcen().enabled());
611 rcc.apb2enr.read(); // delay after an RCC peripheral clock enabling
612 }
613
614 /// Pulse the ADC reset.
615 ///
616 /// [`new`](crate::adc::Adc::new) will pulse reset for you.
617 ///
618 /// # Safety
619 ///
620 /// 1. Ensure nothing is using the ADC before calling this function.
621 /// 2. You are responsible for setting up the ADC after a reset.
622 #[inline]
623 pub unsafe fn pulse_reset(rcc: &mut pac::RCC) {
624 rcc.apb2rstr.modify(|_, w| w.adcrst().set_bit());
625 rcc.apb2rstr.modify(|_, w| w.adcrst().clear_bit());
626 }
627
628 /// Calculate the ADC clock frequency in hertz.
629 ///
630 /// **Note:** If the ADC prescaler register erroneously returns a reserved
631 /// value the code will default to an ADC prescaler of 1.
632 ///
633 /// Fractional frequencies will be rounded towards zero.
634 ///
635 /// # Example
636 ///
637 /// ```no_run
638 /// use stm32wlxx_hal::{
639 /// adc::{self, Adc},
640 /// pac,
641 /// };
642 ///
643 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
644 ///
645 /// // enable the HSI16 source clock
646 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
647 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
648 ///
649 /// let adc: Adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
650 /// assert_eq!(adc.clock_hz(&dp.RCC), 16_000_000);
651 /// ```
652 pub fn clock_hz(&self, rcc: &pac::RCC) -> u32 {
653 use pac::{
654 adc::{ccr::PRESC_A, cfgr2::CKMODE_A},
655 rcc::ccipr::ADCSEL_A,
656 };
657
658 let source_freq: Ratio<u32> = match self.adc.cfgr2.read().ckmode().variant() {
659 CKMODE_A::Adclk => {
660 let src: Ratio<u32> = match rcc.ccipr.read().adcsel().variant() {
661 ADCSEL_A::NoClock => Ratio::new_raw(0, 1),
662 ADCSEL_A::Hsi16 => Ratio::new_raw(16_000_000, 1),
663 ADCSEL_A::Pllp => crate::rcc::pllpclk(rcc, &rcc.pllcfgr.read()),
664 ADCSEL_A::Sysclk => crate::rcc::sysclk(rcc, &rcc.cfgr.read()),
665 };
666
667 // only the asynchronous clocks have the prescaler applied
668 let ccr = self.adc.ccr.read();
669 let prescaler: u32 = match ccr.presc().variant() {
670 Some(p) => match p {
671 PRESC_A::Div1 => 1,
672 PRESC_A::Div2 => 2,
673 PRESC_A::Div4 => 4,
674 PRESC_A::Div6 => 6,
675 PRESC_A::Div8 => 8,
676 PRESC_A::Div10 => 10,
677 PRESC_A::Div12 => 12,
678 PRESC_A::Div16 => 16,
679 PRESC_A::Div32 => 32,
680 PRESC_A::Div64 => 64,
681 PRESC_A::Div128 => 128,
682 PRESC_A::Div256 => 256,
683 },
684 None => {
685 error!("Reserved ADC prescaler value {:#X}", ccr.presc().bits());
686 1
687 }
688 };
689
690 src / prescaler
691 }
692 CKMODE_A::PclkDiv2 => crate::rcc::pclk2(rcc, &rcc.cfgr.read()) / 2,
693 CKMODE_A::PclkDiv4 => crate::rcc::pclk2(rcc, &rcc.cfgr.read()) / 4,
694 CKMODE_A::Pclk => crate::rcc::pclk2(rcc, &rcc.cfgr.read()),
695 };
696
697 source_freq.to_integer()
698 }
699
700 /// Unmask the ADC IRQ in the NVIC.
701 ///
702 /// # Safety
703 ///
704 /// This can break mask-based critical sections.
705 ///
706 /// # Example
707 ///
708 /// ```no_run
709 /// # #[cfg(all(not(feature = "stm32wl5x_cm0p"), feature = "rt"))]
710 /// unsafe { stm32wlxx_hal::adc::Adc::unmask_irq() };
711 /// ```
712 #[cfg(feature = "rt")]
713 #[inline]
714 pub unsafe fn unmask_irq() {
715 pac::NVIC::unmask(pac::Interrupt::ADC)
716 }
717
718 /// Mask the ADC IRQ in the NVIC.
719 ///
720 /// # Example
721 ///
722 /// ```no_run
723 /// # #[cfg(all(not(feature = "stm32wl5x_cm0p"), feature = "rt"))]
724 /// unsafe { stm32wlxx_hal::adc::Adc::mask_irq() }
725 /// ```
726 #[cfg(feature = "rt")]
727 #[inline]
728 pub fn mask_irq() {
729 pac::NVIC::mask(pac::Interrupt::ADC)
730 }
731
732 /// Set sample times for **all** channels.
733 ///
734 /// For each bit in the mask:
735 ///
736 /// * `0`: Sample time is set by the `sel0` argument.
737 /// * `1`: Sample time is set by the `sel1` argument.
738 ///
739 /// # Panics
740 ///
741 /// * (debug) An ADC conversion is in-progress
742 ///
743 /// # Example
744 ///
745 /// Set ADC channels [`In0`] and [`In1`] (pins [`B13`] and [`B14`]
746 /// respectively) and the internal V<sub>BAT</sub> to a sample time of
747 /// 39.5 ADC clock cycles, and set all other channels to a sample time of
748 /// 160.5 clock cycles.
749 ///
750 /// ```no_run
751 /// use stm32wlxx_hal::{
752 /// self as hal,
753 /// adc::{self, Adc, Ts},
754 /// gpio::pins::{B13, B14},
755 /// pac,
756 /// };
757 ///
758 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
759 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
760 /// adc.set_sample_times(
761 /// B14::ADC_CH.mask() | B13::ADC_CH.mask() | adc::Ch::Vbat.mask(),
762 /// Ts::Cyc160,
763 /// Ts::Cyc39,
764 /// );
765 /// ```
766 ///
767 /// [`In0`]: crate::adc::Ch::In0
768 /// [`In1`]: crate::adc::Ch::In1
769 /// [`B13`]: crate::gpio::pins::B13
770 /// [`B14`]: crate::gpio::pins::B14
771 #[inline]
772 pub fn set_sample_times(&mut self, mask: u32, sel0: Ts, sel1: Ts) {
773 debug_assert!(self.adc.cr.read().adstart().is_not_active());
774 self.adc.smpr.write(|w| unsafe {
775 w.bits((mask & CH_MASK) << 8 | u32::from(sel1) << 4 | u32::from(sel0))
776 })
777 }
778
779 /// Sets all channels to the maximum sample time.
780 ///
781 /// This is a helper for testing and rapid prototyping purpose because
782 /// [`set_sample_times`](Adc::set_sample_times) is verbose.
783 ///
784 /// This method is equivalent to this:
785 ///
786 /// ```no_run
787 /// # let mut adc = unsafe { stm32wlxx_hal::adc::Adc::steal() };
788 /// use stm32wlxx_hal::adc::Ts;
789 ///
790 /// adc.set_sample_times(0, Ts::Cyc160, Ts::Cyc160);
791 /// ```
792 ///
793 /// # Example
794 ///
795 /// ```no_run
796 /// use stm32wlxx_hal::{
797 /// adc::{self, Adc},
798 /// pac,
799 /// };
800 ///
801 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
802 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
803 /// adc.set_max_sample_time();
804 /// ```
805 #[inline]
806 pub fn set_max_sample_time(&mut self) {
807 self.set_sample_times(0, Ts::Cyc160, Ts::Cyc160);
808 }
809
810 /// Clear interrupts.
811 ///
812 /// # Example
813 ///
814 /// Clear all interrupts.
815 ///
816 /// ```no_run
817 /// use stm32wlxx_hal::{
818 /// adc::{self, Adc},
819 /// pac,
820 /// };
821 ///
822 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
823 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
824 /// adc.set_isr(adc::irq::ALL);
825 /// ```
826 #[inline]
827 pub fn set_isr(&mut self, isr: u32) {
828 // saftey: reserved bits are masked and will be held at reset value
829 self.adc.isr.write(|w| unsafe { w.bits(isr & irq::ALL) })
830 }
831
832 /// Read the interrupt status.
833 ///
834 /// # Example
835 ///
836 /// Check if the ADC is ready.
837 ///
838 /// ```no_run
839 /// use stm32wlxx_hal::{
840 /// adc::{self, Adc},
841 /// pac,
842 /// };
843 ///
844 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
845 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
846 /// // this will be false because the ADC is not enabled
847 /// let ready: bool = Adc::isr().adrdy().is_ready();
848 /// ```
849 #[inline]
850 pub fn isr() -> pac::adc::isr::R {
851 // saftey: atomic read with no side-effects
852 unsafe { (*pac::ADC::PTR).isr.read() }
853 }
854
855 /// Enable and disable interrupts.
856 ///
857 /// # Example
858 ///
859 /// Enable all IRQs
860 ///
861 /// ```no_run
862 /// use stm32wlxx_hal::{
863 /// adc::{self, Adc},
864 /// pac,
865 /// };
866 ///
867 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
868 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
869 /// adc.set_ier(adc::irq::ALL);
870 /// ```
871 #[inline]
872 pub fn set_ier(&mut self, ier: u32) {
873 // saftey: reserved bits are masked and will be held at reset value
874 self.adc.ier.write(|w| unsafe { w.bits(ier & irq::ALL) })
875 }
876
877 /// Configure the channel sequencer.
878 ///
879 /// This is advanced ADC usage, most of the time you will want to use a
880 /// one of the available sample methods that will configure this.
881 ///
882 /// * [`pin`](Self::pin)
883 /// * [`temperature`](Self::temperature)
884 /// * [`vbat`](Self::vbat)
885 ///
886 /// This will not poll for completion, when this method returns the channel
887 /// configuration may not be ready.
888 ///
889 /// # Panics
890 ///
891 /// * (debug) ADC conversion is in-progress.
892 ///
893 /// # Example
894 ///
895 /// Select the ADC V<sub>BAT</sub> channel.
896 ///
897 /// ```no_run
898 /// use stm32wlxx_hal::{
899 /// adc::{self, Adc},
900 /// pac,
901 /// };
902 ///
903 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
904 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
905 /// adc.start_chsel(adc::Ch::Vbat.mask());
906 /// while Adc::isr().ccrdy().is_not_complete() {}
907 /// ```
908 #[inline]
909 pub fn start_chsel(&mut self, ch: u32) {
910 debug_assert!(self.adc.cr.read().adstart().is_not_active());
911 // See section 18.3.8 page 542 "Channel selection"
912 // saftey: reserved bits are masked and will be held at reset value
913 self.adc
914 .chselr0()
915 .write(|w| unsafe { w.chsel().bits(ch & CH_MASK) });
916 }
917
918 #[inline]
919 fn cfg_ch_seq(&mut self, ch: u32) {
920 self.start_chsel(ch);
921 while self.adc.isr.read().ccrdy().is_not_complete() {}
922 }
923
924 /// Start an ADC conversion.
925 ///
926 /// This is advanced ADC usage, most of the time you will want to use a
927 /// one of the available sample methods that will configure this.
928 ///
929 /// * [`pin`](Self::pin)
930 /// * [`temperature`](Self::temperature)
931 /// * [`vbat`](Self::vbat)
932 ///
933 /// This will not poll for completion, when this method returns the AD
934 /// conversion may not be complete.
935 ///
936 /// # Panics
937 ///
938 /// * (debug) ADC is not enabled
939 /// * (debug) ADC has a pending disable request
940 ///
941 /// # Example
942 ///
943 /// See [`data`](Self::data).
944 #[inline]
945 pub fn start_conversion(&mut self) {
946 debug_assert!(self.is_enabled());
947 debug_assert!(self.adc.cr.read().addis().is_not_disabling());
948 self.adc.cr.write(|w| w.adstart().start_conversion());
949 }
950
951 /// Stop an ADC conversion if there is one in-progress.
952 pub fn stop_conversion(&mut self) {
953 if self.adc.cr.read().adstart().is_active() {
954 self.adc.cr.write(|w| w.adstp().stop_conversion());
955 while self.adc.cr.read().adstp().bit_is_set() {}
956 }
957 }
958
959 /// Read the ADC conversion data.
960 ///
961 /// This is advanced ADC usage, most of the time you will want to use a
962 /// one of the available sample methods.
963 ///
964 /// * [`pin`](Self::pin)
965 /// * [`temperature`](Self::temperature)
966 /// * [`vbat`](Self::vbat)
967 ///
968 /// # Example
969 ///
970 /// Read the ADC V<sub>BAT</sub> channel.
971 ///
972 /// ```no_run
973 /// use stm32wlxx_hal::{
974 /// adc::{self, Adc},
975 /// pac,
976 /// util::new_delay,
977 /// };
978 ///
979 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
980 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
981 ///
982 /// // enable the HSI16 source clock
983 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
984 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
985 ///
986 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
987 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
988 ///
989 /// // calibrate the ADC before it is enabled
990 /// adc.calibrate(&mut delay);
991 ///
992 /// // enable the ADC
993 /// adc.enable();
994 ///
995 /// // set the sample times to the maximum (160.5 ADC cycles)
996 /// adc.set_max_sample_time();
997 ///
998 /// // select the Vbat channel and poll for completion
999 /// adc.start_chsel(adc::Ch::Vbat.mask());
1000 /// while Adc::isr().ccrdy().is_not_complete() {}
1001 ///
1002 /// // start the conversion and poll for completion
1003 /// adc.start_conversion();
1004 /// while Adc::isr().eoc().is_not_complete() {}
1005 ///
1006 /// // read the ADC data
1007 /// let vbat: u16 = adc.data();
1008 /// ```
1009 #[inline]
1010 pub fn data(&self) -> u16 {
1011 self.adc.dr.read().data().bits()
1012 }
1013
1014 fn poll_data(&self) -> u16 {
1015 while self.adc.isr.read().eoc().is_not_complete() {}
1016 let data: u16 = self.data();
1017 self.adc.isr.write(|w| w.eoc().set_bit());
1018 data
1019 }
1020
1021 /// Enable the temperature sensor.
1022 ///
1023 /// You **MUST** wait for the temperature sensor to start up
1024 /// ([`TS_START_TYP`] or [`TS_START_MAX`])
1025 /// before the samples will be accurate.
1026 ///
1027 /// # Example
1028 ///
1029 /// ```no_run
1030 /// use stm32wlxx_hal::{
1031 /// adc::{self, Adc},
1032 /// pac, rcc,
1033 /// util::new_delay,
1034 /// };
1035 ///
1036 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1037 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1038 ///
1039 /// // enable the HSI16 source clock
1040 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1041 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1042 ///
1043 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1044 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1045 /// adc.enable_tsen();
1046 /// // wait for the temperature sensor to startup
1047 /// delay.delay_us(adc::TS_START_MAX.as_micros() as u32);
1048 /// ```
1049 #[inline]
1050 pub fn enable_tsen(&mut self) {
1051 self.adc.ccr.modify(|_, w| w.tsen().enabled())
1052 }
1053
1054 /// Disable the temperature sensor.
1055 #[inline]
1056 pub fn disable_tsen(&mut self) {
1057 self.adc.ccr.modify(|_, w| w.tsen().disabled())
1058 }
1059
1060 /// Returns `true` if the temperature sensor is enabled.
1061 #[inline]
1062 #[must_use]
1063 pub fn is_tsen_enabled(&mut self) -> bool {
1064 self.adc.ccr.read().tsen().is_enabled()
1065 }
1066
1067 /// Get the junction temperature.
1068 ///
1069 /// # Panics
1070 ///
1071 /// * (debug) ADC is not enabled
1072 /// * (debug) ADC has a pending disable request
1073 /// * (debug) Temperature sensor is not enabled
1074 ///
1075 /// # Sample Time
1076 ///
1077 /// You must set a sampling time with
1078 /// [`set_sample_times`](Adc::set_sample_times) greater than or equal to
1079 /// [`TS_MIN_SAMPLE`] before calling this method.
1080 /// When in doubt use the maximum sampling time, [`Ts::Cyc160`].
1081 ///
1082 /// # Calibration
1083 ///
1084 /// The temperature calibration provided on-chip appears to be for an
1085 /// uncalibrated ADC, though I can find no mention of this in the
1086 /// datasheet.
1087 ///
1088 /// If the ADC has been calibrated with [`calibrate`] the calibration offset
1089 /// will be removed from the sample.
1090 ///
1091 /// # Example
1092 ///
1093 /// ```no_run
1094 /// use stm32wlxx_hal::{
1095 /// adc::{self, Adc},
1096 /// pac, rcc,
1097 /// util::new_delay,
1098 /// };
1099 ///
1100 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1101 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1102 ///
1103 /// // enable the HSI16 source clock
1104 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1105 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1106 ///
1107 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1108 ///
1109 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1110 /// adc.enable();
1111 /// adc.enable_tsen();
1112 /// delay.delay_us(adc::TS_START_MAX.as_micros() as u32);
1113 /// adc.set_max_sample_time();
1114 ///
1115 /// let tj: i16 = adc.temperature().to_integer();
1116 /// ```
1117 ///
1118 /// [`calibrate`]: crate::adc::Adc::calibrate
1119 pub fn temperature(&mut self) -> Ratio<i16> {
1120 debug_assert!(self.is_enabled());
1121 debug_assert!(self.is_tsen_enabled());
1122
1123 self.cfg_ch_seq(Ch::Vts.mask());
1124 self.start_conversion();
1125
1126 let (ts_cal1, ts_cal2): (u16, u16) = ts_cal();
1127 let ret: Ratio<i16> =
1128 Ratio::new_raw(TS_CAL_TEMP_DELTA, ts_cal2.wrapping_sub(ts_cal1) as i16);
1129
1130 let calfact: u8 = self.adc.calfact.read().calfact().bits();
1131 let ts_data: u16 = self.poll_data().saturating_add(u16::from(calfact));
1132
1133 ret * (ts_data.wrapping_sub(ts_cal1) as i16) + TS_CAL1_TEMP
1134 }
1135
1136 /// Enable the internal voltage reference.
1137 #[inline]
1138 pub fn enable_vref(&mut self) {
1139 self.adc.ccr.modify(|_, w| w.vrefen().enabled())
1140 }
1141
1142 /// Disable the internal voltage reference.
1143 #[inline]
1144 pub fn disable_vref(&mut self) {
1145 self.adc.ccr.modify(|_, w| w.vrefen().disabled())
1146 }
1147
1148 /// Returns `true` if the internal voltage reference is enabled.
1149 #[inline]
1150 #[must_use]
1151 pub fn is_vref_enabled(&mut self) -> bool {
1152 self.adc.ccr.read().vrefen().is_enabled()
1153 }
1154
1155 /// Enable oversampling.
1156 ///
1157 /// # Panics
1158 ///
1159 /// * (debug) ADC is enabled
1160 #[inline]
1161 #[cfg(not(feature = "stm32wl5x_cm0p"))]
1162 pub fn enable_oversampling(&mut self, ratio: OversampleRatio, shift: OversampleShift) {
1163 debug_assert!(!self.is_enabled());
1164 self.adc.cfgr2.modify(|_, w| {
1165 w.ovse()
1166 .enabled()
1167 .ovsr()
1168 .variant(ratio)
1169 .ovss()
1170 .variant(shift)
1171 })
1172 }
1173
1174 /// Disables oversampling.
1175 ///
1176 /// # Panics
1177 ///
1178 /// * (debug) ADC is enabled
1179 #[inline]
1180 pub fn disable_oversampling(&mut self) {
1181 debug_assert!(!self.is_enabled());
1182 self.adc.cfgr2.modify(|_, w| w.ovse().disabled())
1183 }
1184
1185 /// Returns `true` if oversampling is enabled.
1186 #[inline]
1187 #[must_use]
1188 pub fn is_oversampling_enabled(&mut self) -> bool {
1189 self.adc.cfgr2.read().ovse().is_enabled()
1190 }
1191
1192 /// Read the internal voltage reference.
1193 ///
1194 /// # Panics
1195 ///
1196 /// * (debug) ADC is not enabled
1197 /// * (debug) ADC has a pending disable request
1198 /// * (debug) Voltage reference is not enabled
1199 ///
1200 /// # Example
1201 ///
1202 /// ```no_run
1203 /// use stm32wlxx_hal::{
1204 /// adc::{self, Adc},
1205 /// pac, rcc,
1206 /// util::new_delay,
1207 /// };
1208 ///
1209 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1210 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1211 ///
1212 /// // enable the HSI16 source clock
1213 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1214 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1215 ///
1216 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1217 ///
1218 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1219 /// adc.calibrate(&mut delay);
1220 /// adc.set_max_sample_time();
1221 /// adc.enable();
1222 /// adc.enable_vref();
1223 ///
1224 /// let vref: u16 = adc.vref();
1225 /// let vref_cal: u16 = adc::vref_cal();
1226 /// let error: i16 = ((vref as i16) - (vref_cal as i16)).abs();
1227 /// assert!(error < 10);
1228 /// ```
1229 pub fn vref(&mut self) -> u16 {
1230 debug_assert!(self.is_enabled());
1231 debug_assert!(self.is_vref_enabled());
1232 self.cfg_ch_seq(Ch::Vref.mask());
1233 self.start_conversion();
1234 self.poll_data()
1235 }
1236
1237 /// Sample the DAC output.
1238 ///
1239 /// The DAC must be configured to output to chip peripherals for this to
1240 /// work as expected.
1241 ///
1242 /// # Panics
1243 ///
1244 /// * (debug) ADC is not enabled
1245 /// * (debug) ADC has a pending disable request
1246 ///
1247 /// # Example
1248 ///
1249 /// ```no_run
1250 /// use stm32wlxx_hal::{
1251 /// adc::{self, Adc},
1252 /// dac::{Dac, ModeChip},
1253 /// pac, rcc,
1254 /// util::new_delay,
1255 /// };
1256 ///
1257 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1258 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1259 ///
1260 /// // enable the HSI16 source clock
1261 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1262 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1263 ///
1264 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1265 ///
1266 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1267 /// adc.calibrate(&mut delay);
1268 /// adc.set_max_sample_time();
1269 ///
1270 /// let mut dac: Dac = Dac::new(dp.DAC, &mut dp.RCC);
1271 /// dac.set_mode_chip(ModeChip::Norm);
1272 ///
1273 /// dac.setup_soft_trigger();
1274 /// dac.soft_trigger(1234);
1275 /// // should be in the same ballpark as the DAC output
1276 /// let sample: u16 = adc.dac();
1277 /// ```
1278 pub fn dac(&mut self) -> u16 {
1279 debug_assert!(self.is_enabled());
1280 self.cfg_ch_seq(Ch::Dac.mask());
1281 self.start_conversion();
1282 self.poll_data()
1283 }
1284
1285 /// Sample a GPIO pin.
1286 ///
1287 /// # Panics
1288 ///
1289 /// * (debug) ADC is not enabled
1290 /// * (debug) ADC has a pending disable request
1291 ///
1292 /// # Example
1293 ///
1294 /// ```no_run
1295 /// use stm32wlxx_hal::{
1296 /// adc::{self, Adc},
1297 /// gpio::{pins::B4, Analog, PortB},
1298 /// pac, rcc,
1299 /// util::new_delay,
1300 /// };
1301 ///
1302 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1303 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1304 ///
1305 /// // enable the HSI16 source clock
1306 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1307 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1308 ///
1309 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1310 ///
1311 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1312 /// adc.calibrate(&mut delay);
1313 /// adc.set_max_sample_time();
1314 /// adc.enable();
1315 ///
1316 /// let gpiob: PortB = PortB::split(dp.GPIOB, &mut dp.RCC);
1317 /// let b4: Analog<B4> = cortex_m::interrupt::free(|cs| Analog::new(gpiob.b4, cs));
1318 ///
1319 /// let sample: u16 = adc.pin(&b4);
1320 /// ```
1321 #[allow(unused_variables)]
1322 pub fn pin<P: gpio::sealed::AdcCh>(&mut self, pin: &gpio::Analog<P>) -> u16 {
1323 debug_assert!(self.is_enabled());
1324 self.cfg_ch_seq(P::ADC_CH.mask());
1325 self.start_conversion();
1326 self.poll_data()
1327 }
1328
1329 /// Enable V<sub>BAT</sub>.
1330 ///
1331 /// To prevent any unwanted consumption on the battery, it is recommended to
1332 /// enable the bridge divider only when needed for ADC conversion.
1333 #[inline]
1334 pub fn enable_vbat(&mut self) {
1335 self.adc.ccr.modify(|_, w| w.vbaten().enabled())
1336 }
1337
1338 /// Disable V<sub>BAT</sub>.
1339 #[inline]
1340 pub fn disable_vbat(&mut self) {
1341 self.adc.ccr.modify(|_, w| w.vbaten().disabled());
1342 }
1343
1344 /// Returns `true` if V<sub>BAT</sub> is enabled.
1345 #[inline]
1346 #[must_use]
1347 pub fn is_vbat_enabled(&self) -> bool {
1348 self.adc.ccr.read().vbaten().is_enabled()
1349 }
1350
1351 /// Sample the V<sub>BAT</sub> pin.
1352 ///
1353 /// This is internally connected to a bridge divider, the converted digital
1354 /// value is a third the V<sub>BAT</sub> voltage.
1355 ///
1356 /// # Panics
1357 ///
1358 /// * (debug) ADC is not enabled
1359 /// * (debug) ADC has a pending disable request
1360 /// * (debug) V<sub>BAT</sub> is not enabled
1361 ///
1362 /// # Example
1363 ///
1364 /// ```no_run
1365 /// use stm32wlxx_hal::{
1366 /// self as hal,
1367 /// adc::{self, Adc},
1368 /// dac::{Dac, ModeChip},
1369 /// pac, rcc,
1370 /// util::new_delay,
1371 /// };
1372 ///
1373 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1374 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1375 ///
1376 /// // enable the HSI16 source clock
1377 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1378 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1379 ///
1380 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1381 ///
1382 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1383 /// adc.calibrate(&mut delay);
1384 ///
1385 /// adc.enable();
1386 /// adc.enable_vbat();
1387 /// adc.set_max_sample_time();
1388 /// let sample: u16 = adc.vbat();
1389 /// ```
1390 pub fn vbat(&mut self) -> u16 {
1391 debug_assert!(self.is_enabled());
1392 debug_assert!(self.is_vbat_enabled());
1393 self.cfg_ch_seq(Ch::Vbat.mask());
1394 self.start_conversion();
1395 self.poll_data()
1396 }
1397}
1398
1399// on-off control
1400// see RM0453 rev 1 section 18.3.4 page 537
1401#[cfg(not(feature = "stm32wl5x_cm0p"))]
1402impl Adc {
1403 /// Returns `true` if the ADC is enabled.
1404 ///
1405 /// # Example
1406 ///
1407 /// ```no_run
1408 /// use stm32wlxx_hal::{
1409 /// adc::{self, Adc},
1410 /// pac,
1411 /// };
1412 ///
1413 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1414 ///
1415 /// // enable the HSI16 source clock
1416 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1417 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1418 ///
1419 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1420 /// assert_eq!(adc.is_enabled(), false);
1421 /// ```
1422 #[inline]
1423 #[must_use]
1424 pub fn is_enabled(&self) -> bool {
1425 self.adc.cr.read().aden().bit_is_set()
1426 }
1427
1428 /// Returns `true` if an ADC disable command is in-progress.
1429 #[inline]
1430 #[must_use]
1431 pub fn disable_in_progress(&self) -> bool {
1432 self.adc.cr.read().addis().bit_is_set()
1433 }
1434
1435 /// Returns `true` if the ADC is disabled, and there is no disable command
1436 /// in-progress.
1437 ///
1438 /// # Example
1439 ///
1440 /// ```no_run
1441 /// use stm32wlxx_hal::{
1442 /// adc::{self, Adc},
1443 /// pac,
1444 /// };
1445 ///
1446 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1447 ///
1448 /// // enable the HSI16 source clock
1449 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1450 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1451 ///
1452 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1453 /// assert_eq!(adc.is_disabled(), true);
1454 /// ```
1455 #[inline]
1456 #[must_use]
1457 pub fn is_disabled(&self) -> bool {
1458 let cr = self.adc.cr.read();
1459 cr.aden().bit_is_clear() && cr.addis().bit_is_clear()
1460 }
1461
1462 /// Start the ADC enable procedure.
1463 ///
1464 /// This is advanced ADC usage, most of the time you will want to use
1465 /// [`enable`](Self::enable).
1466 ///
1467 /// This will not poll for completion, when this method returns the ADC
1468 /// may not be enabled.
1469 ///
1470 /// The method returns `true` if the caller function should poll for
1471 /// completion (the ADC was not already enabled),
1472 /// if the ADC was already enabled and the ADRDY interrupt was cleared then
1473 /// the ADRDY bit will **not** be set again after calling this method
1474 /// which can lead to polling loops that will never terminate.
1475 ///
1476 /// # Example
1477 ///
1478 /// ```no_run
1479 /// use stm32wlxx_hal::{
1480 /// adc::{self, Adc},
1481 /// pac,
1482 /// };
1483 ///
1484 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1485 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
1486 /// if adc.start_enable() {
1487 /// while Adc::isr().adrdy().is_not_ready() {}
1488 /// }
1489 /// ```
1490 #[inline]
1491 #[must_use = "the return value indicates if you should wait for completion"]
1492 pub fn start_enable(&mut self) -> bool {
1493 if self.adc.cr.read().aden().is_disabled() {
1494 self.adc.isr.write(|w| w.adrdy().set_bit());
1495 self.adc.cr.write(|w| w.aden().set_bit());
1496 true
1497 } else {
1498 false
1499 }
1500 }
1501
1502 /// Enable the ADC and poll for completion.
1503 ///
1504 /// # Example
1505 ///
1506 /// ```no_run
1507 /// use stm32wlxx_hal::{
1508 /// adc::{self, Adc},
1509 /// pac,
1510 /// };
1511 ///
1512 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1513 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
1514 /// adc.enable();
1515 /// ```
1516 #[inline]
1517 pub fn enable(&mut self) {
1518 if self.start_enable() {
1519 while self.adc.isr.read().adrdy().is_not_ready() {}
1520 }
1521 }
1522
1523 /// Start the ADC disable procedure.
1524 ///
1525 /// This is advanced ADC usage, most of the time you will want to use
1526 /// [`disable`](Self::disable).
1527 ///
1528 /// This will not poll for completion, when this function returns the ADC
1529 /// may not be disabled.
1530 ///
1531 /// This will stop any conversions in-progress.
1532 ///
1533 /// The ADC takes about 20 CPU cycles to disable with a 48MHz sysclk and
1534 /// the ADC on the 16MHz HSI clock.
1535 ///
1536 /// # Example
1537 ///
1538 /// ```no_run
1539 /// use stm32wlxx_hal::{
1540 /// adc::{self, Adc},
1541 /// pac,
1542 /// };
1543 ///
1544 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1545 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
1546 /// adc.enable();
1547 /// // ... use ADC
1548 /// adc.start_disable();
1549 /// while !adc.is_disabled() {}
1550 /// ```
1551 pub fn start_disable(&mut self) {
1552 // RM0453 rev 1 section 18.3.4 page 537 ADC on-off control
1553 // 1. Check that ADSTART = 0 in the ADC_CR register to ensure that no
1554 // conversion is ongoing.
1555 // If required, stop any ongoing conversion by writing 1 to the
1556 // ADSTP bit in the ADC_CR register and waiting until this bit is
1557 // read at 0.
1558 // 2. Set ADDIS = 1 in the ADC_CR register.
1559 // 3. If required by the application, wait until ADEN = 0 in the ADC_CR
1560 // register, indicating that the ADC is fully disabled
1561 // (ADDIS is automatically reset once ADEN = 0).
1562 // 4. Clear the ADRDY bit in ADC_ISR register by programming this bit to 1
1563 // (optional).
1564 self.stop_conversion();
1565 // Setting ADDIS to `1` is only effective when ADEN = 1 and ADSTART = 0
1566 // (which ensures that no conversion is ongoing)
1567 if self.adc.cr.read().aden().bit_is_set() {
1568 self.adc.cr.write(|w| w.addis().set_bit());
1569 }
1570 }
1571
1572 /// Disable the ADC and poll for completion.
1573 ///
1574 /// # Example
1575 ///
1576 /// ```no_run
1577 /// use stm32wlxx_hal::{
1578 /// adc::{self, Adc},
1579 /// pac,
1580 /// };
1581 ///
1582 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1583 /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
1584 /// adc.enable();
1585 /// // ... use ADC
1586 /// adc.disable();
1587 /// ```
1588 pub fn disable(&mut self) {
1589 self.start_disable();
1590 while !self.is_disabled() {}
1591 }
1592}
1593
1594// calibration related methods
1595// see RM0453 rev 1 section 18.3.3 page 536
1596#[cfg(not(feature = "stm32wl5x_cm0p"))]
1597impl Adc {
1598 /// Calibrate the ADC for additional accuracy.
1599 ///
1600 /// Calibration should be performed before starting A/D conversion.
1601 /// It removes the offset error which may vary from chip to chip due to
1602 /// process variation.
1603 ///
1604 /// The calibration factor is lost in the following cases:
1605 /// * The power supply is removed from the ADC
1606 /// (for example when entering STANDBY or VBAT mode)
1607 /// * The ADC peripheral is reset.
1608 ///
1609 /// This will disable the ADC if it is not already disabled.
1610 ///
1611 /// This function is the simple way to calibrate the ADC, you can use
1612 /// these methods to achieve the same results if you desire finer controls:
1613 ///
1614 /// * [`enable_vreg`](Self::enable_vreg)
1615 /// * A delay function
1616 /// * [`start_calibrate`](Self::start_calibrate)
1617 /// * [`set_ier`](Self::set_ier) (optional)
1618 /// * [`Adc::isr`]
1619 ///
1620 /// # Example
1621 ///
1622 /// ```no_run
1623 /// use stm32wlxx_hal::{
1624 /// adc::{self, Adc},
1625 /// pac, rcc,
1626 /// util::new_delay,
1627 /// };
1628 ///
1629 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1630 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1631 ///
1632 /// // enable the HSI16 source clock
1633 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1634 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1635 ///
1636 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1637 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1638 /// adc.calibrate(&mut delay);
1639 /// ```
1640 pub fn calibrate<D: DelayUs<u8>>(&mut self, delay: &mut D) {
1641 self.enable_vreg();
1642
1643 // voltage regulator output is available after T_ADCVREG_SETUP
1644 delay.delay_us(T_ADCVREG_SETUP_MICROS);
1645
1646 self.start_calibrate();
1647
1648 // takes 401 cycles at 48MHz sysclk, ADC at 16MHz with HSI
1649 while self.adc.cr.read().adcal().is_calibrating() {}
1650 self.adc.isr.write(|w| w.eocal().set_bit());
1651 }
1652
1653 /// Enable the ADC voltage regulator for calibration.
1654 ///
1655 /// This is advanced ADC usage, most of the time you will want to use
1656 /// [`calibrate`](Self::calibrate).
1657 ///
1658 /// This will disable the ADC and DMA request generation if not already
1659 /// disabled.
1660 ///
1661 /// You **MUST** wait [`T_ADCVREG_SETUP`] before the voltage regulator
1662 /// output is available. This delay is not performed for you.
1663 ///
1664 /// # Example
1665 ///
1666 /// ```no_run
1667 /// use stm32wlxx_hal::{
1668 /// adc::{self, Adc},
1669 /// pac, rcc,
1670 /// util::new_delay,
1671 /// };
1672 ///
1673 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1674 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1675 ///
1676 /// // enable the HSI16 source clock
1677 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1678 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1679 ///
1680 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1681 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1682 /// adc.enable_vreg();
1683 /// delay.delay_us(u32::from(adc::T_ADCVREG_SETUP_MICROS));
1684 /// ```
1685 pub fn enable_vreg(&mut self) {
1686 // RM0453 rev 1 section 18.3.3 page 536 Software calibration procedure
1687 // 1. Ensure that ADEN = 0, ADVREGEN = 1 and DMAEN = 0.
1688 // 2. Set ADCAL = 1.
1689 // 3. Wait until ADCAL = 0 (or until EOCAL = 1).
1690 // This can be handled by interrupt if the interrupt is enabled by
1691 // setting the EOCALIE bit in the ADC_IER register
1692 // 4. The calibration factor can be read from bits 6:0 of ADC_DR or
1693 // ADC_CALFACT registers.
1694
1695 // takes appx 55 cycles when already disabled
1696 self.disable();
1697
1698 // enable the voltage regulator as soon as possible to start the
1699 // countdown on the regulator setup time
1700 // this is a write because all other fields must be zero
1701 self.adc.cr.write(|w| w.advregen().enabled());
1702 // disable DMA per the calibration procedure
1703 self.adc.cfgr1.modify(|_, w| w.dmaen().clear_bit());
1704 }
1705
1706 /// Disable the ADC voltage regulator.
1707 ///
1708 /// # Panics
1709 ///
1710 /// * (debug) ADC is enabled
1711 #[inline]
1712 pub fn disable_vreg(&mut self) {
1713 debug_assert!(self.is_disabled());
1714 self.adc.cr.write(|w| w.advregen().disabled());
1715 }
1716
1717 /// Start the ADC calibration.
1718 ///
1719 /// This is advanced ADC usage, most of the time you will want to use
1720 /// [`calibrate`](Self::calibrate).
1721 ///
1722 /// When this function returns the ADC calibration has started, but
1723 /// may not have finished.
1724 /// Check if the ADC calibration has finished with [`Adc::isr`].
1725 ///
1726 /// # Panics
1727 ///
1728 /// * (debug) ADC is enabled.
1729 /// * (debug) ADC voltage regulator is not enabled.
1730 ///
1731 /// # Example
1732 ///
1733 /// ```no_run
1734 /// use stm32wlxx_hal::{
1735 /// adc::{self, Adc},
1736 /// pac, rcc,
1737 /// util::new_delay,
1738 /// };
1739 ///
1740 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1741 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1742 ///
1743 /// // enable the HSI16 source clock
1744 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1745 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1746 ///
1747 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1748 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1749 ///
1750 /// adc.enable_vreg();
1751 /// delay.delay_us(u32::from(adc::T_ADCVREG_SETUP_MICROS));
1752 /// adc.start_calibrate();
1753 /// // datasheet says this takes 82 ADC clock cycles
1754 /// // my measurements are closer to 120 ADC clock cycles
1755 /// while Adc::isr().eocal().is_not_complete() {}
1756 /// ```
1757 #[inline]
1758 pub fn start_calibrate(&mut self) {
1759 debug_assert!(self.adc.cr.read().advregen().is_enabled());
1760 debug_assert!(self.is_disabled());
1761 self.adc
1762 .cr
1763 .write(|w| w.adcal().start_calibration().advregen().enabled());
1764 }
1765
1766 /// Get the ADC calibration factor.
1767 ///
1768 /// # Example
1769 ///
1770 /// See [`force_cal`](Self::force_cal).
1771 #[inline]
1772 pub fn calfact(&self) -> u8 {
1773 self.adc.calfact.read().calfact().bits()
1774 }
1775
1776 /// Force the ADC calibration.
1777 ///
1778 /// The calibration factor is lost each time power is removed from the ADC
1779 /// (for example when entering standby or V<sub>BAT</sub> mode)
1780 /// It is possible to save and restore the calibration factor with firmware
1781 /// to save time when re-starting the ADC (as long as temperature and
1782 /// voltage are stable during the ADC power-down).
1783 ///
1784 /// # Panics
1785 ///
1786 /// * (debug) ADC is not enabled
1787 /// * (debug) ADC conversion is in-progress
1788 ///
1789 /// # Example
1790 ///
1791 /// ```no_run
1792 /// use stm32wlxx_hal::{
1793 /// adc::{self, Adc},
1794 /// pac, rcc,
1795 /// util::new_delay,
1796 /// };
1797 ///
1798 /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1799 /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1800 ///
1801 /// // enable the HSI16 source clock
1802 /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1803 /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1804 ///
1805 /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1806 /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1807 /// adc.calibrate(&mut delay);
1808 ///
1809 /// // save the calibration factor
1810 /// let calfact: u8 = adc.calfact();
1811 ///
1812 /// // restore the calibration
1813 /// adc.enable(); // ADC must be enabled to restore the calibration
1814 /// adc.force_cal(calfact);
1815 /// ```
1816 #[inline]
1817 pub fn force_cal(&mut self, calfact: u8) {
1818 debug_assert!(self.is_enabled());
1819 debug_assert!(self.adc.cr.read().adstart().bit_is_clear());
1820 self.adc.calfact.write(|w| w.calfact().bits(calfact))
1821 }
1822}