diff options
| author | Chuck Davis <[email protected]> | 2022-10-10 09:17:07 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-10-10 09:17:07 -0500 |
| commit | 79ba20d315f456ac525daf4c3d5dd0d2ce92ad2b (patch) | |
| tree | fced8cc48be09f8418fa5e9e1b9dcbd016e189d6 | |
| parent | 3d0ba58b2d337ca74c5ae7d1d594af21f4b5ff8c (diff) | |
| parent | 9d5b524bb083310c2e1753859ebc9fca080a4238 (diff) | |
Merge branch 'embassy-rs:master' into master
| -rw-r--r-- | embassy-rp/src/gpio.rs | 32 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/mod.rs | 9 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v2.rs | 161 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v4.rs | 16 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/adc.rs | 25 |
5 files changed, 160 insertions, 83 deletions
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index a28bae96b..f79f592b4 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs | |||
| @@ -599,12 +599,12 @@ pub(crate) mod sealed { | |||
| 599 | fn pin_bank(&self) -> u8; | 599 | fn pin_bank(&self) -> u8; |
| 600 | 600 | ||
| 601 | #[inline] | 601 | #[inline] |
| 602 | fn pin(&self) -> u8 { | 602 | fn _pin(&self) -> u8 { |
| 603 | self.pin_bank() & 0x1f | 603 | self.pin_bank() & 0x1f |
| 604 | } | 604 | } |
| 605 | 605 | ||
| 606 | #[inline] | 606 | #[inline] |
| 607 | fn bank(&self) -> Bank { | 607 | fn _bank(&self) -> Bank { |
| 608 | if self.pin_bank() & 0x20 == 0 { | 608 | if self.pin_bank() & 0x20 == 0 { |
| 609 | Bank::Bank0 | 609 | Bank::Bank0 |
| 610 | } else { | 610 | } else { |
| @@ -613,35 +613,35 @@ pub(crate) mod sealed { | |||
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | fn io(&self) -> pac::io::Gpio { | 615 | fn io(&self) -> pac::io::Gpio { |
| 616 | let block = match self.bank() { | 616 | let block = match self._bank() { |
| 617 | Bank::Bank0 => crate::pac::IO_BANK0, | 617 | Bank::Bank0 => crate::pac::IO_BANK0, |
| 618 | Bank::Qspi => crate::pac::IO_QSPI, | 618 | Bank::Qspi => crate::pac::IO_QSPI, |
| 619 | }; | 619 | }; |
| 620 | block.gpio(self.pin() as _) | 620 | block.gpio(self._pin() as _) |
| 621 | } | 621 | } |
| 622 | 622 | ||
| 623 | fn pad_ctrl(&self) -> Reg<pac::pads::regs::GpioCtrl, RW> { | 623 | fn pad_ctrl(&self) -> Reg<pac::pads::regs::GpioCtrl, RW> { |
| 624 | let block = match self.bank() { | 624 | let block = match self._bank() { |
| 625 | Bank::Bank0 => crate::pac::PADS_BANK0, | 625 | Bank::Bank0 => crate::pac::PADS_BANK0, |
| 626 | Bank::Qspi => crate::pac::PADS_QSPI, | 626 | Bank::Qspi => crate::pac::PADS_QSPI, |
| 627 | }; | 627 | }; |
| 628 | block.gpio(self.pin() as _) | 628 | block.gpio(self._pin() as _) |
| 629 | } | 629 | } |
| 630 | 630 | ||
| 631 | fn sio_out(&self) -> pac::sio::Gpio { | 631 | fn sio_out(&self) -> pac::sio::Gpio { |
| 632 | SIO.gpio_out(self.bank() as _) | 632 | SIO.gpio_out(self._bank() as _) |
| 633 | } | 633 | } |
| 634 | 634 | ||
| 635 | fn sio_oe(&self) -> pac::sio::Gpio { | 635 | fn sio_oe(&self) -> pac::sio::Gpio { |
| 636 | SIO.gpio_oe(self.bank() as _) | 636 | SIO.gpio_oe(self._bank() as _) |
| 637 | } | 637 | } |
| 638 | 638 | ||
| 639 | fn sio_in(&self) -> Reg<u32, RW> { | 639 | fn sio_in(&self) -> Reg<u32, RW> { |
| 640 | SIO.gpio_in(self.bank() as _) | 640 | SIO.gpio_in(self._bank() as _) |
| 641 | } | 641 | } |
| 642 | 642 | ||
| 643 | fn int_proc(&self) -> pac::io::Int { | 643 | fn int_proc(&self) -> pac::io::Int { |
| 644 | let io_block = match self.bank() { | 644 | let io_block = match self._bank() { |
| 645 | Bank::Bank0 => crate::pac::IO_BANK0, | 645 | Bank::Bank0 => crate::pac::IO_BANK0, |
| 646 | Bank::Qspi => crate::pac::IO_QSPI, | 646 | Bank::Qspi => crate::pac::IO_QSPI, |
| 647 | }; | 647 | }; |
| @@ -658,6 +658,18 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'stat | |||
| 658 | pin_bank: self.pin_bank(), | 658 | pin_bank: self.pin_bank(), |
| 659 | } | 659 | } |
| 660 | } | 660 | } |
| 661 | |||
| 662 | /// Returns the pin number within a bank | ||
| 663 | #[inline] | ||
| 664 | fn pin(&self) -> u8 { | ||
| 665 | self._pin() | ||
| 666 | } | ||
| 667 | |||
| 668 | /// Returns the bank of this pin | ||
| 669 | #[inline] | ||
| 670 | fn bank(&self) -> Bank { | ||
| 671 | self._bank() | ||
| 672 | } | ||
| 661 | } | 673 | } |
| 662 | 674 | ||
| 663 | pub struct AnyPin { | 675 | pub struct AnyPin { |
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 8da13073e..0eb4eba73 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs | |||
| @@ -28,15 +28,20 @@ pub(crate) mod sealed { | |||
| 28 | pub trait AdcPin<T: Instance> { | 28 | pub trait AdcPin<T: Instance> { |
| 29 | fn channel(&self) -> u8; | 29 | fn channel(&self) -> u8; |
| 30 | } | 30 | } |
| 31 | |||
| 32 | pub trait InternalChannel<T> { | ||
| 33 | fn channel(&self) -> u8; | ||
| 34 | } | ||
| 31 | } | 35 | } |
| 32 | 36 | ||
| 33 | #[cfg(not(adc_f1))] | 37 | #[cfg(not(any(adc_f1, adc_v2)))] |
| 34 | pub trait Instance: sealed::Instance + 'static {} | 38 | pub trait Instance: sealed::Instance + 'static {} |
| 35 | #[cfg(adc_f1)] | 39 | #[cfg(any(adc_f1, adc_v2))] |
| 36 | pub trait Instance: sealed::Instance + crate::rcc::RccPeripheral + 'static {} | 40 | pub trait Instance: sealed::Instance + crate::rcc::RccPeripheral + 'static {} |
| 37 | #[cfg(all(not(adc_f1), not(adc_v1)))] | 41 | #[cfg(all(not(adc_f1), not(adc_v1)))] |
| 38 | pub trait Common: sealed::Common + 'static {} | 42 | pub trait Common: sealed::Common + 'static {} |
| 39 | pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} | 43 | pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} |
| 44 | pub trait InternalChannel<T>: sealed::InternalChannel<T> {} | ||
| 40 | 45 | ||
| 41 | #[cfg(not(stm32h7))] | 46 | #[cfg(not(stm32h7))] |
| 42 | foreach_peripheral!( | 47 | foreach_peripheral!( |
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index 25b7ba967..4fe4ad1f0 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs | |||
| @@ -3,7 +3,9 @@ use core::marker::PhantomData; | |||
| 3 | use embassy_hal_common::into_ref; | 3 | use embassy_hal_common::into_ref; |
| 4 | use embedded_hal_02::blocking::delay::DelayUs; | 4 | use embedded_hal_02::blocking::delay::DelayUs; |
| 5 | 5 | ||
| 6 | use super::InternalChannel; | ||
| 6 | use crate::adc::{AdcPin, Instance}; | 7 | use crate::adc::{AdcPin, Instance}; |
| 8 | use crate::peripherals::ADC1; | ||
| 7 | use crate::time::Hertz; | 9 | use crate::time::Hertz; |
| 8 | use crate::Peripheral; | 10 | use crate::Peripheral; |
| 9 | 11 | ||
| @@ -12,20 +14,8 @@ pub const VREF_DEFAULT_MV: u32 = 3300; | |||
| 12 | /// VREF voltage used for factory calibration of VREFINTCAL register. | 14 | /// VREF voltage used for factory calibration of VREFINTCAL register. |
| 13 | pub const VREF_CALIB_MV: u32 = 3300; | 15 | pub const VREF_CALIB_MV: u32 = 3300; |
| 14 | 16 | ||
| 15 | #[cfg(not(any(rcc_f4, rcc_f7)))] | 17 | /// ADC turn-on time |
| 16 | fn enable() { | 18 | pub const ADC_POWERUP_TIME_US: u32 = 3; |
| 17 | todo!() | ||
| 18 | } | ||
| 19 | |||
| 20 | #[cfg(any(rcc_f4, rcc_f7))] | ||
| 21 | fn enable() { | ||
| 22 | critical_section::with(|_| unsafe { | ||
| 23 | // TODO do not enable all adc clocks if not needed | ||
| 24 | crate::pac::RCC.apb2enr().modify(|w| w.set_adc1en(true)); | ||
| 25 | crate::pac::RCC.apb2enr().modify(|w| w.set_adc2en(true)); | ||
| 26 | crate::pac::RCC.apb2enr().modify(|w| w.set_adc3en(true)); | ||
| 27 | }); | ||
| 28 | } | ||
| 29 | 19 | ||
| 30 | pub enum Resolution { | 20 | pub enum Resolution { |
| 31 | TwelveBit, | 21 | TwelveBit, |
| @@ -61,24 +51,53 @@ impl Resolution { | |||
| 61 | } | 51 | } |
| 62 | 52 | ||
| 63 | pub struct VrefInt; | 53 | pub struct VrefInt; |
| 64 | impl<T: Instance> AdcPin<T> for VrefInt {} | 54 | impl InternalChannel<ADC1> for VrefInt {} |
| 65 | impl<T: Instance> super::sealed::AdcPin<T> for VrefInt { | 55 | impl super::sealed::InternalChannel<ADC1> for VrefInt { |
| 66 | fn channel(&self) -> u8 { | 56 | fn channel(&self) -> u8 { |
| 67 | 17 | 57 | 17 |
| 68 | } | 58 | } |
| 69 | } | 59 | } |
| 70 | 60 | ||
| 61 | impl VrefInt { | ||
| 62 | /// Time needed for internal voltage reference to stabilize | ||
| 63 | pub fn start_time_us() -> u32 { | ||
| 64 | 10 | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 71 | pub struct Temperature; | 68 | pub struct Temperature; |
| 72 | impl<T: Instance> AdcPin<T> for Temperature {} | 69 | impl InternalChannel<ADC1> for Temperature {} |
| 73 | impl<T: Instance> super::sealed::AdcPin<T> for Temperature { | 70 | impl super::sealed::InternalChannel<ADC1> for Temperature { |
| 74 | fn channel(&self) -> u8 { | 71 | fn channel(&self) -> u8 { |
| 75 | 16 | 72 | cfg_if::cfg_if! { |
| 73 | if #[cfg(any(stm32f40, stm32f41))] { | ||
| 74 | 16 | ||
| 75 | } else { | ||
| 76 | 18 | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | impl Temperature { | ||
| 83 | /// Converts temperature sensor reading in millivolts to degrees celcius | ||
| 84 | pub fn to_celcius(sample_mv: u16) -> f32 { | ||
| 85 | // From 6.3.22 Temperature sensor characteristics | ||
| 86 | const V25: i32 = 760; // mV | ||
| 87 | const AVG_SLOPE: f32 = 2.5; // mV/C | ||
| 88 | |||
| 89 | (sample_mv as i32 - V25) as f32 / AVG_SLOPE + 25.0 | ||
| 90 | } | ||
| 91 | |||
| 92 | /// Time needed for temperature sensor readings to stabilize | ||
| 93 | pub fn start_time_us() -> u32 { | ||
| 94 | 10 | ||
| 76 | } | 95 | } |
| 77 | } | 96 | } |
| 78 | 97 | ||
| 79 | pub struct Vbat; | 98 | pub struct Vbat; |
| 80 | impl<T: Instance> AdcPin<T> for Vbat {} | 99 | impl InternalChannel<ADC1> for Vbat {} |
| 81 | impl<T: Instance> super::sealed::AdcPin<T> for Vbat { | 100 | impl super::sealed::InternalChannel<ADC1> for Vbat { |
| 82 | fn channel(&self) -> u8 { | 101 | fn channel(&self) -> u8 { |
| 83 | 18 | 102 | 18 |
| 84 | } | 103 | } |
| @@ -164,21 +183,19 @@ where | |||
| 164 | { | 183 | { |
| 165 | pub fn new(_peri: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { | 184 | pub fn new(_peri: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { |
| 166 | into_ref!(_peri); | 185 | into_ref!(_peri); |
| 167 | enable(); | 186 | T::enable(); |
| 187 | T::reset(); | ||
| 168 | 188 | ||
| 169 | let presc = unsafe { Prescaler::from_pclk2(crate::rcc::get_freqs().apb2) }; | 189 | let presc = Prescaler::from_pclk2(T::frequency()); |
| 170 | unsafe { | 190 | unsafe { |
| 171 | T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); | 191 | T::common_regs().ccr().modify(|w| w.set_adcpre(presc.adcpre())); |
| 172 | } | ||
| 173 | 192 | ||
| 174 | unsafe { | ||
| 175 | // disable before config is set | ||
| 176 | T::regs().cr2().modify(|reg| { | 193 | T::regs().cr2().modify(|reg| { |
| 177 | reg.set_adon(crate::pac::adc::vals::Adon::DISABLED); | 194 | reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); |
| 178 | }); | 195 | }); |
| 179 | } | 196 | } |
| 180 | 197 | ||
| 181 | delay.delay_us(20); // TODO? | 198 | delay.delay_us(ADC_POWERUP_TIME_US); |
| 182 | 199 | ||
| 183 | Self { | 200 | Self { |
| 184 | sample_time: Default::default(), | 201 | sample_time: Default::default(), |
| @@ -208,6 +225,45 @@ where | |||
| 208 | ((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16 | 225 | ((u32::from(sample) * self.vref_mv) / self.resolution.to_max_count()) as u16 |
| 209 | } | 226 | } |
| 210 | 227 | ||
| 228 | /// Enables internal voltage reference and returns [VrefInt], which can be used in | ||
| 229 | /// [Adc::read_internal()] to perform conversion. | ||
| 230 | pub fn enable_vrefint(&self) -> VrefInt { | ||
| 231 | unsafe { | ||
| 232 | T::common_regs().ccr().modify(|reg| { | ||
| 233 | reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); | ||
| 234 | }); | ||
| 235 | } | ||
| 236 | |||
| 237 | VrefInt {} | ||
| 238 | } | ||
| 239 | |||
| 240 | /// Enables internal temperature sensor and returns [Temperature], which can be used in | ||
| 241 | /// [Adc::read_internal()] to perform conversion. | ||
| 242 | /// | ||
| 243 | /// On STM32F42 and STM32F43 this can not be used together with [Vbat]. If both are enabled, | ||
| 244 | /// temperature sensor will return vbat value. | ||
| 245 | pub fn enable_temperature(&self) -> Temperature { | ||
| 246 | unsafe { | ||
| 247 | T::common_regs().ccr().modify(|reg| { | ||
| 248 | reg.set_tsvrefe(crate::pac::adccommon::vals::Tsvrefe::ENABLED); | ||
| 249 | }); | ||
| 250 | } | ||
| 251 | |||
| 252 | Temperature {} | ||
| 253 | } | ||
| 254 | |||
| 255 | /// Enables vbat input and returns [Vbat], which can be used in | ||
| 256 | /// [Adc::read_internal()] to perform conversion. | ||
| 257 | pub fn enable_vbat(&self) -> Vbat { | ||
| 258 | unsafe { | ||
| 259 | T::common_regs().ccr().modify(|reg| { | ||
| 260 | reg.set_vbate(crate::pac::adccommon::vals::Vbate::ENABLED); | ||
| 261 | }); | ||
| 262 | } | ||
| 263 | |||
| 264 | Vbat {} | ||
| 265 | } | ||
| 266 | |||
| 211 | /// Perform a single conversion. | 267 | /// Perform a single conversion. |
| 212 | fn convert(&mut self) -> u16 { | 268 | fn convert(&mut self) -> u16 { |
| 213 | unsafe { | 269 | unsafe { |
| @@ -238,42 +294,29 @@ where | |||
| 238 | P: crate::gpio::sealed::Pin, | 294 | P: crate::gpio::sealed::Pin, |
| 239 | { | 295 | { |
| 240 | unsafe { | 296 | unsafe { |
| 241 | // dissable ADC | ||
| 242 | T::regs().cr2().modify(|reg| { | ||
| 243 | reg.set_swstart(false); | ||
| 244 | }); | ||
| 245 | T::regs().cr2().modify(|reg| { | ||
| 246 | reg.set_adon(crate::pac::adc::vals::Adon::DISABLED); | ||
| 247 | }); | ||
| 248 | |||
| 249 | pin.set_as_analog(); | 297 | pin.set_as_analog(); |
| 250 | 298 | ||
| 251 | // Configure ADC | 299 | self.read_channel(pin.channel()) |
| 252 | T::regs().cr1().modify(|reg| reg.set_res(self.resolution.res())); | 300 | } |
| 301 | } | ||
| 253 | 302 | ||
| 254 | // Select channel | 303 | pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 { |
| 255 | T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel())); | 304 | unsafe { self.read_channel(channel.channel()) } |
| 305 | } | ||
| 256 | 306 | ||
| 257 | // Configure channel | 307 | unsafe fn read_channel(&mut self, channel: u8) -> u16 { |
| 258 | Self::set_channel_sample_time(pin.channel(), self.sample_time); | 308 | // Configure ADC |
| 309 | T::regs().cr1().modify(|reg| reg.set_res(self.resolution.res())); | ||
| 259 | 310 | ||
| 260 | // enable adc | 311 | // Select channel |
| 261 | T::regs().cr2().modify(|reg| { | 312 | T::regs().sqr3().write(|reg| reg.set_sq(0, channel)); |
| 262 | reg.set_adon(crate::pac::adc::vals::Adon::ENABLED); | ||
| 263 | }); | ||
| 264 | 313 | ||
| 265 | let val = self.convert(); | 314 | // Configure channel |
| 315 | Self::set_channel_sample_time(channel, self.sample_time); | ||
| 266 | 316 | ||
| 267 | // dissable ADC | 317 | let val = self.convert(); |
| 268 | T::regs().cr2().modify(|reg| { | ||
| 269 | reg.set_swstart(false); | ||
| 270 | }); | ||
| 271 | T::regs().cr2().modify(|reg| { | ||
| 272 | reg.set_adon(crate::pac::adc::vals::Adon::DISABLED); | ||
| 273 | }); | ||
| 274 | 318 | ||
| 275 | val | 319 | val |
| 276 | } | ||
| 277 | } | 320 | } |
| 278 | 321 | ||
| 279 | unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { | 322 | unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { |
| @@ -288,3 +331,9 @@ where | |||
| 288 | } | 331 | } |
| 289 | } | 332 | } |
| 290 | } | 333 | } |
| 334 | |||
| 335 | impl<'d, T: Instance> Drop for Adc<'d, T> { | ||
| 336 | fn drop(&mut self) { | ||
| 337 | T::disable(); | ||
| 338 | } | ||
| 339 | } | ||
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index d356d7b66..eda2b2a72 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs | |||
| @@ -5,7 +5,7 @@ use embedded_hal_02::blocking::delay::DelayUs; | |||
| 5 | use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel}; | 5 | use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel}; |
| 6 | use pac::adccommon::vals::Presc; | 6 | use pac::adccommon::vals::Presc; |
| 7 | 7 | ||
| 8 | use super::{AdcPin, Instance}; | 8 | use super::{AdcPin, Instance, InternalChannel}; |
| 9 | use crate::time::Hertz; | 9 | use crate::time::Hertz; |
| 10 | use crate::{pac, Peripheral}; | 10 | use crate::{pac, Peripheral}; |
| 11 | 11 | ||
| @@ -50,18 +50,10 @@ impl Resolution { | |||
| 50 | } | 50 | } |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | pub trait InternalChannel<T>: sealed::InternalChannel<T> {} | ||
| 54 | |||
| 55 | mod sealed { | ||
| 56 | pub trait InternalChannel<T> { | ||
| 57 | fn channel(&self) -> u8; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | |||
| 61 | // NOTE: Vrefint/Temperature/Vbat are only available on ADC3 on H7, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs | 53 | // NOTE: Vrefint/Temperature/Vbat are only available on ADC3 on H7, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs |
| 62 | pub struct VrefInt; | 54 | pub struct VrefInt; |
| 63 | impl<T: Instance> InternalChannel<T> for VrefInt {} | 55 | impl<T: Instance> InternalChannel<T> for VrefInt {} |
| 64 | impl<T: Instance> sealed::InternalChannel<T> for VrefInt { | 56 | impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt { |
| 65 | fn channel(&self) -> u8 { | 57 | fn channel(&self) -> u8 { |
| 66 | 19 | 58 | 19 |
| 67 | } | 59 | } |
| @@ -69,7 +61,7 @@ impl<T: Instance> sealed::InternalChannel<T> for VrefInt { | |||
| 69 | 61 | ||
| 70 | pub struct Temperature; | 62 | pub struct Temperature; |
| 71 | impl<T: Instance> InternalChannel<T> for Temperature {} | 63 | impl<T: Instance> InternalChannel<T> for Temperature {} |
| 72 | impl<T: Instance> sealed::InternalChannel<T> for Temperature { | 64 | impl<T: Instance> super::sealed::InternalChannel<T> for Temperature { |
| 73 | fn channel(&self) -> u8 { | 65 | fn channel(&self) -> u8 { |
| 74 | 18 | 66 | 18 |
| 75 | } | 67 | } |
| @@ -77,7 +69,7 @@ impl<T: Instance> sealed::InternalChannel<T> for Temperature { | |||
| 77 | 69 | ||
| 78 | pub struct Vbat; | 70 | pub struct Vbat; |
| 79 | impl<T: Instance> InternalChannel<T> for Vbat {} | 71 | impl<T: Instance> InternalChannel<T> for Vbat {} |
| 80 | impl<T: Instance> sealed::InternalChannel<T> for Vbat { | 72 | impl<T: Instance> super::sealed::InternalChannel<T> for Vbat { |
| 81 | fn channel(&self) -> u8 { | 73 | fn channel(&self) -> u8 { |
| 82 | // TODO this should be 14 for H7a/b/35 | 74 | // TODO this should be 14 for H7a/b/35 |
| 83 | 17 | 75 | 17 |
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs index 871185074..1d030f7dc 100644 --- a/examples/stm32f4/src/bin/adc.rs +++ b/examples/stm32f4/src/bin/adc.rs | |||
| @@ -2,9 +2,10 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | 4 | ||
| 5 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; | ||
| 5 | use defmt::*; | 6 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::adc::Adc; | 8 | use embassy_stm32::adc::{Adc, Temperature, VrefInt}; |
| 8 | use embassy_time::{Delay, Duration, Timer}; | 9 | use embassy_time::{Delay, Duration, Timer}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 11 | ||
| @@ -13,12 +14,30 @@ async fn main(_spawner: Spawner) { | |||
| 13 | let p = embassy_stm32::init(Default::default()); | 14 | let p = embassy_stm32::init(Default::default()); |
| 14 | info!("Hello World!"); | 15 | info!("Hello World!"); |
| 15 | 16 | ||
| 16 | let mut adc = Adc::new(p.ADC1, &mut Delay); | 17 | let mut delay = Delay; |
| 18 | let mut adc = Adc::new(p.ADC1, &mut delay); | ||
| 17 | let mut pin = p.PC1; | 19 | let mut pin = p.PC1; |
| 18 | 20 | ||
| 21 | let mut vrefint = adc.enable_vrefint(); | ||
| 22 | let mut temp = adc.enable_temperature(); | ||
| 23 | |||
| 24 | // Startup delay can be combined to the maximum of either | ||
| 25 | delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); | ||
| 26 | |||
| 19 | loop { | 27 | loop { |
| 28 | // Read pin | ||
| 20 | let v = adc.read(&mut pin); | 29 | let v = adc.read(&mut pin); |
| 21 | info!("--> {} - {} mV", v, adc.to_millivolts(v)); | 30 | info!("PC1: {} ({} mV)", v, adc.to_millivolts(v)); |
| 31 | |||
| 32 | // Read internal temperature | ||
| 33 | let v = adc.read_internal(&mut temp); | ||
| 34 | let celcius = Temperature::to_celcius(adc.to_millivolts(v)); | ||
| 35 | info!("Internal temp: {} ({} C)", v, celcius); | ||
| 36 | |||
| 37 | // Read internal voltage reference | ||
| 38 | let v = adc.read_internal(&mut vrefint); | ||
| 39 | info!("VrefInt: {} ({} mV)", v, adc.to_millivolts(v)); | ||
| 40 | |||
| 22 | Timer::after(Duration::from_millis(100)).await; | 41 | Timer::after(Duration::from_millis(100)).await; |
| 23 | } | 42 | } |
| 24 | } | 43 | } |
