diff options
42 files changed, 475 insertions, 653 deletions
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md index 595778748..8a53c9f03 100644 --- a/embassy-stm32/CHANGELOG.md +++ b/embassy-stm32/CHANGELOG.md | |||
| @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 52 | - feat: stm32/dsi support zero parameter commands in `write_cmd` ([#4847](https://github.com/embassy-rs/embassy/pull/4847)) | 52 | - feat: stm32/dsi support zero parameter commands in `write_cmd` ([#4847](https://github.com/embassy-rs/embassy/pull/4847)) |
| 53 | - feat: stm32/spi: added support for slave mode ([#4388](https://github.com/embassy-rs/embassy/pull/4388)) | 53 | - feat: stm32/spi: added support for slave mode ([#4388](https://github.com/embassy-rs/embassy/pull/4388)) |
| 54 | - chore: Updated stm32-metapac and stm32-data dependencies | 54 | - chore: Updated stm32-metapac and stm32-data dependencies |
| 55 | - adc: reogranize and cleanup somewhat. require sample_time to be passed on conversion | ||
| 55 | 56 | ||
| 56 | ## 0.4.0 - 2025-08-26 | 57 | ## 0.4.0 - 2025-08-26 |
| 57 | 58 | ||
diff --git a/embassy-stm32/src/adc/adc4.rs b/embassy-stm32/src/adc/adc4.rs index 2608160a3..befa8ed4a 100644 --- a/embassy-stm32/src/adc/adc4.rs +++ b/embassy-stm32/src/adc/adc4.rs | |||
| @@ -327,18 +327,6 @@ impl<'d, T: Instance> Adc4<'d, T> { | |||
| 327 | Dac {} | 327 | Dac {} |
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | /// Set the ADC sample time. | ||
| 331 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||
| 332 | T::regs().smpr().modify(|w| { | ||
| 333 | w.set_smp(0, sample_time); | ||
| 334 | }); | ||
| 335 | } | ||
| 336 | |||
| 337 | /// Get the ADC sample time. | ||
| 338 | pub fn sample_time(&self) -> SampleTime { | ||
| 339 | T::regs().smpr().read().smp(0) | ||
| 340 | } | ||
| 341 | |||
| 342 | /// Set the ADC resolution. | 330 | /// Set the ADC resolution. |
| 343 | pub fn set_resolution(&mut self, resolution: Resolution) { | 331 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 344 | T::regs().cfgr1().modify(|w| w.set_res(resolution.into())); | 332 | T::regs().cfgr1().modify(|w| w.set_res(resolution.into())); |
| @@ -387,7 +375,11 @@ impl<'d, T: Instance> Adc4<'d, T> { | |||
| 387 | } | 375 | } |
| 388 | 376 | ||
| 389 | /// Read an ADC channel. | 377 | /// Read an ADC channel. |
| 390 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 378 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 379 | T::regs().smpr().modify(|w| { | ||
| 380 | w.set_smp(0, sample_time); | ||
| 381 | }); | ||
| 382 | |||
| 391 | channel.setup(); | 383 | channel.setup(); |
| 392 | 384 | ||
| 393 | // Select channel | 385 | // Select channel |
diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs index fc28df346..1869993a5 100644 --- a/embassy-stm32/src/adc/c0.rs +++ b/embassy-stm32/src/adc/c0.rs | |||
| @@ -19,33 +19,17 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(25); | |||
| 19 | 19 | ||
| 20 | const TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US: u32 = 20; | 20 | const TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US: u32 = 20; |
| 21 | 21 | ||
| 22 | const TEMP_CHANNEL: u8 = 9; | ||
| 23 | const VREF_CHANNEL: u8 = 10; | ||
| 24 | |||
| 25 | const NUM_HW_CHANNELS: u8 = 22; | 22 | const NUM_HW_CHANNELS: u8 = 22; |
| 26 | const CHSELR_SQ_SIZE: usize = 8; | 23 | const CHSELR_SQ_SIZE: usize = 8; |
| 27 | const CHSELR_SQ_MAX_CHANNEL: u8 = 14; | 24 | const CHSELR_SQ_MAX_CHANNEL: u8 = 14; |
| 28 | const CHSELR_SQ_SEQUENCE_END_MARKER: u8 = 0b1111; | 25 | const CHSELR_SQ_SEQUENCE_END_MARKER: u8 = 0b1111; |
| 29 | 26 | ||
| 30 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, | 27 | impl<T: Instance> super::VrefConverter for T { |
| 31 | // this currently cannot be modeled with stm32-data, | 28 | const CHANNEL: u8 = 10; |
| 32 | // so these are available from the software on all ADCs. | ||
| 33 | /// Internal voltage reference channel. | ||
| 34 | pub struct VrefInt; | ||
| 35 | impl<T: Instance> AdcChannel<T> for VrefInt {} | ||
| 36 | impl<T: Instance> SealedAdcChannel<T> for VrefInt { | ||
| 37 | fn channel(&self) -> u8 { | ||
| 38 | VREF_CHANNEL | ||
| 39 | } | ||
| 40 | } | 29 | } |
| 41 | 30 | ||
| 42 | /// Internal temperature channel. | 31 | impl<T: Instance> super::TemperatureConverter for T { |
| 43 | pub struct Temperature; | 32 | const CHANNEL: u8 = 9; |
| 44 | impl<T: Instance> AdcChannel<T> for Temperature {} | ||
| 45 | impl<T: Instance> SealedAdcChannel<T> for Temperature { | ||
| 46 | fn channel(&self) -> u8 { | ||
| 47 | TEMP_CHANNEL | ||
| 48 | } | ||
| 49 | } | 33 | } |
| 50 | 34 | ||
| 51 | #[derive(Copy, Clone, Debug)] | 35 | #[derive(Copy, Clone, Debug)] |
| @@ -156,7 +140,7 @@ pub enum Averaging { | |||
| 156 | 140 | ||
| 157 | impl<'d, T: Instance> Adc<'d, T> { | 141 | impl<'d, T: Instance> Adc<'d, T> { |
| 158 | /// Create a new ADC driver. | 142 | /// Create a new ADC driver. |
| 159 | pub fn new(adc: Peri<'d, T>, sample_time: SampleTime, resolution: Resolution) -> Self { | 143 | pub fn new(adc: Peri<'d, T>, resolution: Resolution) -> Self { |
| 160 | rcc::enable_and_reset::<T>(); | 144 | rcc::enable_and_reset::<T>(); |
| 161 | 145 | ||
| 162 | T::regs().cfgr2().modify(|w| w.set_ckmode(Ckmode::SYSCLK)); | 146 | T::regs().cfgr2().modify(|w| w.set_ckmode(Ckmode::SYSCLK)); |
| @@ -174,10 +158,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 174 | ); | 158 | ); |
| 175 | } | 159 | } |
| 176 | 160 | ||
| 177 | let mut s = Self { | 161 | let mut s = Self { adc }; |
| 178 | adc, | ||
| 179 | sample_time: SampleTime::from_bits(0), | ||
| 180 | }; | ||
| 181 | 162 | ||
| 182 | s.power_up(); | 163 | s.power_up(); |
| 183 | 164 | ||
| @@ -189,8 +170,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 189 | 170 | ||
| 190 | s.configure_default(); | 171 | s.configure_default(); |
| 191 | 172 | ||
| 192 | s.set_sample_time_all_channels(sample_time); | ||
| 193 | |||
| 194 | s | 173 | s |
| 195 | } | 174 | } |
| 196 | 175 | ||
| @@ -237,29 +216,27 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 237 | } | 216 | } |
| 238 | 217 | ||
| 239 | /// Enable reading the voltage reference internal channel. | 218 | /// Enable reading the voltage reference internal channel. |
| 240 | pub fn enable_vrefint(&self) -> VrefInt { | 219 | pub fn enable_vrefint(&self) -> super::VrefInt { |
| 241 | T::common_regs().ccr().modify(|reg| { | 220 | T::common_regs().ccr().modify(|reg| { |
| 242 | reg.set_vrefen(true); | 221 | reg.set_vrefen(true); |
| 243 | }); | 222 | }); |
| 244 | 223 | ||
| 245 | VrefInt {} | 224 | super::VrefInt {} |
| 246 | } | 225 | } |
| 247 | 226 | ||
| 248 | /// Enable reading the temperature internal channel. | 227 | /// Enable reading the temperature internal channel. |
| 249 | pub fn enable_temperature(&self) -> Temperature { | 228 | pub fn enable_temperature(&self) -> super::Temperature { |
| 250 | debug!("Ensure that sample time is set to more than temperature sensor T_start from the datasheet!"); | 229 | debug!("Ensure that sample time is set to more than temperature sensor T_start from the datasheet!"); |
| 251 | T::common_regs().ccr().modify(|reg| { | 230 | T::common_regs().ccr().modify(|reg| { |
| 252 | reg.set_tsen(true); | 231 | reg.set_tsen(true); |
| 253 | }); | 232 | }); |
| 254 | 233 | ||
| 255 | Temperature {} | 234 | super::Temperature {} |
| 256 | } | 235 | } |
| 257 | 236 | ||
| 258 | /// Set the ADC sample time. | 237 | /// Set the ADC sample time. |
| 259 | /// Shall only be called when ADC is not converting. | 238 | /// Shall only be called when ADC is not converting. |
| 260 | pub fn set_sample_time_all_channels(&mut self, sample_time: SampleTime) { | 239 | pub fn set_sample_time_all_channels(&mut self, sample_time: SampleTime) { |
| 261 | self.sample_time = sample_time; | ||
| 262 | |||
| 263 | // Set all channels to use SMP1 field as source. | 240 | // Set all channels to use SMP1 field as source. |
| 264 | T::regs().smpr().modify(|w| { | 241 | T::regs().smpr().modify(|w| { |
| 265 | w.smpsel(0); | 242 | w.smpsel(0); |
| @@ -288,7 +265,9 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 288 | T::regs().dr().read().data() as u16 | 265 | T::regs().dr().read().data() as u16 |
| 289 | } | 266 | } |
| 290 | 267 | ||
| 291 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 268 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 269 | self.set_sample_time_all_channels(sample_time); | ||
| 270 | |||
| 292 | Self::configure_channel(channel); | 271 | Self::configure_channel(channel); |
| 293 | T::regs().cfgr1().write(|reg| { | 272 | T::regs().cfgr1().write(|reg| { |
| 294 | reg.set_chselrmod(false); | 273 | reg.set_chselrmod(false); |
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index f9c23d72b..835cc8c63 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs | |||
| @@ -28,20 +28,12 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 28 | } | 28 | } |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | pub struct Vref; | 31 | impl<T: Instance> super::VrefConverter for T { |
| 32 | impl<T: Instance> AdcChannel<T> for Vref {} | 32 | const CHANNEL: u8 = 17; |
| 33 | impl<T: Instance> super::SealedAdcChannel<T> for Vref { | ||
| 34 | fn channel(&self) -> u8 { | ||
| 35 | 17 | ||
| 36 | } | ||
| 37 | } | 33 | } |
| 38 | 34 | ||
| 39 | pub struct Temperature; | 35 | impl<T: Instance> super::TemperatureConverter for T { |
| 40 | impl<T: Instance> AdcChannel<T> for Temperature {} | 36 | const CHANNEL: u8 = 16; |
| 41 | impl<T: Instance> super::SealedAdcChannel<T> for Temperature { | ||
| 42 | fn channel(&self) -> u8 { | ||
| 43 | 16 | ||
| 44 | } | ||
| 45 | } | 37 | } |
| 46 | 38 | ||
| 47 | impl<'d, T: Instance> Adc<'d, T> { | 39 | impl<'d, T: Instance> Adc<'d, T> { |
| @@ -71,10 +63,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 71 | T::Interrupt::unpend(); | 63 | T::Interrupt::unpend(); |
| 72 | unsafe { T::Interrupt::enable() }; | 64 | unsafe { T::Interrupt::enable() }; |
| 73 | 65 | ||
| 74 | Self { | 66 | Self { adc } |
| 75 | adc, | ||
| 76 | sample_time: SampleTime::from_bits(0), | ||
| 77 | } | ||
| 78 | } | 67 | } |
| 79 | 68 | ||
| 80 | fn freq() -> Hertz { | 69 | fn freq() -> Hertz { |
| @@ -94,22 +83,18 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 94 | } | 83 | } |
| 95 | } | 84 | } |
| 96 | 85 | ||
| 97 | pub fn enable_vref(&self) -> Vref { | 86 | pub fn enable_vref(&self) -> super::VrefInt { |
| 98 | T::regs().cr2().modify(|reg| { | 87 | T::regs().cr2().modify(|reg| { |
| 99 | reg.set_tsvrefe(true); | 88 | reg.set_tsvrefe(true); |
| 100 | }); | 89 | }); |
| 101 | Vref {} | 90 | super::VrefInt {} |
| 102 | } | 91 | } |
| 103 | 92 | ||
| 104 | pub fn enable_temperature(&self) -> Temperature { | 93 | pub fn enable_temperature(&self) -> super::Temperature { |
| 105 | T::regs().cr2().modify(|reg| { | 94 | T::regs().cr2().modify(|reg| { |
| 106 | reg.set_tsvrefe(true); | 95 | reg.set_tsvrefe(true); |
| 107 | }); | 96 | }); |
| 108 | Temperature {} | 97 | super::Temperature {} |
| 109 | } | ||
| 110 | |||
| 111 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||
| 112 | self.sample_time = sample_time; | ||
| 113 | } | 98 | } |
| 114 | 99 | ||
| 115 | /// Perform a single conversion. | 100 | /// Perform a single conversion. |
| @@ -134,8 +119,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 134 | T::regs().dr().read().0 as u16 | 119 | T::regs().dr().read().0 as u16 |
| 135 | } | 120 | } |
| 136 | 121 | ||
| 137 | pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 122 | pub async fn read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 138 | Self::set_channel_sample_time(channel.channel(), self.sample_time); | 123 | Self::set_channel_sample_time(channel.channel(), sample_time); |
| 139 | T::regs().cr1().modify(|reg| { | 124 | T::regs().cr1().modify(|reg| { |
| 140 | reg.set_scan(false); | 125 | reg.set_scan(false); |
| 141 | reg.set_discen(false); | 126 | reg.set_discen(false); |
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs index 73ceb087a..f6a4e1209 100644 --- a/embassy-stm32/src/adc/f3.rs +++ b/embassy-stm32/src/adc/f3.rs | |||
| @@ -29,27 +29,12 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 29 | } | 29 | } |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | pub struct Vref; | 32 | impl<T: Instance> super::VrefConverter for T { |
| 33 | impl<T: Instance> AdcChannel<T> for Vref {} | 33 | const CHANNEL: u8 = 18; |
| 34 | impl<T: Instance> super::SealedAdcChannel<T> for Vref { | ||
| 35 | fn channel(&self) -> u8 { | ||
| 36 | 18 | ||
| 37 | } | ||
| 38 | } | ||
| 39 | |||
| 40 | impl Vref { | ||
| 41 | /// The value that vref would be if vdda was at 3300mv | ||
| 42 | pub fn value(&self) -> u16 { | ||
| 43 | crate::pac::VREFINTCAL.data().read() | ||
| 44 | } | ||
| 45 | } | 34 | } |
| 46 | 35 | ||
| 47 | pub struct Temperature; | 36 | impl<T: Instance> super::TemperatureConverter for T { |
| 48 | impl<T: Instance> AdcChannel<T> for Temperature {} | 37 | const CHANNEL: u8 = 16; |
| 49 | impl<T: Instance> super::SealedAdcChannel<T> for Temperature { | ||
| 50 | fn channel(&self) -> u8 { | ||
| 51 | 16 | ||
| 52 | } | ||
| 53 | } | 38 | } |
| 54 | 39 | ||
| 55 | impl<'d, T: Instance> Adc<'d, T> { | 40 | impl<'d, T: Instance> Adc<'d, T> { |
| @@ -90,10 +75,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 90 | T::Interrupt::enable(); | 75 | T::Interrupt::enable(); |
| 91 | } | 76 | } |
| 92 | 77 | ||
| 93 | Self { | 78 | Self { adc } |
| 94 | adc, | ||
| 95 | sample_time: SampleTime::from_bits(0), | ||
| 96 | } | ||
| 97 | } | 79 | } |
| 98 | 80 | ||
| 99 | fn freq() -> Hertz { | 81 | fn freq() -> Hertz { |
| @@ -112,20 +94,16 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 112 | } | 94 | } |
| 113 | } | 95 | } |
| 114 | 96 | ||
| 115 | pub fn enable_vref(&self) -> Vref { | 97 | pub fn enable_vref(&self) -> super::VrefInt { |
| 116 | T::common_regs().ccr().modify(|w| w.set_vrefen(true)); | 98 | T::common_regs().ccr().modify(|w| w.set_vrefen(true)); |
| 117 | 99 | ||
| 118 | Vref {} | 100 | super::VrefInt {} |
| 119 | } | 101 | } |
| 120 | 102 | ||
| 121 | pub fn enable_temperature(&self) -> Temperature { | 103 | pub fn enable_temperature(&self) -> super::Temperature { |
| 122 | T::common_regs().ccr().modify(|w| w.set_tsen(true)); | 104 | T::common_regs().ccr().modify(|w| w.set_tsen(true)); |
| 123 | 105 | ||
| 124 | Temperature {} | 106 | super::Temperature {} |
| 125 | } | ||
| 126 | |||
| 127 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||
| 128 | self.sample_time = sample_time; | ||
| 129 | } | 107 | } |
| 130 | 108 | ||
| 131 | /// Perform a single conversion. | 109 | /// Perform a single conversion. |
| @@ -150,8 +128,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 150 | T::regs().dr().read().rdata() | 128 | T::regs().dr().read().rdata() |
| 151 | } | 129 | } |
| 152 | 130 | ||
| 153 | pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 131 | pub async fn read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 154 | Self::set_channel_sample_time(channel.channel(), self.sample_time); | 132 | Self::set_channel_sample_time(channel.channel(), sample_time); |
| 155 | 133 | ||
| 156 | // Configure the channel to sample | 134 | // Configure the channel to sample |
| 157 | T::regs().sqr1().write(|w| w.set_sq(0, channel.channel())); | 135 | T::regs().sqr1().write(|w| w.set_sq(0, channel.channel())); |
diff --git a/embassy-stm32/src/adc/f3_v1_1.rs b/embassy-stm32/src/adc/f3_v1_1.rs index cd5de54f5..919ac3cc0 100644 --- a/embassy-stm32/src/adc/f3_v1_1.rs +++ b/embassy-stm32/src/adc/f3_v1_1.rs | |||
| @@ -79,7 +79,7 @@ impl<T: Instance> Vref<T> { | |||
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | pub async fn calibrate(&mut self, adc: &mut Adc<'_, T>) -> Calibration { | 81 | pub async fn calibrate(&mut self, adc: &mut Adc<'_, T>) -> Calibration { |
| 82 | let vref_val = adc.read(self).await; | 82 | let vref_val = adc.read(self, SampleTime::from(0)).await; |
| 83 | Calibration { | 83 | Calibration { |
| 84 | vref_cal: self.calibrated_value(), | 84 | vref_cal: self.calibrated_value(), |
| 85 | vref_val, | 85 | vref_val, |
| @@ -270,7 +270,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 270 | } | 270 | } |
| 271 | } | 271 | } |
| 272 | 272 | ||
| 273 | pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 273 | pub async fn read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 274 | self.set_sample_time(channel, sample_time).await; | ||
| 274 | self.set_sample_sequence(&[channel.channel()]).await; | 275 | self.set_sample_sequence(&[channel.channel()]).await; |
| 275 | self.convert().await | 276 | self.convert().await |
| 276 | } | 277 | } |
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index 3767820cf..5d9c6ff74 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs | |||
| @@ -35,34 +35,6 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60); | |||
| 35 | #[cfg(stm32h7)] | 35 | #[cfg(stm32h7)] |
| 36 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); | 36 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); |
| 37 | 37 | ||
| 38 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs | ||
| 39 | /// Internal voltage reference channel. | ||
| 40 | pub struct VrefInt; | ||
| 41 | impl<T: Instance + VrefChannel> AdcChannel<T> for VrefInt {} | ||
| 42 | impl<T: Instance + VrefChannel> super::SealedAdcChannel<T> for VrefInt { | ||
| 43 | fn channel(&self) -> u8 { | ||
| 44 | T::CHANNEL | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | /// Internal temperature channel. | ||
| 49 | pub struct Temperature; | ||
| 50 | impl<T: Instance + TemperatureChannel> AdcChannel<T> for Temperature {} | ||
| 51 | impl<T: Instance + TemperatureChannel> super::SealedAdcChannel<T> for Temperature { | ||
| 52 | fn channel(&self) -> u8 { | ||
| 53 | T::CHANNEL | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | /// Internal battery voltage channel. | ||
| 58 | pub struct Vbat; | ||
| 59 | impl<T: Instance + VBatChannel> AdcChannel<T> for Vbat {} | ||
| 60 | impl<T: Instance + VBatChannel> super::SealedAdcChannel<T> for Vbat { | ||
| 61 | fn channel(&self) -> u8 { | ||
| 62 | T::CHANNEL | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | // NOTE (unused): The prescaler enum closely copies the hardware capabilities, | 38 | // NOTE (unused): The prescaler enum closely copies the hardware capabilities, |
| 67 | // but high prescaling doesn't make a lot of sense in the current implementation and is ommited. | 39 | // but high prescaling doesn't make a lot of sense in the current implementation and is ommited. |
| 68 | #[allow(unused)] | 40 | #[allow(unused)] |
| @@ -168,17 +140,14 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 168 | ); | 140 | ); |
| 169 | } | 141 | } |
| 170 | 142 | ||
| 171 | let mut s = Self { | 143 | let mut s = Self { adc }; |
| 172 | adc, | ||
| 173 | sample_time: SampleTime::from_bits(0), | ||
| 174 | }; | ||
| 175 | s.power_up(); | 144 | s.power_up(); |
| 176 | s.configure_differential_inputs(); | 145 | s.configure_differential_inputs(); |
| 177 | 146 | ||
| 178 | s.calibrate(); | 147 | s.calibrate(); |
| 179 | blocking_delay_us(1); | 148 | blocking_delay_us(1); |
| 180 | 149 | ||
| 181 | s.enable(); | 150 | Self::enable(); |
| 182 | s.configure(); | 151 | s.configure(); |
| 183 | 152 | ||
| 184 | s | 153 | s |
| @@ -223,7 +192,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 223 | blocking_delay_us(20); | 192 | blocking_delay_us(20); |
| 224 | } | 193 | } |
| 225 | 194 | ||
| 226 | fn enable(&mut self) { | 195 | fn enable() { |
| 227 | // Make sure bits are off | 196 | // Make sure bits are off |
| 228 | while T::regs().cr().read().addis() { | 197 | while T::regs().cr().read().addis() { |
| 229 | // spin | 198 | // spin |
| @@ -253,39 +222,39 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 253 | } | 222 | } |
| 254 | 223 | ||
| 255 | /// Enable reading the voltage reference internal channel. | 224 | /// Enable reading the voltage reference internal channel. |
| 256 | pub fn enable_vrefint(&self) -> VrefInt | 225 | pub fn enable_vrefint(&self) -> super::VrefInt |
| 257 | where | 226 | where |
| 258 | T: VrefChannel, | 227 | T: super::VrefConverter, |
| 259 | { | 228 | { |
| 260 | T::common_regs().ccr().modify(|reg| { | 229 | T::common_regs().ccr().modify(|reg| { |
| 261 | reg.set_vrefen(true); | 230 | reg.set_vrefen(true); |
| 262 | }); | 231 | }); |
| 263 | 232 | ||
| 264 | VrefInt {} | 233 | super::VrefInt {} |
| 265 | } | 234 | } |
| 266 | 235 | ||
| 267 | /// Enable reading the temperature internal channel. | 236 | /// Enable reading the temperature internal channel. |
| 268 | pub fn enable_temperature(&self) -> Temperature | 237 | pub fn enable_temperature(&self) -> super::Temperature |
| 269 | where | 238 | where |
| 270 | T: TemperatureChannel, | 239 | T: super::TemperatureConverter, |
| 271 | { | 240 | { |
| 272 | T::common_regs().ccr().modify(|reg| { | 241 | T::common_regs().ccr().modify(|reg| { |
| 273 | reg.set_vsenseen(true); | 242 | reg.set_vsenseen(true); |
| 274 | }); | 243 | }); |
| 275 | 244 | ||
| 276 | Temperature {} | 245 | super::Temperature {} |
| 277 | } | 246 | } |
| 278 | 247 | ||
| 279 | /// Enable reading the vbat internal channel. | 248 | /// Enable reading the vbat internal channel. |
| 280 | pub fn enable_vbat(&self) -> Vbat | 249 | pub fn enable_vbat(&self) -> super::Vbat |
| 281 | where | 250 | where |
| 282 | T: VBatChannel, | 251 | T: super::VBatConverter, |
| 283 | { | 252 | { |
| 284 | T::common_regs().ccr().modify(|reg| { | 253 | T::common_regs().ccr().modify(|reg| { |
| 285 | reg.set_vbaten(true); | 254 | reg.set_vbaten(true); |
| 286 | }); | 255 | }); |
| 287 | 256 | ||
| 288 | Vbat {} | 257 | super::Vbat {} |
| 289 | } | 258 | } |
| 290 | 259 | ||
| 291 | /// Enable differential channel. | 260 | /// Enable differential channel. |
| @@ -297,7 +266,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 297 | /// channel on the other ADC unusable. The only exception is when ADC master and the slave | 266 | /// channel on the other ADC unusable. The only exception is when ADC master and the slave |
| 298 | /// operate in interleaved mode. | 267 | /// operate in interleaved mode. |
| 299 | #[cfg(stm32g4)] | 268 | #[cfg(stm32g4)] |
| 300 | pub fn set_differential_channel(&mut self, ch: usize, enable: bool) { | 269 | fn set_differential_channel(&mut self, ch: usize, enable: bool) { |
| 301 | T::regs().cr().modify(|w| w.set_aden(false)); // disable adc | 270 | T::regs().cr().modify(|w| w.set_aden(false)); // disable adc |
| 302 | T::regs().difsel().modify(|w| { | 271 | T::regs().difsel().modify(|w| { |
| 303 | w.set_difsel( | 272 | w.set_difsel( |
| @@ -350,11 +319,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 350 | // T::regs().cfgr2().modify(|reg| reg.set_jovse(enable)); | 319 | // T::regs().cfgr2().modify(|reg| reg.set_jovse(enable)); |
| 351 | // } | 320 | // } |
| 352 | 321 | ||
| 353 | /// Set the ADC sample time. | ||
| 354 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||
| 355 | self.sample_time = sample_time; | ||
| 356 | } | ||
| 357 | |||
| 358 | /// Set the ADC resolution. | 322 | /// Set the ADC resolution. |
| 359 | pub fn set_resolution(&mut self, resolution: Resolution) { | 323 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 360 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); | 324 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); |
| @@ -380,10 +344,10 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 380 | } | 344 | } |
| 381 | 345 | ||
| 382 | /// Read an ADC pin. | 346 | /// Read an ADC pin. |
| 383 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 347 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 384 | channel.setup(); | 348 | channel.setup(); |
| 385 | 349 | ||
| 386 | self.read_channel(channel) | 350 | self.read_channel(channel, sample_time) |
| 387 | } | 351 | } |
| 388 | 352 | ||
| 389 | /// Start regular adc conversion | 353 | /// Start regular adc conversion |
| @@ -399,7 +363,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 399 | } | 363 | } |
| 400 | 364 | ||
| 401 | /// Teardown method for stopping regular ADC conversions | 365 | /// Teardown method for stopping regular ADC conversions |
| 402 | pub(super) fn teardown_adc() { | 366 | pub(super) fn teardown_dma() { |
| 403 | Self::stop_regular_conversions(); | 367 | Self::stop_regular_conversions(); |
| 404 | 368 | ||
| 405 | // Disable dma control | 369 | // Disable dma control |
| @@ -454,39 +418,13 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 454 | 418 | ||
| 455 | // Ensure no conversions are ongoing and ADC is enabled. | 419 | // Ensure no conversions are ongoing and ADC is enabled. |
| 456 | Self::stop_regular_conversions(); | 420 | Self::stop_regular_conversions(); |
| 457 | self.enable(); | 421 | Self::enable(); |
| 458 | 422 | ||
| 459 | // Set sequence length | 423 | Self::configure_sequence(sequence.map(|(channel, sample_time)| { |
| 460 | T::regs().sqr1().modify(|w| { | 424 | channel.setup(); |
| 461 | w.set_l(sequence.len() as u8 - 1); | 425 | |
| 462 | }); | 426 | (channel.channel, sample_time) |
| 463 | // Configure channels and ranks | 427 | })); |
| 464 | for (_i, (channel, sample_time)) in sequence.enumerate() { | ||
| 465 | Self::configure_channel(channel, sample_time); | ||
| 466 | match _i { | ||
| 467 | 0..=3 => { | ||
| 468 | T::regs().sqr1().modify(|w| { | ||
| 469 | w.set_sq(_i, channel.channel()); | ||
| 470 | }); | ||
| 471 | } | ||
| 472 | 4..=8 => { | ||
| 473 | T::regs().sqr2().modify(|w| { | ||
| 474 | w.set_sq(_i - 4, channel.channel()); | ||
| 475 | }); | ||
| 476 | } | ||
| 477 | 9..=13 => { | ||
| 478 | T::regs().sqr3().modify(|w| { | ||
| 479 | w.set_sq(_i - 9, channel.channel()); | ||
| 480 | }); | ||
| 481 | } | ||
| 482 | 14..=15 => { | ||
| 483 | T::regs().sqr4().modify(|w| { | ||
| 484 | w.set_sq(_i - 14, channel.channel()); | ||
| 485 | }); | ||
| 486 | } | ||
| 487 | _ => unreachable!(), | ||
| 488 | } | ||
| 489 | } | ||
| 490 | 428 | ||
| 491 | // Set continuous mode with oneshot dma. | 429 | // Set continuous mode with oneshot dma. |
| 492 | // Clear overrun flag before starting transfer. | 430 | // Clear overrun flag before starting transfer. |
| @@ -529,6 +467,47 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 529 | }); | 467 | }); |
| 530 | } | 468 | } |
| 531 | 469 | ||
| 470 | pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = (u8, SampleTime)>) { | ||
| 471 | // Set sequence length | ||
| 472 | T::regs().sqr1().modify(|w| { | ||
| 473 | w.set_l(sequence.len() as u8 - 1); | ||
| 474 | }); | ||
| 475 | |||
| 476 | // Configure channels and ranks | ||
| 477 | for (_i, (ch, sample_time)) in sequence.enumerate() { | ||
| 478 | let sample_time = sample_time.into(); | ||
| 479 | if ch <= 9 { | ||
| 480 | T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time)); | ||
| 481 | } else { | ||
| 482 | T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); | ||
| 483 | } | ||
| 484 | |||
| 485 | match _i { | ||
| 486 | 0..=3 => { | ||
| 487 | T::regs().sqr1().modify(|w| { | ||
| 488 | w.set_sq(_i, ch); | ||
| 489 | }); | ||
| 490 | } | ||
| 491 | 4..=8 => { | ||
| 492 | T::regs().sqr2().modify(|w| { | ||
| 493 | w.set_sq(_i - 4, ch); | ||
| 494 | }); | ||
| 495 | } | ||
| 496 | 9..=13 => { | ||
| 497 | T::regs().sqr3().modify(|w| { | ||
| 498 | w.set_sq(_i - 9, ch); | ||
| 499 | }); | ||
| 500 | } | ||
| 501 | 14..=15 => { | ||
| 502 | T::regs().sqr4().modify(|w| { | ||
| 503 | w.set_sq(_i - 14, ch); | ||
| 504 | }); | ||
| 505 | } | ||
| 506 | _ => unreachable!(), | ||
| 507 | } | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 532 | /// Set external trigger for regular conversion sequence | 511 | /// Set external trigger for regular conversion sequence |
| 533 | fn set_regular_conversion_trigger(&mut self, trigger: ConversionTrigger) { | 512 | fn set_regular_conversion_trigger(&mut self, trigger: ConversionTrigger) { |
| 534 | T::regs().cfgr().modify(|r| { | 513 | T::regs().cfgr().modify(|r| { |
| @@ -582,43 +561,15 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 582 | ); | 561 | ); |
| 583 | // reset conversions and enable the adc | 562 | // reset conversions and enable the adc |
| 584 | Self::stop_regular_conversions(); | 563 | Self::stop_regular_conversions(); |
| 585 | self.enable(); | 564 | Self::enable(); |
| 586 | 565 | ||
| 587 | //adc side setup | 566 | //adc side setup |
| 588 | 567 | ||
| 589 | // Set sequence length | 568 | Self::configure_sequence(sequence.map(|(mut channel, sample_time)| { |
| 590 | T::regs().sqr1().modify(|w| { | 569 | channel.setup(); |
| 591 | w.set_l(sequence.len() as u8 - 1); | ||
| 592 | }); | ||
| 593 | 570 | ||
| 594 | // Configure channels and ranks | 571 | (channel.channel, sample_time) |
| 595 | for (_i, (mut channel, sample_time)) in sequence.enumerate() { | 572 | })); |
| 596 | Self::configure_channel(&mut channel, sample_time); | ||
| 597 | |||
| 598 | match _i { | ||
| 599 | 0..=3 => { | ||
| 600 | T::regs().sqr1().modify(|w| { | ||
| 601 | w.set_sq(_i, channel.channel()); | ||
| 602 | }); | ||
| 603 | } | ||
| 604 | 4..=8 => { | ||
| 605 | T::regs().sqr2().modify(|w| { | ||
| 606 | w.set_sq(_i - 4, channel.channel()); | ||
| 607 | }); | ||
| 608 | } | ||
| 609 | 9..=13 => { | ||
| 610 | T::regs().sqr3().modify(|w| { | ||
| 611 | w.set_sq(_i - 9, channel.channel()); | ||
| 612 | }); | ||
| 613 | } | ||
| 614 | 14..=15 => { | ||
| 615 | T::regs().sqr4().modify(|w| { | ||
| 616 | w.set_sq(_i - 14, channel.channel()); | ||
| 617 | }); | ||
| 618 | } | ||
| 619 | _ => unreachable!(), | ||
| 620 | } | ||
| 621 | } | ||
| 622 | 573 | ||
| 623 | // Clear overrun flag before starting transfer. | 574 | // Clear overrun flag before starting transfer. |
| 624 | T::regs().isr().modify(|reg| { | 575 | T::regs().isr().modify(|reg| { |
| @@ -691,7 +642,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 691 | ); | 642 | ); |
| 692 | 643 | ||
| 693 | Self::stop_regular_conversions(); | 644 | Self::stop_regular_conversions(); |
| 694 | self.enable(); | 645 | Self::enable(); |
| 695 | 646 | ||
| 696 | T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); | 647 | T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); |
| 697 | 648 | ||
| @@ -755,12 +706,10 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 755 | ( | 706 | ( |
| 756 | Self { | 707 | Self { |
| 757 | adc: self.adc.clone_unchecked(), | 708 | adc: self.adc.clone_unchecked(), |
| 758 | sample_time: self.sample_time, | ||
| 759 | } | 709 | } |
| 760 | .into_ring_buffered(dma, dma_buf, regular_sequence, regular_conversion_mode), | 710 | .into_ring_buffered(dma, dma_buf, regular_sequence, regular_conversion_mode), |
| 761 | Self { | 711 | Self { |
| 762 | adc: self.adc.clone_unchecked(), | 712 | adc: self.adc.clone_unchecked(), |
| 763 | sample_time: self.sample_time, | ||
| 764 | } | 713 | } |
| 765 | .setup_injected_conversions(injected_sequence, injected_trigger, injected_interrupt), | 714 | .setup_injected_conversions(injected_sequence, injected_trigger, injected_interrupt), |
| 766 | ) | 715 | ) |
| @@ -805,8 +754,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 805 | Self::set_channel_sample_time(channel.channel(), sample_time); | 754 | Self::set_channel_sample_time(channel.channel(), sample_time); |
| 806 | } | 755 | } |
| 807 | 756 | ||
| 808 | fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 757 | fn read_channel(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 809 | Self::configure_channel(channel, self.sample_time); | 758 | Self::configure_channel(channel, sample_time); |
| 810 | #[cfg(stm32h7)] | 759 | #[cfg(stm32h7)] |
| 811 | { | 760 | { |
| 812 | T::regs().cfgr2().modify(|w| w.set_lshift(0)); | 761 | T::regs().cfgr2().modify(|w| w.set_lshift(0)); |
| @@ -860,62 +809,49 @@ impl<T: Instance, const N: usize> InjectedAdc<T, N> { | |||
| 860 | } | 809 | } |
| 861 | } | 810 | } |
| 862 | 811 | ||
| 863 | /// Implemented for ADCs that have a Temperature channel | ||
| 864 | pub trait TemperatureChannel { | ||
| 865 | const CHANNEL: u8; | ||
| 866 | } | ||
| 867 | /// Implemented for ADCs that have a Vref channel | ||
| 868 | pub trait VrefChannel { | ||
| 869 | const CHANNEL: u8; | ||
| 870 | } | ||
| 871 | /// Implemented for ADCs that have a VBat channel | ||
| 872 | pub trait VBatChannel { | ||
| 873 | const CHANNEL: u8; | ||
| 874 | } | ||
| 875 | |||
| 876 | #[cfg(stm32g4)] | 812 | #[cfg(stm32g4)] |
| 877 | mod g4 { | 813 | mod g4 { |
| 878 | pub use super::*; | 814 | use crate::adc::{TemperatureConverter, VBatConverter, VrefConverter}; |
| 879 | 815 | ||
| 880 | impl TemperatureChannel for crate::peripherals::ADC1 { | 816 | impl TemperatureConverter for crate::peripherals::ADC1 { |
| 881 | const CHANNEL: u8 = 16; | 817 | const CHANNEL: u8 = 16; |
| 882 | } | 818 | } |
| 883 | 819 | ||
| 884 | impl VrefChannel for crate::peripherals::ADC1 { | 820 | impl VrefConverter for crate::peripherals::ADC1 { |
| 885 | const CHANNEL: u8 = 18; | 821 | const CHANNEL: u8 = 18; |
| 886 | } | 822 | } |
| 887 | 823 | ||
| 888 | impl VBatChannel for crate::peripherals::ADC1 { | 824 | impl VBatConverter for crate::peripherals::ADC1 { |
| 889 | const CHANNEL: u8 = 17; | 825 | const CHANNEL: u8 = 17; |
| 890 | } | 826 | } |
| 891 | 827 | ||
| 892 | #[cfg(peri_adc3_common)] | 828 | #[cfg(peri_adc3_common)] |
| 893 | impl VrefChannel for crate::peripherals::ADC3 { | 829 | impl VrefConverter for crate::peripherals::ADC3 { |
| 894 | const CHANNEL: u8 = 18; | 830 | const CHANNEL: u8 = 18; |
| 895 | } | 831 | } |
| 896 | 832 | ||
| 897 | #[cfg(peri_adc3_common)] | 833 | #[cfg(peri_adc3_common)] |
| 898 | impl VBatChannel for crate::peripherals::ADC3 { | 834 | impl VBatConverter for crate::peripherals::ADC3 { |
| 899 | const CHANNEL: u8 = 17; | 835 | const CHANNEL: u8 = 17; |
| 900 | } | 836 | } |
| 901 | 837 | ||
| 902 | #[cfg(not(stm32g4x1))] | 838 | #[cfg(not(stm32g4x1))] |
| 903 | impl VrefChannel for crate::peripherals::ADC4 { | 839 | impl VrefConverter for crate::peripherals::ADC4 { |
| 904 | const CHANNEL: u8 = 18; | 840 | const CHANNEL: u8 = 18; |
| 905 | } | 841 | } |
| 906 | 842 | ||
| 907 | #[cfg(not(stm32g4x1))] | 843 | #[cfg(not(stm32g4x1))] |
| 908 | impl TemperatureChannel for crate::peripherals::ADC5 { | 844 | impl TemperatureConverter for crate::peripherals::ADC5 { |
| 909 | const CHANNEL: u8 = 4; | 845 | const CHANNEL: u8 = 4; |
| 910 | } | 846 | } |
| 911 | 847 | ||
| 912 | #[cfg(not(stm32g4x1))] | 848 | #[cfg(not(stm32g4x1))] |
| 913 | impl VrefChannel for crate::peripherals::ADC5 { | 849 | impl VrefConverter for crate::peripherals::ADC5 { |
| 914 | const CHANNEL: u8 = 18; | 850 | const CHANNEL: u8 = 18; |
| 915 | } | 851 | } |
| 916 | 852 | ||
| 917 | #[cfg(not(stm32g4x1))] | 853 | #[cfg(not(stm32g4x1))] |
| 918 | impl VBatChannel for crate::peripherals::ADC5 { | 854 | impl VBatConverter for crate::peripherals::ADC5 { |
| 919 | const CHANNEL: u8 = 17; | 855 | const CHANNEL: u8 = 17; |
| 920 | } | 856 | } |
| 921 | } | 857 | } |
| @@ -923,13 +859,13 @@ mod g4 { | |||
| 923 | // TODO this should look at each ADC individually and impl the correct channels | 859 | // TODO this should look at each ADC individually and impl the correct channels |
| 924 | #[cfg(stm32h7)] | 860 | #[cfg(stm32h7)] |
| 925 | mod h7 { | 861 | mod h7 { |
| 926 | impl<T: Instance> TemperatureChannel for T { | 862 | impl<T: Instance> TemperatureConverter for T { |
| 927 | const CHANNEL: u8 = 18; | 863 | const CHANNEL: u8 = 18; |
| 928 | } | 864 | } |
| 929 | impl<T: Instance> VrefChannel for T { | 865 | impl<T: Instance> VrefConverter for T { |
| 930 | const CHANNEL: u8 = 19; | 866 | const CHANNEL: u8 = 19; |
| 931 | } | 867 | } |
| 932 | impl<T: Instance> VBatChannel for T { | 868 | impl<T: Instance> VBatConverter for T { |
| 933 | // TODO this should be 14 for H7a/b/35 | 869 | // TODO this should be 14 for H7a/b/35 |
| 934 | const CHANNEL: u8 = 17; | 870 | const CHANNEL: u8 = 17; |
| 935 | } | 871 | } |
diff --git a/embassy-stm32/src/adc/injected.rs b/embassy-stm32/src/adc/injected.rs index 0e4fe5847..f9f1bba2a 100644 --- a/embassy-stm32/src/adc/injected.rs +++ b/embassy-stm32/src/adc/injected.rs | |||
| @@ -38,7 +38,7 @@ impl<T: Instance, const N: usize> InjectedAdc<T, N> { | |||
| 38 | 38 | ||
| 39 | impl<T: Instance, const N: usize> Drop for InjectedAdc<T, N> { | 39 | impl<T: Instance, const N: usize> Drop for InjectedAdc<T, N> { |
| 40 | fn drop(&mut self) { | 40 | fn drop(&mut self) { |
| 41 | Adc::<T>::teardown_adc(); | 41 | Adc::<T>::teardown_dma(); |
| 42 | compiler_fence(Ordering::SeqCst); | 42 | compiler_fence(Ordering::SeqCst); |
| 43 | } | 43 | } |
| 44 | } | 44 | } |
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index ea7341f75..3bf893a35 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs | |||
| @@ -47,8 +47,6 @@ dma_trait!(RxDma4, adc4::Instance); | |||
| 47 | pub struct Adc<'d, T: Instance> { | 47 | pub struct Adc<'d, T: Instance> { |
| 48 | #[allow(unused)] | 48 | #[allow(unused)] |
| 49 | adc: crate::Peri<'d, T>, | 49 | adc: crate::Peri<'d, T>, |
| 50 | #[cfg(not(any(adc_f3v3, adc_f3v2, adc_wba)))] | ||
| 51 | sample_time: SampleTime, | ||
| 52 | } | 50 | } |
| 53 | 51 | ||
| 54 | #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] | 52 | #[cfg(any(adc_f1, adc_f3v1, adc_v1, adc_l0, adc_f3v2))] |
| @@ -102,6 +100,55 @@ pub(crate) fn blocking_delay_us(us: u32) { | |||
| 102 | } | 100 | } |
| 103 | } | 101 | } |
| 104 | 102 | ||
| 103 | /// Implemented for ADCs that have a Temperature channel | ||
| 104 | pub trait TemperatureConverter { | ||
| 105 | const CHANNEL: u8; | ||
| 106 | } | ||
| 107 | /// Implemented for ADCs that have a Vref channel | ||
| 108 | pub trait VrefConverter { | ||
| 109 | const CHANNEL: u8; | ||
| 110 | } | ||
| 111 | /// Implemented for ADCs that have a VBat channel | ||
| 112 | pub trait VBatConverter { | ||
| 113 | const CHANNEL: u8; | ||
| 114 | } | ||
| 115 | |||
| 116 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs | ||
| 117 | /// Internal voltage reference channel. | ||
| 118 | pub struct VrefInt; | ||
| 119 | impl<T: Instance + VrefConverter> AdcChannel<T> for VrefInt {} | ||
| 120 | impl<T: Instance + VrefConverter> SealedAdcChannel<T> for VrefInt { | ||
| 121 | fn channel(&self) -> u8 { | ||
| 122 | T::CHANNEL | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | impl VrefInt { | ||
| 127 | #[cfg(any(adc_f3v1, adc_f3v2))] | ||
| 128 | /// The value that vref would be if vdda was at 3300mv | ||
| 129 | pub fn calibrated_value(&self) -> u16 { | ||
| 130 | crate::pac::VREFINTCAL.data().read() | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | /// Internal temperature channel. | ||
| 135 | pub struct Temperature; | ||
| 136 | impl<T: Instance + TemperatureConverter> AdcChannel<T> for Temperature {} | ||
| 137 | impl<T: Instance + TemperatureConverter> SealedAdcChannel<T> for Temperature { | ||
| 138 | fn channel(&self) -> u8 { | ||
| 139 | T::CHANNEL | ||
| 140 | } | ||
| 141 | } | ||
| 142 | |||
| 143 | /// Internal battery voltage channel. | ||
| 144 | pub struct Vbat; | ||
| 145 | impl<T: Instance + VBatConverter> AdcChannel<T> for Vbat {} | ||
| 146 | impl<T: Instance + VBatConverter> SealedAdcChannel<T> for Vbat { | ||
| 147 | fn channel(&self) -> u8 { | ||
| 148 | T::CHANNEL | ||
| 149 | } | ||
| 150 | } | ||
| 151 | |||
| 105 | /// ADC instance. | 152 | /// ADC instance. |
| 106 | #[cfg(not(any( | 153 | #[cfg(not(any( |
| 107 | adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, | 154 | adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, |
diff --git a/embassy-stm32/src/adc/ringbuffered.rs b/embassy-stm32/src/adc/ringbuffered.rs index 971c8195c..024c6acdc 100644 --- a/embassy-stm32/src/adc/ringbuffered.rs +++ b/embassy-stm32/src/adc/ringbuffered.rs | |||
| @@ -172,7 +172,7 @@ impl<'d, T: Instance> RingBufferedAdc<'d, T> { | |||
| 172 | 172 | ||
| 173 | impl<T: Instance> Drop for RingBufferedAdc<'_, T> { | 173 | impl<T: Instance> Drop for RingBufferedAdc<'_, T> { |
| 174 | fn drop(&mut self) { | 174 | fn drop(&mut self) { |
| 175 | Adc::<T>::teardown_adc(); | 175 | Adc::<T>::teardown_dma(); |
| 176 | 176 | ||
| 177 | compiler_fence(Ordering::SeqCst); | 177 | compiler_fence(Ordering::SeqCst); |
| 178 | 178 | ||
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index a5869d110..97557ee8a 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs | |||
| @@ -5,10 +5,11 @@ use core::task::Poll; | |||
| 5 | #[cfg(adc_l0)] | 5 | #[cfg(adc_l0)] |
| 6 | use stm32_metapac::adc::vals::Ckmode; | 6 | use stm32_metapac::adc::vals::Ckmode; |
| 7 | 7 | ||
| 8 | use super::blocking_delay_us; | 8 | #[cfg(not(adc_l0))] |
| 9 | use super::Vbat; | ||
| 10 | use super::{Temperature, VrefInt, blocking_delay_us}; | ||
| 9 | use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime}; | 11 | use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime}; |
| 10 | use crate::interrupt::typelevel::Interrupt; | 12 | use crate::interrupt::typelevel::Interrupt; |
| 11 | use crate::peripherals::ADC1; | ||
| 12 | use crate::{Peri, interrupt, rcc}; | 13 | use crate::{Peri, interrupt, rcc}; |
| 13 | 14 | ||
| 14 | mod watchdog_v1; | 15 | mod watchdog_v1; |
| @@ -42,32 +43,23 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | #[cfg(not(adc_l0))] | 45 | #[cfg(not(adc_l0))] |
| 45 | pub struct Vbat; | 46 | impl super::VBatConverter for crate::peripherals::ADC1 { |
| 46 | 47 | const CHANNEL: u8 = 18; | |
| 47 | #[cfg(not(adc_l0))] | 48 | } |
| 48 | impl AdcChannel<ADC1> for Vbat {} | ||
| 49 | 49 | ||
| 50 | #[cfg(not(adc_l0))] | 50 | #[cfg(not(adc_l0))] |
| 51 | impl super::SealedAdcChannel<ADC1> for Vbat { | 51 | impl super::VrefConverter for crate::peripherals::ADC1 { |
| 52 | fn channel(&self) -> u8 { | 52 | const CHANNEL: u8 = 17; |
| 53 | 18 | ||
| 54 | } | ||
| 55 | } | 53 | } |
| 56 | 54 | ||
| 57 | pub struct Vref; | 55 | #[cfg(adc_l0)] |
| 58 | impl AdcChannel<ADC1> for Vref {} | 56 | impl super::VrefConverter for crate::peripherals::ADC1 { |
| 59 | impl super::SealedAdcChannel<ADC1> for Vref { | 57 | const CHANNEL: u8 = 18; |
| 60 | fn channel(&self) -> u8 { | ||
| 61 | 17 | ||
| 62 | } | ||
| 63 | } | 58 | } |
| 64 | 59 | ||
| 65 | pub struct Temperature; | 60 | #[cfg(not(adc_l0))] |
| 66 | impl AdcChannel<ADC1> for Temperature {} | 61 | impl super::TemperatureConverter for crate::peripherals::ADC1 { |
| 67 | impl super::SealedAdcChannel<ADC1> for Temperature { | 62 | const CHANNEL: u8 = 16; |
| 68 | fn channel(&self) -> u8 { | ||
| 69 | if cfg!(adc_l0) { 18 } else { 16 } | ||
| 70 | } | ||
| 71 | } | 63 | } |
| 72 | 64 | ||
| 73 | impl<'d, T: Instance> Adc<'d, T> { | 65 | impl<'d, T: Instance> Adc<'d, T> { |
| @@ -114,10 +106,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 114 | T::Interrupt::enable(); | 106 | T::Interrupt::enable(); |
| 115 | } | 107 | } |
| 116 | 108 | ||
| 117 | Self { | 109 | Self { adc } |
| 118 | adc, | ||
| 119 | sample_time: SampleTime::from_bits(0), | ||
| 120 | } | ||
| 121 | } | 110 | } |
| 122 | 111 | ||
| 123 | #[cfg(not(adc_l0))] | 112 | #[cfg(not(adc_l0))] |
| @@ -130,12 +119,12 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 130 | Vbat | 119 | Vbat |
| 131 | } | 120 | } |
| 132 | 121 | ||
| 133 | pub fn enable_vref(&self) -> Vref { | 122 | pub fn enable_vref(&self) -> VrefInt { |
| 134 | // Table 28. Embedded internal reference voltage | 123 | // Table 28. Embedded internal reference voltage |
| 135 | // tstart = 10μs | 124 | // tstart = 10μs |
| 136 | T::regs().ccr().modify(|reg| reg.set_vrefen(true)); | 125 | T::regs().ccr().modify(|reg| reg.set_vrefen(true)); |
| 137 | blocking_delay_us(10); | 126 | blocking_delay_us(10); |
| 138 | Vref | 127 | VrefInt |
| 139 | } | 128 | } |
| 140 | 129 | ||
| 141 | pub fn enable_temperature(&self) -> Temperature { | 130 | pub fn enable_temperature(&self) -> Temperature { |
| @@ -149,10 +138,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 149 | Temperature | 138 | Temperature |
| 150 | } | 139 | } |
| 151 | 140 | ||
| 152 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||
| 153 | self.sample_time = sample_time; | ||
| 154 | } | ||
| 155 | |||
| 156 | pub fn set_resolution(&mut self, resolution: Resolution) { | 141 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 157 | T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); | 142 | T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); |
| 158 | } | 143 | } |
| @@ -163,12 +148,13 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 163 | T::regs().cfgr2().modify(|reg| reg.set_ckmode(ckmode)); | 148 | T::regs().cfgr2().modify(|reg| reg.set_ckmode(ckmode)); |
| 164 | } | 149 | } |
| 165 | 150 | ||
| 166 | pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 151 | pub async fn read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 167 | let ch_num = channel.channel(); | 152 | let ch_num = channel.channel(); |
| 168 | channel.setup(); | 153 | channel.setup(); |
| 169 | 154 | ||
| 170 | // A.7.5 Single conversion sequence code example - Software trigger | 155 | // A.7.5 Single conversion sequence code example - Software trigger |
| 171 | T::regs().chselr().write(|reg| reg.set_chsel_x(ch_num as usize, true)); | 156 | T::regs().chselr().write(|reg| reg.set_chsel_x(ch_num as usize, true)); |
| 157 | T::regs().smpr().modify(|reg| reg.set_smp(sample_time.into())); | ||
| 172 | 158 | ||
| 173 | self.convert().await | 159 | self.convert().await |
| 174 | } | 160 | } |
| @@ -179,7 +165,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 179 | reg.set_eosmp(true); | 165 | reg.set_eosmp(true); |
| 180 | }); | 166 | }); |
| 181 | 167 | ||
| 182 | T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into())); | ||
| 183 | T::regs().ier().modify(|w| w.set_eocie(true)); | 168 | T::regs().ier().modify(|w| w.set_eocie(true)); |
| 184 | T::regs().cr().modify(|reg| reg.set_adstart(true)); | 169 | T::regs().cr().modify(|reg| reg.set_adstart(true)); |
| 185 | 170 | ||
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index 90c6294d2..88a8b96ed 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | use core::mem; | 1 | use core::mem; |
| 2 | use core::sync::atomic::{Ordering, compiler_fence}; | 2 | use core::sync::atomic::{Ordering, compiler_fence}; |
| 3 | 3 | ||
| 4 | use super::blocking_delay_us; | 4 | use super::{Temperature, Vbat, VrefInt, blocking_delay_us}; |
| 5 | use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; | 5 | use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; |
| 6 | use crate::pac::adc::vals; | 6 | use crate::pac::adc::vals; |
| 7 | use crate::peripherals::ADC1; | ||
| 8 | use crate::time::Hertz; | 7 | use crate::time::Hertz; |
| 9 | use crate::{Peri, rcc}; | 8 | use crate::{Peri, rcc}; |
| 10 | 9 | ||
| @@ -23,12 +22,22 @@ pub const VREF_DEFAULT_MV: u32 = 3300; | |||
| 23 | /// VREF voltage used for factory calibration of VREFINTCAL register. | 22 | /// VREF voltage used for factory calibration of VREFINTCAL register. |
| 24 | pub const VREF_CALIB_MV: u32 = 3300; | 23 | pub const VREF_CALIB_MV: u32 = 3300; |
| 25 | 24 | ||
| 26 | pub struct VrefInt; | 25 | impl super::VrefConverter for crate::peripherals::ADC1 { |
| 27 | impl AdcChannel<ADC1> for VrefInt {} | 26 | const CHANNEL: u8 = 17; |
| 28 | impl super::SealedAdcChannel<ADC1> for VrefInt { | 27 | } |
| 29 | fn channel(&self) -> u8 { | 28 | |
| 30 | 17 | 29 | #[cfg(any(stm32f2, stm32f40x, stm32f41x))] |
| 31 | } | 30 | impl super::TemperatureConverter for crate::peripherals::ADC1 { |
| 31 | const CHANNEL: u8 = 16; | ||
| 32 | } | ||
| 33 | |||
| 34 | #[cfg(not(any(stm32f2, stm32f40x, stm32f41x)))] | ||
| 35 | impl super::TemperatureConverter for crate::peripherals::ADC1 { | ||
| 36 | const CHANNEL: u8 = 18; | ||
| 37 | } | ||
| 38 | |||
| 39 | impl super::VBatConverter for crate::peripherals::ADC1 { | ||
| 40 | const CHANNEL: u8 = 18; | ||
| 32 | } | 41 | } |
| 33 | 42 | ||
| 34 | impl VrefInt { | 43 | impl VrefInt { |
| @@ -38,20 +47,6 @@ impl VrefInt { | |||
| 38 | } | 47 | } |
| 39 | } | 48 | } |
| 40 | 49 | ||
| 41 | pub struct Temperature; | ||
| 42 | impl AdcChannel<ADC1> for Temperature {} | ||
| 43 | impl super::SealedAdcChannel<ADC1> for Temperature { | ||
| 44 | fn channel(&self) -> u8 { | ||
| 45 | cfg_if::cfg_if! { | ||
| 46 | if #[cfg(any(stm32f2, stm32f40x, stm32f41x))] { | ||
| 47 | 16 | ||
| 48 | } else { | ||
| 49 | 18 | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | impl Temperature { | 50 | impl Temperature { |
| 56 | /// Time needed for temperature sensor readings to stabilize | 51 | /// Time needed for temperature sensor readings to stabilize |
| 57 | pub fn start_time_us() -> u32 { | 52 | pub fn start_time_us() -> u32 { |
| @@ -59,14 +54,6 @@ impl Temperature { | |||
| 59 | } | 54 | } |
| 60 | } | 55 | } |
| 61 | 56 | ||
| 62 | pub struct Vbat; | ||
| 63 | impl AdcChannel<ADC1> for Vbat {} | ||
| 64 | impl super::SealedAdcChannel<ADC1> for Vbat { | ||
| 65 | fn channel(&self) -> u8 { | ||
| 66 | 18 | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | enum Prescaler { | 57 | enum Prescaler { |
| 71 | Div2, | 58 | Div2, |
| 72 | Div4, | 59 | Div4, |
| @@ -117,10 +104,7 @@ where | |||
| 117 | 104 | ||
| 118 | blocking_delay_us(3); | 105 | blocking_delay_us(3); |
| 119 | 106 | ||
| 120 | Self { | 107 | Self { adc } |
| 121 | adc, | ||
| 122 | sample_time: SampleTime::from_bits(0), | ||
| 123 | } | ||
| 124 | } | 108 | } |
| 125 | 109 | ||
| 126 | /// Configures the ADC to use a DMA ring buffer for continuous data acquisition. | 110 | /// Configures the ADC to use a DMA ring buffer for continuous data acquisition. |
| @@ -137,61 +121,18 @@ where | |||
| 137 | self, | 121 | self, |
| 138 | dma: Peri<'d, impl RxDma<T>>, | 122 | dma: Peri<'d, impl RxDma<T>>, |
| 139 | dma_buf: &'d mut [u16], | 123 | dma_buf: &'d mut [u16], |
| 140 | sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<T>, SampleTime)>, | 124 | sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, SampleTime)>, |
| 141 | ) -> RingBufferedAdc<'d, T> { | 125 | ) -> RingBufferedAdc<'d, T> { |
| 142 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); | 126 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); |
| 143 | 127 | ||
| 144 | T::regs().cr2().modify(|reg| { | 128 | Self::configure_sequence(sequence.map(|(mut channel, sample_time)| { |
| 145 | reg.set_adon(true); | ||
| 146 | }); | ||
| 147 | |||
| 148 | // Check the sequence is long enough | ||
| 149 | T::regs().sqr1().modify(|r| { | ||
| 150 | r.set_l((sequence.len() - 1).try_into().unwrap()); | ||
| 151 | }); | ||
| 152 | |||
| 153 | for (i, (channel, sample_time)) in sequence.enumerate() { | ||
| 154 | // Set this GPIO as an analog input. | ||
| 155 | channel.setup(); | 129 | channel.setup(); |
| 156 | 130 | ||
| 157 | // Set the channel in the right sequence field. | 131 | (channel.channel, sample_time) |
| 158 | T::regs().sqr3().modify(|w| w.set_sq(i, channel.channel())); | 132 | })); |
| 159 | |||
| 160 | Self::set_channel_sample_time(channel.channel(), sample_time); | ||
| 161 | } | ||
| 162 | |||
| 163 | compiler_fence(Ordering::SeqCst); | 133 | compiler_fence(Ordering::SeqCst); |
| 164 | 134 | ||
| 165 | let r = T::regs(); | 135 | Self::setup_dma(); |
| 166 | |||
| 167 | // Clear all interrupts | ||
| 168 | r.sr().modify(|regs| { | ||
| 169 | regs.set_eoc(false); | ||
| 170 | regs.set_ovr(false); | ||
| 171 | regs.set_strt(false); | ||
| 172 | }); | ||
| 173 | |||
| 174 | r.cr1().modify(|w| { | ||
| 175 | // Enable interrupt for end of conversion | ||
| 176 | w.set_eocie(true); | ||
| 177 | // Enable interrupt for overrun | ||
| 178 | w.set_ovrie(true); | ||
| 179 | // Scanning converisons of multiple channels | ||
| 180 | w.set_scan(true); | ||
| 181 | // Continuous conversion mode | ||
| 182 | w.set_discen(false); | ||
| 183 | }); | ||
| 184 | |||
| 185 | r.cr2().modify(|w| { | ||
| 186 | // Enable DMA mode | ||
| 187 | w.set_dma(true); | ||
| 188 | // Enable continuous conversions | ||
| 189 | w.set_cont(true); | ||
| 190 | // DMA requests are issues as long as DMA=1 and data are converted. | ||
| 191 | w.set_dds(vals::Dds::CONTINUOUS); | ||
| 192 | // EOC flag is set at the end of each conversion. | ||
| 193 | w.set_eocs(vals::Eocs::EACH_CONVERSION); | ||
| 194 | }); | ||
| 195 | 136 | ||
| 196 | // Don't disable the clock | 137 | // Don't disable the clock |
| 197 | mem::forget(self); | 138 | mem::forget(self); |
| @@ -199,28 +140,14 @@ where | |||
| 199 | RingBufferedAdc::new(dma, dma_buf) | 140 | RingBufferedAdc::new(dma, dma_buf) |
| 200 | } | 141 | } |
| 201 | 142 | ||
| 202 | pub(super) fn start() { | 143 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 203 | // Begin ADC conversions | 144 | channel.setup(); |
| 204 | T::regs().cr2().modify(|reg| { | ||
| 205 | reg.set_adon(true); | ||
| 206 | reg.set_swstart(true); | ||
| 207 | }); | ||
| 208 | } | ||
| 209 | |||
| 210 | pub(super) fn stop() { | ||
| 211 | // Stop ADC | ||
| 212 | T::regs().cr2().modify(|reg| { | ||
| 213 | // Stop ADC | ||
| 214 | reg.set_swstart(false); | ||
| 215 | }); | ||
| 216 | } | ||
| 217 | 145 | ||
| 218 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | 146 | // Configure ADC |
| 219 | self.sample_time = sample_time; | 147 | let channel = channel.channel(); |
| 220 | } | ||
| 221 | 148 | ||
| 222 | pub fn set_resolution(&mut self, resolution: Resolution) { | 149 | Self::configure_sequence([(channel, sample_time)].into_iter()); |
| 223 | T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); | 150 | Self::blocking_convert() |
| 224 | } | 151 | } |
| 225 | 152 | ||
| 226 | /// Enables internal voltage reference and returns [VrefInt], which can be used in | 153 | /// Enables internal voltage reference and returns [VrefInt], which can be used in |
| @@ -256,8 +183,27 @@ where | |||
| 256 | Vbat {} | 183 | Vbat {} |
| 257 | } | 184 | } |
| 258 | 185 | ||
| 259 | /// Perform a single conversion. | 186 | pub(super) fn start() { |
| 260 | fn convert(&mut self) -> u16 { | 187 | // Begin ADC conversions |
| 188 | T::regs().cr2().modify(|reg| { | ||
| 189 | reg.set_adon(true); | ||
| 190 | reg.set_swstart(true); | ||
| 191 | }); | ||
| 192 | } | ||
| 193 | |||
| 194 | pub(super) fn stop() { | ||
| 195 | // Stop ADC | ||
| 196 | T::regs().cr2().modify(|reg| { | ||
| 197 | // Stop ADC | ||
| 198 | reg.set_swstart(false); | ||
| 199 | }); | ||
| 200 | } | ||
| 201 | |||
| 202 | pub fn set_resolution(&mut self, resolution: Resolution) { | ||
| 203 | T::regs().cr1().modify(|reg| reg.set_res(resolution.into())); | ||
| 204 | } | ||
| 205 | |||
| 206 | pub(super) fn blocking_convert() -> u16 { | ||
| 261 | // clear end of conversion flag | 207 | // clear end of conversion flag |
| 262 | T::regs().sr().modify(|reg| { | 208 | T::regs().sr().modify(|reg| { |
| 263 | reg.set_eoc(false); | 209 | reg.set_eoc(false); |
| @@ -278,31 +224,63 @@ where | |||
| 278 | T::regs().dr().read().0 as u16 | 224 | T::regs().dr().read().0 as u16 |
| 279 | } | 225 | } |
| 280 | 226 | ||
| 281 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 227 | pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = (u8, SampleTime)>) { |
| 282 | channel.setup(); | 228 | T::regs().cr2().modify(|reg| { |
| 283 | 229 | reg.set_adon(true); | |
| 284 | // Configure ADC | 230 | }); |
| 285 | let channel = channel.channel(); | ||
| 286 | 231 | ||
| 287 | // Select channel | 232 | // Check the sequence is long enough |
| 288 | T::regs().sqr3().write(|reg| reg.set_sq(0, channel)); | 233 | T::regs().sqr1().modify(|r| { |
| 234 | r.set_l((sequence.len() - 1).try_into().unwrap()); | ||
| 235 | }); | ||
| 289 | 236 | ||
| 290 | // Configure channel | 237 | for (i, (ch, sample_time)) in sequence.enumerate() { |
| 291 | Self::set_channel_sample_time(channel, self.sample_time); | 238 | // Set the channel in the right sequence field. |
| 239 | T::regs().sqr3().modify(|w| w.set_sq(i, ch)); | ||
| 292 | 240 | ||
| 293 | self.convert() | 241 | let sample_time = sample_time.into(); |
| 242 | if ch <= 9 { | ||
| 243 | T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); | ||
| 244 | } else { | ||
| 245 | T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); | ||
| 246 | } | ||
| 247 | } | ||
| 294 | } | 248 | } |
| 295 | 249 | ||
| 296 | fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { | 250 | pub(super) fn setup_dma() { |
| 297 | let sample_time = sample_time.into(); | 251 | let r = T::regs(); |
| 298 | if ch <= 9 { | 252 | |
| 299 | T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time)); | 253 | // Clear all interrupts |
| 300 | } else { | 254 | r.sr().modify(|regs| { |
| 301 | T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time)); | 255 | regs.set_eoc(false); |
| 302 | } | 256 | regs.set_ovr(false); |
| 257 | regs.set_strt(false); | ||
| 258 | }); | ||
| 259 | |||
| 260 | r.cr1().modify(|w| { | ||
| 261 | // Enable interrupt for end of conversion | ||
| 262 | w.set_eocie(true); | ||
| 263 | // Enable interrupt for overrun | ||
| 264 | w.set_ovrie(true); | ||
| 265 | // Scanning converisons of multiple channels | ||
| 266 | w.set_scan(true); | ||
| 267 | // Continuous conversion mode | ||
| 268 | w.set_discen(false); | ||
| 269 | }); | ||
| 270 | |||
| 271 | r.cr2().modify(|w| { | ||
| 272 | // Enable DMA mode | ||
| 273 | w.set_dma(true); | ||
| 274 | // Enable continuous conversions | ||
| 275 | w.set_cont(true); | ||
| 276 | // DMA requests are issues as long as DMA=1 and data are converted. | ||
| 277 | w.set_dds(vals::Dds::CONTINUOUS); | ||
| 278 | // EOC flag is set at the end of each conversion. | ||
| 279 | w.set_eocs(vals::Eocs::EACH_CONVERSION); | ||
| 280 | }); | ||
| 303 | } | 281 | } |
| 304 | 282 | ||
| 305 | pub(super) fn teardown_adc() { | 283 | pub(super) fn teardown_dma() { |
| 306 | let r = T::regs(); | 284 | let r = T::regs(); |
| 307 | 285 | ||
| 308 | // Stop ADC | 286 | // Stop ADC |
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 170b08a25..e816907d1 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs | |||
| @@ -9,8 +9,11 @@ use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs}; | |||
| 9 | #[cfg(adc_g0)] | 9 | #[cfg(adc_g0)] |
| 10 | pub use pac::adc::vals::{Ovsr, Ovss, Presc}; | 10 | pub use pac::adc::vals::{Ovsr, Ovss, Presc}; |
| 11 | 11 | ||
| 12 | #[allow(unused_imports)] | ||
| 13 | use super::SealedAdcChannel; | ||
| 12 | use super::{ | 14 | use super::{ |
| 13 | Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, | 15 | Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, Temperature, Vbat, VrefInt, |
| 16 | blocking_delay_us, | ||
| 14 | }; | 17 | }; |
| 15 | 18 | ||
| 16 | #[cfg(any(adc_v3, adc_g0, adc_u0))] | 19 | #[cfg(any(adc_v3, adc_g0, adc_u0))] |
| @@ -32,61 +35,55 @@ pub const VREF_CALIB_MV: u32 = 3000; | |||
| 32 | // TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable | 35 | // TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable |
| 33 | const SAMPLE_TIMES_CAPACITY: usize = 2; | 36 | const SAMPLE_TIMES_CAPACITY: usize = 2; |
| 34 | 37 | ||
| 35 | pub struct VrefInt; | 38 | #[cfg(adc_g0)] |
| 36 | impl<T: Instance> AdcChannel<T> for VrefInt {} | 39 | impl<T: Instance> super::VrefConverter for T { |
| 37 | impl<T: Instance> SealedAdcChannel<T> for VrefInt { | 40 | const CHANNEL: u8 = 13; |
| 38 | fn channel(&self) -> u8 { | 41 | } |
| 39 | cfg_if! { | 42 | #[cfg(any(adc_h5, adc_h7rs))] |
| 40 | if #[cfg(adc_g0)] { | 43 | impl<T: Instance> super::VrefConverter for T { |
| 41 | let val = 13; | 44 | const CHANNEL: u8 = 17; |
| 42 | } else if #[cfg(any(adc_h5, adc_h7rs))] { | 45 | } |
| 43 | let val = 17; | 46 | #[cfg(adc_u0)] |
| 44 | } else if #[cfg(adc_u0)] { | 47 | impl<T: Instance> super::VrefConverter for T { |
| 45 | let val = 12; | 48 | const CHANNEL: u8 = 12; |
| 46 | } else { | 49 | } |
| 47 | let val = 0; | 50 | #[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] |
| 48 | } | 51 | impl<T: Instance> super::VrefConverter for T { |
| 49 | } | 52 | const CHANNEL: u8 = 0; |
| 50 | val | ||
| 51 | } | ||
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | pub struct Temperature; | 55 | #[cfg(adc_g0)] |
| 55 | impl<T: Instance> AdcChannel<T> for Temperature {} | 56 | impl<T: Instance> super::TemperatureConverter for T { |
| 56 | impl<T: Instance> SealedAdcChannel<T> for Temperature { | 57 | const CHANNEL: u8 = 12; |
| 57 | fn channel(&self) -> u8 { | 58 | } |
| 58 | cfg_if! { | 59 | #[cfg(any(adc_h5, adc_h7rs))] |
| 59 | if #[cfg(adc_g0)] { | 60 | impl<T: Instance> super::TemperatureConverter for T { |
| 60 | let val = 12; | 61 | const CHANNEL: u8 = 16; |
| 61 | } else if #[cfg(any(adc_h5, adc_h7rs))] { | 62 | } |
| 62 | let val = 16; | 63 | #[cfg(adc_u0)] |
| 63 | } else if #[cfg(adc_u0)] { | 64 | impl<T: Instance> super::TemperatureConverter for T { |
| 64 | let val = 11; | 65 | const CHANNEL: u8 = 11; |
| 65 | } else { | 66 | } |
| 66 | let val = 17; | 67 | #[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] |
| 67 | } | 68 | impl<T: Instance> super::TemperatureConverter for T { |
| 68 | } | 69 | const CHANNEL: u8 = 17; |
| 69 | val | ||
| 70 | } | ||
| 71 | } | 70 | } |
| 72 | 71 | ||
| 73 | pub struct Vbat; | 72 | #[cfg(adc_g0)] |
| 74 | impl<T: Instance> AdcChannel<T> for Vbat {} | 73 | impl<T: Instance> super::VBatConverter for T { |
| 75 | impl<T: Instance> SealedAdcChannel<T> for Vbat { | 74 | const CHANNEL: u8 = 14; |
| 76 | fn channel(&self) -> u8 { | 75 | } |
| 77 | cfg_if! { | 76 | #[cfg(any(adc_h5, adc_h7rs))] |
| 78 | if #[cfg(adc_g0)] { | 77 | impl<T: Instance> super::VBatConverter for T { |
| 79 | let val = 14; | 78 | const CHANNEL: u8 = 2; |
| 80 | } else if #[cfg(any(adc_h5, adc_h7rs))] { | 79 | } |
| 81 | let val = 2; | 80 | #[cfg(adc_u0)] |
| 82 | } else if #[cfg(any(adc_h5, adc_h7rs))] { | 81 | impl<T: Instance> super::VBatConverter for T { |
| 83 | let val = 13; | 82 | const CHANNEL: u8 = 13; |
| 84 | } else { | 83 | } |
| 85 | let val = 18; | 84 | #[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] |
| 86 | } | 85 | impl<T: Instance> super::VBatConverter for T { |
| 87 | } | 86 | const CHANNEL: u8 = 18; |
| 88 | val | ||
| 89 | } | ||
| 90 | } | 87 | } |
| 91 | 88 | ||
| 92 | cfg_if! { | 89 | cfg_if! { |
| @@ -201,7 +198,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 201 | } | 198 | } |
| 202 | 199 | ||
| 203 | #[cfg(any(adc_v3, adc_g0, adc_u0))] | 200 | #[cfg(any(adc_v3, adc_g0, adc_u0))] |
| 204 | pub(super) fn teardown_adc() { | 201 | pub(super) fn teardown_dma() { |
| 205 | //disable dma control | 202 | //disable dma control |
| 206 | #[cfg(not(any(adc_g0, adc_u0)))] | 203 | #[cfg(not(any(adc_g0, adc_u0)))] |
| 207 | T::regs().cfgr().modify(|reg| { | 204 | T::regs().cfgr().modify(|reg| { |
| @@ -218,10 +215,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 218 | pub fn new(adc: Peri<'d, T>) -> Self { | 215 | pub fn new(adc: Peri<'d, T>) -> Self { |
| 219 | Self::init_regulator(); | 216 | Self::init_regulator(); |
| 220 | Self::init_calibrate(); | 217 | Self::init_calibrate(); |
| 221 | Self { | 218 | Self { adc } |
| 222 | adc, | ||
| 223 | sample_time: SampleTime::from_bits(0), | ||
| 224 | } | ||
| 225 | } | 219 | } |
| 226 | 220 | ||
| 227 | #[cfg(adc_g0)] | 221 | #[cfg(adc_g0)] |
| @@ -257,10 +251,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 257 | 251 | ||
| 258 | Self::init_calibrate(); | 252 | Self::init_calibrate(); |
| 259 | 253 | ||
| 260 | Self { | 254 | Self { adc } |
| 261 | adc, | ||
| 262 | sample_time: SampleTime::from_bits(0), | ||
| 263 | } | ||
| 264 | } | 255 | } |
| 265 | 256 | ||
| 266 | // Enable ADC only when it is not already running. | 257 | // Enable ADC only when it is not already running. |
| @@ -342,16 +333,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 342 | Vbat {} | 333 | Vbat {} |
| 343 | } | 334 | } |
| 344 | 335 | ||
| 345 | /// Set the ADC sample time. | ||
| 346 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||
| 347 | self.sample_time = sample_time; | ||
| 348 | } | ||
| 349 | |||
| 350 | /// Get the ADC sample time. | ||
| 351 | pub fn sample_time(&self) -> SampleTime { | ||
| 352 | self.sample_time | ||
| 353 | } | ||
| 354 | |||
| 355 | /// Set the ADC resolution. | 336 | /// Set the ADC resolution. |
| 356 | pub fn set_resolution(&mut self, resolution: Resolution) { | 337 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 357 | #[cfg(not(any(adc_g0, adc_u0)))] | 338 | #[cfg(not(any(adc_g0, adc_u0)))] |
| @@ -413,8 +394,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 413 | } | 394 | } |
| 414 | 395 | ||
| 415 | /// Read an ADC channel. | 396 | /// Read an ADC channel. |
| 416 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 397 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 417 | self.read_channel(channel) | 398 | self.read_channel(channel, sample_time) |
| 418 | } | 399 | } |
| 419 | 400 | ||
| 420 | /// Read one or multiple ADC channels using DMA. | 401 | /// Read one or multiple ADC channels using DMA. |
| @@ -616,7 +597,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 616 | &mut self, | 597 | &mut self, |
| 617 | dma: Peri<'a, impl RxDma<T>>, | 598 | dma: Peri<'a, impl RxDma<T>>, |
| 618 | dma_buf: &'a mut [u16], | 599 | dma_buf: &'a mut [u16], |
| 619 | sequence: impl ExactSizeIterator<Item = (&'a mut AnyAdcChannel<T>, SampleTime)>, | 600 | sequence: impl ExactSizeIterator<Item = (AnyAdcChannel<T>, SampleTime)>, |
| 620 | ) -> RingBufferedAdc<'a, T> { | 601 | ) -> RingBufferedAdc<'a, T> { |
| 621 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); | 602 | assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF); |
| 622 | assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); | 603 | assert!(sequence.len() != 0, "Asynchronous read sequence cannot be empty"); |
| @@ -665,8 +646,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 665 | let mut channel_mask = 0; | 646 | let mut channel_mask = 0; |
| 666 | 647 | ||
| 667 | // Configure channels and ranks | 648 | // Configure channels and ranks |
| 668 | for (_i, (channel, sample_time)) in sequence.enumerate() { | 649 | for (_i, (mut channel, sample_time)) in sequence.enumerate() { |
| 669 | Self::configure_channel(channel, sample_time); | 650 | Self::configure_channel(&mut channel, sample_time); |
| 670 | 651 | ||
| 671 | // Each channel is sampled according to sequence | 652 | // Each channel is sampled according to sequence |
| 672 | #[cfg(not(any(adc_g0, adc_u0)))] | 653 | #[cfg(not(any(adc_g0, adc_u0)))] |
| @@ -745,13 +726,13 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 745 | Self::set_channel_sample_time(channel.channel(), sample_time); | 726 | Self::set_channel_sample_time(channel.channel(), sample_time); |
| 746 | } | 727 | } |
| 747 | 728 | ||
| 748 | fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 729 | fn read_channel(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 749 | self.enable(); | 730 | self.enable(); |
| 750 | #[cfg(not(adc_g0))] | 731 | #[cfg(not(adc_g0))] |
| 751 | Self::configure_channel(channel, self.sample_time); | 732 | Self::configure_channel(channel, sample_time); |
| 752 | #[cfg(adc_g0)] | 733 | #[cfg(adc_g0)] |
| 753 | T::regs().smpr().write(|reg| { | 734 | T::regs().smpr().write(|reg| { |
| 754 | reg.set_sample_time(0, self.sample_time); | 735 | reg.set_sample_time(0, sample_time); |
| 755 | reg.set_smpsel(channel.channel().into(), Smpsel::SMP1); | 736 | reg.set_smpsel(channel.channel().into(), Smpsel::SMP1); |
| 756 | }); | 737 | }); |
| 757 | // Select channel | 738 | // Select channel |
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index c7d0103a6..2f7baf3bf 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs | |||
| @@ -5,7 +5,8 @@ use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel}; | |||
| 5 | use pac::adccommon::vals::Presc; | 5 | use pac::adccommon::vals::Presc; |
| 6 | 6 | ||
| 7 | use super::{ | 7 | use super::{ |
| 8 | Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, | 8 | Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, Temperature, Vbat, |
| 9 | VrefInt, blocking_delay_us, | ||
| 9 | }; | 10 | }; |
| 10 | use crate::dma::Transfer; | 11 | use crate::dma::Transfer; |
| 11 | use crate::time::Hertz; | 12 | use crate::time::Hertz; |
| @@ -25,52 +26,40 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); | |||
| 25 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); | 26 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); |
| 26 | 27 | ||
| 27 | #[cfg(stm32g4)] | 28 | #[cfg(stm32g4)] |
| 28 | const VREF_CHANNEL: u8 = 18; | 29 | impl<T: Instance> super::VrefConverter for T { |
| 30 | const CHANNEL: u8 = 18; | ||
| 31 | } | ||
| 29 | #[cfg(stm32g4)] | 32 | #[cfg(stm32g4)] |
| 30 | const TEMP_CHANNEL: u8 = 16; | 33 | impl<T: Instance> super::TemperatureConverter for T { |
| 34 | const CHANNEL: u8 = 16; | ||
| 35 | } | ||
| 31 | 36 | ||
| 32 | #[cfg(stm32h7)] | 37 | #[cfg(stm32h7)] |
| 33 | const VREF_CHANNEL: u8 = 19; | 38 | impl<T: Instance> super::VrefConverter for T { |
| 39 | const CHANNEL: u8 = 19; | ||
| 40 | } | ||
| 34 | #[cfg(stm32h7)] | 41 | #[cfg(stm32h7)] |
| 35 | const TEMP_CHANNEL: u8 = 18; | 42 | impl<T: Instance> super::TemperatureConverter for T { |
| 43 | const CHANNEL: u8 = 18; | ||
| 44 | } | ||
| 36 | 45 | ||
| 37 | // TODO this should be 14 for H7a/b/35 | 46 | // TODO this should be 14 for H7a/b/35 |
| 38 | #[cfg(not(stm32u5))] | 47 | #[cfg(not(stm32u5))] |
| 39 | const VBAT_CHANNEL: u8 = 17; | 48 | impl<T: Instance> super::VBatConverter for T { |
| 49 | const CHANNEL: u8 = 17; | ||
| 50 | } | ||
| 40 | 51 | ||
| 41 | #[cfg(stm32u5)] | 52 | #[cfg(stm32u5)] |
| 42 | const VREF_CHANNEL: u8 = 0; | 53 | impl<T: Instance> super::VrefConverter for T { |
| 43 | #[cfg(stm32u5)] | 54 | const CHANNEL: u8 = 0; |
| 44 | const TEMP_CHANNEL: u8 = 19; | ||
| 45 | #[cfg(stm32u5)] | ||
| 46 | const VBAT_CHANNEL: u8 = 18; | ||
| 47 | |||
| 48 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs | ||
| 49 | /// Internal voltage reference channel. | ||
| 50 | pub struct VrefInt; | ||
| 51 | impl<T: Instance> AdcChannel<T> for VrefInt {} | ||
| 52 | impl<T: Instance> SealedAdcChannel<T> for VrefInt { | ||
| 53 | fn channel(&self) -> u8 { | ||
| 54 | VREF_CHANNEL | ||
| 55 | } | ||
| 56 | } | 55 | } |
| 57 | 56 | #[cfg(stm32u5)] | |
| 58 | /// Internal temperature channel. | 57 | impl<T: Instance> super::TemperatureConverter for T { |
| 59 | pub struct Temperature; | 58 | const CHANNEL: u8 = 19; |
| 60 | impl<T: Instance> AdcChannel<T> for Temperature {} | ||
| 61 | impl<T: Instance> SealedAdcChannel<T> for Temperature { | ||
| 62 | fn channel(&self) -> u8 { | ||
| 63 | TEMP_CHANNEL | ||
| 64 | } | ||
| 65 | } | 59 | } |
| 66 | 60 | #[cfg(stm32u5)] | |
| 67 | /// Internal battery voltage channel. | 61 | impl<T: Instance> super::VBatConverter for T { |
| 68 | pub struct Vbat; | 62 | const CHANNEL: u8 = 18; |
| 69 | impl<T: Instance> AdcChannel<T> for Vbat {} | ||
| 70 | impl<T: Instance> SealedAdcChannel<T> for Vbat { | ||
| 71 | fn channel(&self) -> u8 { | ||
| 72 | VBAT_CHANNEL | ||
| 73 | } | ||
| 74 | } | 63 | } |
| 75 | 64 | ||
| 76 | // NOTE (unused): The prescaler enum closely copies the hardware capabilities, | 65 | // NOTE (unused): The prescaler enum closely copies the hardware capabilities, |
| @@ -190,10 +179,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 190 | }; | 179 | }; |
| 191 | T::regs().cr().modify(|w| w.set_boost(boost)); | 180 | T::regs().cr().modify(|w| w.set_boost(boost)); |
| 192 | } | 181 | } |
| 193 | let mut s = Self { | 182 | let mut s = Self { adc }; |
| 194 | adc, | ||
| 195 | sample_time: SampleTime::from_bits(0), | ||
| 196 | }; | ||
| 197 | s.power_up(); | 183 | s.power_up(); |
| 198 | s.configure_differential_inputs(); | 184 | s.configure_differential_inputs(); |
| 199 | 185 | ||
| @@ -277,16 +263,6 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 277 | Vbat {} | 263 | Vbat {} |
| 278 | } | 264 | } |
| 279 | 265 | ||
| 280 | /// Set the ADC sample time. | ||
| 281 | pub fn set_sample_time(&mut self, sample_time: SampleTime) { | ||
| 282 | self.sample_time = sample_time; | ||
| 283 | } | ||
| 284 | |||
| 285 | /// Get the ADC sample time. | ||
| 286 | pub fn sample_time(&self) -> SampleTime { | ||
| 287 | self.sample_time | ||
| 288 | } | ||
| 289 | |||
| 290 | /// Set the ADC resolution. | 266 | /// Set the ADC resolution. |
| 291 | pub fn set_resolution(&mut self, resolution: Resolution) { | 267 | pub fn set_resolution(&mut self, resolution: Resolution) { |
| 292 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); | 268 | T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); |
| @@ -335,8 +311,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 335 | } | 311 | } |
| 336 | 312 | ||
| 337 | /// Read an ADC channel. | 313 | /// Read an ADC channel. |
| 338 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 314 | pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 339 | self.read_channel(channel) | 315 | self.read_channel(channel, sample_time) |
| 340 | } | 316 | } |
| 341 | 317 | ||
| 342 | /// Read one or multiple ADC channels using DMA. | 318 | /// Read one or multiple ADC channels using DMA. |
| @@ -472,8 +448,8 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 472 | } | 448 | } |
| 473 | } | 449 | } |
| 474 | 450 | ||
| 475 | fn read_channel(&mut self, channel: &mut impl AdcChannel<T>) -> u16 { | 451 | fn read_channel(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { |
| 476 | Self::configure_channel(channel, self.sample_time); | 452 | Self::configure_channel(channel, sample_time); |
| 477 | 453 | ||
| 478 | T::regs().sqr1().modify(|reg| { | 454 | T::regs().sqr1().modify(|reg| { |
| 479 | reg.set_sq(0, channel.channel()); | 455 | reg.set_sq(0, channel.channel()); |
diff --git a/embassy-stm32/src/adc/watchdog_v1.rs b/embassy-stm32/src/adc/watchdog_v1.rs index bbe8e1971..b12e0d333 100644 --- a/embassy-stm32/src/adc/watchdog_v1.rs +++ b/embassy-stm32/src/adc/watchdog_v1.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | use core::future::poll_fn; | 1 | use core::future::poll_fn; |
| 2 | use core::task::Poll; | 2 | use core::task::Poll; |
| 3 | 3 | ||
| 4 | use stm32_metapac::adc::vals::{Align, Awdsgl, Res}; | 4 | use stm32_metapac::adc::vals::{Align, Awdsgl, Res, SampleTime}; |
| 5 | 5 | ||
| 6 | use crate::adc::{Adc, AdcChannel, Instance}; | 6 | use crate::adc::{Adc, AdcChannel, Instance}; |
| 7 | 7 | ||
| @@ -67,7 +67,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 67 | /// let v_high = adc.monitor_watchdog().await; | 67 | /// let v_high = adc.monitor_watchdog().await; |
| 68 | /// info!("ADC sample is high {}", v_high); | 68 | /// info!("ADC sample is high {}", v_high); |
| 69 | /// ``` | 69 | /// ``` |
| 70 | pub async fn monitor_watchdog(&mut self) -> u16 { | 70 | pub async fn monitor_watchdog(&mut self, sample_time: SampleTime) -> u16 { |
| 71 | assert!( | 71 | assert!( |
| 72 | match T::regs().cfgr1().read().awdsgl() { | 72 | match T::regs().cfgr1().read().awdsgl() { |
| 73 | Awdsgl::SINGLE_CHANNEL => T::regs().cfgr1().read().awdch() != 0, | 73 | Awdsgl::SINGLE_CHANNEL => T::regs().cfgr1().read().awdch() != 0, |
| @@ -76,7 +76,7 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 76 | "`set_channel` should be called before `monitor`", | 76 | "`set_channel` should be called before `monitor`", |
| 77 | ); | 77 | ); |
| 78 | assert!(T::regs().chselr().read().0 != 0); | 78 | assert!(T::regs().chselr().read().0 != 0); |
| 79 | T::regs().smpr().modify(|reg| reg.set_smp(self.sample_time.into())); | 79 | T::regs().smpr().modify(|reg| reg.set_smp(sample_time.into())); |
| 80 | Self::start_awd(); | 80 | Self::start_awd(); |
| 81 | 81 | ||
| 82 | let sample = poll_fn(|cx| { | 82 | let sample = poll_fn(|cx| { |
diff --git a/examples/stm32c0/src/bin/adc.rs b/examples/stm32c0/src/bin/adc.rs index 1f54b0b18..b52c9e7f8 100644 --- a/examples/stm32c0/src/bin/adc.rs +++ b/examples/stm32c0/src/bin/adc.rs | |||
| @@ -17,7 +17,7 @@ async fn main(_spawner: Spawner) { | |||
| 17 | info!("ADC STM32C0 example."); | 17 | info!("ADC STM32C0 example."); |
| 18 | 18 | ||
| 19 | // We need to set certain sample time to be able to read temp sensor. | 19 | // We need to set certain sample time to be able to read temp sensor. |
| 20 | let mut adc = Adc::new(p.ADC1, SampleTime::CYCLES12_5, Resolution::BITS12); | 20 | let mut adc = Adc::new(p.ADC1, Resolution::BITS12); |
| 21 | let mut temp = adc.enable_temperature().degrade_adc(); | 21 | let mut temp = adc.enable_temperature().degrade_adc(); |
| 22 | let mut vref = adc.enable_vrefint().degrade_adc(); | 22 | let mut vref = adc.enable_vrefint().degrade_adc(); |
| 23 | let mut pin0 = p.PA0.degrade_adc(); | 23 | let mut pin0 = p.PA0.degrade_adc(); |
| @@ -27,9 +27,9 @@ async fn main(_spawner: Spawner) { | |||
| 27 | 27 | ||
| 28 | loop { | 28 | loop { |
| 29 | info!("============================"); | 29 | info!("============================"); |
| 30 | let blocking_temp = adc.blocking_read(&mut temp); | 30 | let blocking_temp = adc.blocking_read(&mut temp, SampleTime::CYCLES12_5); |
| 31 | let blocking_vref = adc.blocking_read(&mut vref); | 31 | let blocking_vref = adc.blocking_read(&mut vref, SampleTime::CYCLES12_5); |
| 32 | let blocing_pin0 = adc.blocking_read(&mut pin0); | 32 | let blocing_pin0 = adc.blocking_read(&mut pin0, SampleTime::CYCLES12_5); |
| 33 | info!( | 33 | info!( |
| 34 | "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.", | 34 | "Blocking ADC read: vref = {}, temp = {}, pin0 = {}.", |
| 35 | blocking_vref, blocking_temp, blocing_pin0 | 35 | blocking_vref, blocking_temp, blocing_pin0 |
diff --git a/examples/stm32f0/src/bin/adc-watchdog.rs b/examples/stm32f0/src/bin/adc-watchdog.rs index ff98aac8e..6879dd10a 100644 --- a/examples/stm32f0/src/bin/adc-watchdog.rs +++ b/examples/stm32f0/src/bin/adc-watchdog.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::{self, Adc, WatchdogChannels}; | 6 | use embassy_stm32::adc::{self, Adc, SampleTime, WatchdogChannels}; |
| 7 | use embassy_stm32::bind_interrupts; | 7 | use embassy_stm32::bind_interrupts; |
| 8 | use embassy_stm32::peripherals::ADC1; | 8 | use embassy_stm32::peripherals::ADC1; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -23,12 +23,12 @@ async fn main(_spawner: Spawner) { | |||
| 23 | loop { | 23 | loop { |
| 24 | // Wait for pin to go high | 24 | // Wait for pin to go high |
| 25 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); | 25 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0, 0x07F); |
| 26 | let v_high = adc.monitor_watchdog().await; | 26 | let v_high = adc.monitor_watchdog(SampleTime::CYCLES13_5).await; |
| 27 | info!("ADC sample is high {}", v_high); | 27 | info!("ADC sample is high {}", v_high); |
| 28 | 28 | ||
| 29 | // Wait for pin to go low | 29 | // Wait for pin to go low |
| 30 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); | 30 | adc.init_watchdog(WatchdogChannels::from_channel(&pin), 0x01f, 0xFFF); |
| 31 | let v_low = adc.monitor_watchdog().await; | 31 | let v_low = adc.monitor_watchdog(SampleTime::CYCLES13_5).await; |
| 32 | info!("ADC sample is low {}", v_low); | 32 | info!("ADC sample is low {}", v_low); |
| 33 | } | 33 | } |
| 34 | } | 34 | } |
diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs index 8825e2687..fafeeffaf 100644 --- a/examples/stm32f0/src/bin/adc.rs +++ b/examples/stm32f0/src/bin/adc.rs | |||
| @@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) { | |||
| 19 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 20 | 20 | ||
| 21 | let mut adc = Adc::new(p.ADC1, Irqs); | 21 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 22 | adc.set_sample_time(SampleTime::CYCLES71_5); | ||
| 23 | let mut pin = p.PA1; | 22 | let mut pin = p.PA1; |
| 24 | 23 | ||
| 25 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 26 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await; |
| 27 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 28 | // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32f031c6.pdf |
| 29 | // 6.3.4 Embedded reference voltage | 28 | // 6.3.4 Embedded reference voltage |
| @@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | loop { | 34 | loop { |
| 36 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await; |
| 37 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 38 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 39 | } | 38 | } |
diff --git a/examples/stm32f1/src/bin/adc.rs b/examples/stm32f1/src/bin/adc.rs index 541ff159e..2451aee3d 100644 --- a/examples/stm32f1/src/bin/adc.rs +++ b/examples/stm32f1/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::Adc; | 6 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 7 | use embassy_stm32::peripherals::ADC1; | 7 | use embassy_stm32::peripherals::ADC1; |
| 8 | use embassy_stm32::{adc, bind_interrupts}; | 8 | use embassy_stm32::{adc, bind_interrupts}; |
| 9 | use embassy_time::Timer; | 9 | use embassy_time::Timer; |
| @@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) { | |||
| 22 | let mut pin = p.PB1; | 22 | let mut pin = p.PB1; |
| 23 | 23 | ||
| 24 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 25 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES13_5).await; |
| 26 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 27 | // From http://www.st.com/resource/en/datasheet/CD00161566.pdf | 27 | // From http://www.st.com/resource/en/datasheet/CD00161566.pdf |
| 28 | // 5.3.4 Embedded reference voltage | 28 | // 5.3.4 Embedded reference voltage |
| @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | loop { | 34 | loop { |
| 35 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES13_5).await; |
| 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 37 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 38 | } | 38 | } |
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs index a993b00ca..486f160ec 100644 --- a/examples/stm32f334/src/bin/adc.rs +++ b/examples/stm32f334/src/bin/adc.rs | |||
| @@ -40,24 +40,22 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 40 | 40 | ||
| 41 | let mut adc = Adc::new(p.ADC1, Irqs); | 41 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 42 | 42 | ||
| 43 | adc.set_sample_time(SampleTime::CYCLES601_5); | ||
| 44 | |||
| 45 | info!("enable vrefint..."); | 43 | info!("enable vrefint..."); |
| 46 | 44 | ||
| 47 | let mut vrefint = adc.enable_vref(); | 45 | let mut vrefint = adc.enable_vref(); |
| 48 | let mut temperature = adc.enable_temperature(); | 46 | let mut temperature = adc.enable_temperature(); |
| 49 | 47 | ||
| 50 | loop { | 48 | loop { |
| 51 | let vref = adc.read(&mut vrefint).await; | 49 | let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; |
| 52 | info!("read vref: {} (should be {})", vref, vrefint.value()); | 50 | info!("read vref: {} (should be {})", vref, vrefint.calibrated_value()); |
| 53 | 51 | ||
| 54 | let temp = adc.read(&mut temperature).await; | 52 | let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; |
| 55 | info!("read temperature: {}", temp); | 53 | info!("read temperature: {}", temp); |
| 56 | 54 | ||
| 57 | let pin = adc.read(&mut p.PA0).await; | 55 | let pin = adc.read(&mut p.PA0, SampleTime::CYCLES601_5).await; |
| 58 | info!("read pin: {}", pin); | 56 | info!("read pin: {}", pin); |
| 59 | 57 | ||
| 60 | let pin_mv = (pin as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; | 58 | let pin_mv = (pin as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095; |
| 61 | info!("computed pin mv: {}", pin_mv); | 59 | info!("computed pin mv: {}", pin_mv); |
| 62 | 60 | ||
| 63 | Timer::after_millis(500).await; | 61 | Timer::after_millis(500).await; |
diff --git a/examples/stm32f334/src/bin/opamp.rs b/examples/stm32f334/src/bin/opamp.rs index 3e621f2a1..9555fd35d 100644 --- a/examples/stm32f334/src/bin/opamp.rs +++ b/examples/stm32f334/src/bin/opamp.rs | |||
| @@ -42,8 +42,6 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 42 | let mut adc = Adc::new(p.ADC2, Irqs); | 42 | let mut adc = Adc::new(p.ADC2, Irqs); |
| 43 | let mut opamp = OpAmp::new(p.OPAMP2); | 43 | let mut opamp = OpAmp::new(p.OPAMP2); |
| 44 | 44 | ||
| 45 | adc.set_sample_time(SampleTime::CYCLES601_5); | ||
| 46 | |||
| 47 | info!("enable vrefint..."); | 45 | info!("enable vrefint..."); |
| 48 | 46 | ||
| 49 | let mut vrefint = adc.enable_vref(); | 47 | let mut vrefint = adc.enable_vref(); |
| @@ -51,16 +49,16 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 51 | let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow()); | 49 | let mut buffer = opamp.buffer_ext(p.PA7.reborrow(), p.PA6.reborrow()); |
| 52 | 50 | ||
| 53 | loop { | 51 | loop { |
| 54 | let vref = adc.read(&mut vrefint).await; | 52 | let vref = adc.read(&mut vrefint, SampleTime::CYCLES601_5).await; |
| 55 | info!("read vref: {} (should be {})", vref, vrefint.value()); | 53 | info!("read vref: {} (should be {})", vref, vrefint.calibrated_value()); |
| 56 | 54 | ||
| 57 | let temp = adc.read(&mut temperature).await; | 55 | let temp = adc.read(&mut temperature, SampleTime::CYCLES601_5).await; |
| 58 | info!("read temperature: {}", temp); | 56 | info!("read temperature: {}", temp); |
| 59 | 57 | ||
| 60 | let buffer = adc.read(&mut buffer).await; | 58 | let buffer = adc.read(&mut buffer, SampleTime::CYCLES601_5).await; |
| 61 | info!("read buffer: {}", buffer); | 59 | info!("read buffer: {}", buffer); |
| 62 | 60 | ||
| 63 | let pin_mv = (buffer as u32 * vrefint.value() as u32 / vref as u32) * 3300 / 4095; | 61 | let pin_mv = (buffer as u32 * vrefint.calibrated_value() as u32 / vref as u32) * 3300 / 4095; |
| 64 | info!("computed pin mv: {}", pin_mv); | 62 | info!("computed pin mv: {}", pin_mv); |
| 65 | 63 | ||
| 66 | Timer::after_millis(500).await; | 64 | Timer::after_millis(500).await; |
diff --git a/examples/stm32f4/src/bin/adc.rs b/examples/stm32f4/src/bin/adc.rs index 423d29225..5628cb827 100644 --- a/examples/stm32f4/src/bin/adc.rs +++ b/examples/stm32f4/src/bin/adc.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; | 4 | use cortex_m::prelude::_embedded_hal_blocking_delay_DelayUs; |
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::adc::{Adc, Temperature, VrefInt}; | 7 | use embassy_stm32::adc::{Adc, SampleTime, Temperature, VrefInt}; |
| 8 | use embassy_time::{Delay, Timer}; | 8 | use embassy_time::{Delay, Timer}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | // Startup delay can be combined to the maximum of either | 23 | // Startup delay can be combined to the maximum of either |
| 24 | delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); | 24 | delay.delay_us(Temperature::start_time_us().max(VrefInt::start_time_us())); |
| 25 | 25 | ||
| 26 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 26 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 27 | 27 | ||
| 28 | let convert_to_millivolts = |sample| { | 28 | let convert_to_millivolts = |sample| { |
| 29 | // From http://www.st.com/resource/en/datasheet/DM00071990.pdf | 29 | // From http://www.st.com/resource/en/datasheet/DM00071990.pdf |
| @@ -50,16 +50,16 @@ async fn main(_spawner: Spawner) { | |||
| 50 | 50 | ||
| 51 | loop { | 51 | loop { |
| 52 | // Read pin | 52 | // Read pin |
| 53 | let v = adc.blocking_read(&mut pin); | 53 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112); |
| 54 | info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); | 54 | info!("PC1: {} ({} mV)", v, convert_to_millivolts(v)); |
| 55 | 55 | ||
| 56 | // Read internal temperature | 56 | // Read internal temperature |
| 57 | let v = adc.blocking_read(&mut temp); | 57 | let v = adc.blocking_read(&mut temp, SampleTime::CYCLES112); |
| 58 | let celcius = convert_to_celcius(v); | 58 | let celcius = convert_to_celcius(v); |
| 59 | info!("Internal temp: {} ({} C)", v, celcius); | 59 | info!("Internal temp: {} ({} C)", v, celcius); |
| 60 | 60 | ||
| 61 | // Read internal voltage reference | 61 | // Read internal voltage reference |
| 62 | let v = adc.blocking_read(&mut vrefint); | 62 | let v = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 63 | info!("VrefInt: {}", v); | 63 | info!("VrefInt: {}", v); |
| 64 | 64 | ||
| 65 | Timer::after_millis(100).await; | 65 | Timer::after_millis(100).await; |
diff --git a/examples/stm32f4/src/bin/adc_dma.rs b/examples/stm32f4/src/bin/adc_dma.rs index f8da91336..01b881c79 100644 --- a/examples/stm32f4/src/bin/adc_dma.rs +++ b/examples/stm32f4/src/bin/adc_dma.rs | |||
| @@ -27,8 +27,8 @@ async fn adc_task(p: Peripherals) { | |||
| 27 | p.DMA2_CH0, | 27 | p.DMA2_CH0, |
| 28 | adc_data, | 28 | adc_data, |
| 29 | [ | 29 | [ |
| 30 | (&mut p.PA0.degrade_adc(), SampleTime::CYCLES112), | 30 | (p.PA0.degrade_adc(), SampleTime::CYCLES112), |
| 31 | (&mut p.PA2.degrade_adc(), SampleTime::CYCLES112), | 31 | (p.PA2.degrade_adc(), SampleTime::CYCLES112), |
| 32 | ] | 32 | ] |
| 33 | .into_iter(), | 33 | .into_iter(), |
| 34 | ); | 34 | ); |
| @@ -36,8 +36,8 @@ async fn adc_task(p: Peripherals) { | |||
| 36 | p.DMA2_CH2, | 36 | p.DMA2_CH2, |
| 37 | adc_data2, | 37 | adc_data2, |
| 38 | [ | 38 | [ |
| 39 | (&mut p.PA1.degrade_adc(), SampleTime::CYCLES112), | 39 | (p.PA1.degrade_adc(), SampleTime::CYCLES112), |
| 40 | (&mut p.PA3.degrade_adc(), SampleTime::CYCLES112), | 40 | (p.PA3.degrade_adc(), SampleTime::CYCLES112), |
| 41 | ] | 41 | ] |
| 42 | .into_iter(), | 42 | .into_iter(), |
| 43 | ); | 43 | ); |
diff --git a/examples/stm32f7/src/bin/adc.rs b/examples/stm32f7/src/bin/adc.rs index 6689e3b5d..0f226d34e 100644 --- a/examples/stm32f7/src/bin/adc.rs +++ b/examples/stm32f7/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::adc::Adc; | 6 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 7 | use embassy_time::Timer; | 7 | use embassy_time::Timer; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -16,7 +16,7 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let mut pin = p.PA3; | 16 | let mut pin = p.PA3; |
| 17 | 17 | ||
| 18 | let mut vrefint = adc.enable_vrefint(); | 18 | let mut vrefint = adc.enable_vrefint(); |
| 19 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 19 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES112); |
| 20 | let convert_to_millivolts = |sample| { | 20 | let convert_to_millivolts = |sample| { |
| 21 | // From http://www.st.com/resource/en/datasheet/DM00273119.pdf | 21 | // From http://www.st.com/resource/en/datasheet/DM00273119.pdf |
| 22 | // 6.3.27 Reference voltage | 22 | // 6.3.27 Reference voltage |
| @@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) { | |||
| 26 | }; | 26 | }; |
| 27 | 27 | ||
| 28 | loop { | 28 | loop { |
| 29 | let v = adc.blocking_read(&mut pin); | 29 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES112); |
| 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 31 | Timer::after_millis(100).await; | 31 | Timer::after_millis(100).await; |
| 32 | } | 32 | } |
diff --git a/examples/stm32g0/src/bin/adc.rs b/examples/stm32g0/src/bin/adc.rs index 7d8653ef2..972e43b55 100644 --- a/examples/stm32g0/src/bin/adc.rs +++ b/examples/stm32g0/src/bin/adc.rs | |||
| @@ -13,11 +13,10 @@ async fn main(_spawner: Spawner) { | |||
| 13 | info!("Hello World!"); | 13 | info!("Hello World!"); |
| 14 | 14 | ||
| 15 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); | 15 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); |
| 16 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 17 | let mut pin = p.PA1; | 16 | let mut pin = p.PA1; |
| 18 | 17 | ||
| 19 | let mut vrefint = adc.enable_vrefint(); | 18 | let mut vrefint = adc.enable_vrefint(); |
| 20 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 19 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); |
| 21 | let convert_to_millivolts = |sample| { | 20 | let convert_to_millivolts = |sample| { |
| 22 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | 21 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf |
| 23 | // 6.3.3 Embedded internal reference voltage | 22 | // 6.3.3 Embedded internal reference voltage |
| @@ -27,7 +26,7 @@ async fn main(_spawner: Spawner) { | |||
| 27 | }; | 26 | }; |
| 28 | 27 | ||
| 29 | loop { | 28 | loop { |
| 30 | let v = adc.blocking_read(&mut pin); | 29 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); |
| 31 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 30 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 32 | Timer::after_millis(100).await; | 31 | Timer::after_millis(100).await; |
| 33 | } | 32 | } |
diff --git a/examples/stm32g0/src/bin/adc_oversampling.rs b/examples/stm32g0/src/bin/adc_oversampling.rs index 834d1cd4a..f6979889d 100644 --- a/examples/stm32g0/src/bin/adc_oversampling.rs +++ b/examples/stm32g0/src/bin/adc_oversampling.rs | |||
| @@ -17,7 +17,6 @@ async fn main(_spawner: Spawner) { | |||
| 17 | info!("Adc oversample test"); | 17 | info!("Adc oversample test"); |
| 18 | 18 | ||
| 19 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); | 19 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Async { div: Presc::DIV1 }); |
| 20 | adc.set_sample_time(SampleTime::CYCLES1_5); | ||
| 21 | let mut pin = p.PA1; | 20 | let mut pin = p.PA1; |
| 22 | 21 | ||
| 23 | adc.set_oversampling_ratio(Ovsr::MUL16); | 22 | adc.set_oversampling_ratio(Ovsr::MUL16); |
| @@ -25,7 +24,7 @@ async fn main(_spawner: Spawner) { | |||
| 25 | adc.oversampling_enable(true); | 24 | adc.oversampling_enable(true); |
| 26 | 25 | ||
| 27 | loop { | 26 | loop { |
| 28 | let v = adc.blocking_read(&mut pin); | 27 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES1_5); |
| 29 | info!("--> {} ", v); //max 65520 = 0xFFF0 | 28 | info!("--> {} ", v); //max 65520 = 0xFFF0 |
| 30 | Timer::after_millis(100).await; | 29 | Timer::after_millis(100).await; |
| 31 | } | 30 | } |
diff --git a/examples/stm32g4/src/bin/adc.rs b/examples/stm32g4/src/bin/adc.rs index 920142a18..695f37115 100644 --- a/examples/stm32g4/src/bin/adc.rs +++ b/examples/stm32g4/src/bin/adc.rs | |||
| @@ -29,10 +29,9 @@ async fn main(_spawner: Spawner) { | |||
| 29 | info!("Hello World!"); | 29 | info!("Hello World!"); |
| 30 | 30 | ||
| 31 | let mut adc = Adc::new(p.ADC2); | 31 | let mut adc = Adc::new(p.ADC2); |
| 32 | adc.set_sample_time(SampleTime::CYCLES24_5); | ||
| 33 | 32 | ||
| 34 | loop { | 33 | loop { |
| 35 | let measured = adc.blocking_read(&mut p.PA7); | 34 | let measured = adc.blocking_read(&mut p.PA7, SampleTime::CYCLES24_5); |
| 36 | info!("measured: {}", measured); | 35 | info!("measured: {}", measured); |
| 37 | Timer::after_millis(500).await; | 36 | Timer::after_millis(500).await; |
| 38 | } | 37 | } |
diff --git a/examples/stm32g4/src/bin/adc_differential.rs b/examples/stm32g4/src/bin/adc_differential.rs index 301f0da84..a6e2f7d33 100644 --- a/examples/stm32g4/src/bin/adc_differential.rs +++ b/examples/stm32g4/src/bin/adc_differential.rs | |||
| @@ -33,14 +33,13 @@ async fn main(_spawner: Spawner) { | |||
| 33 | let mut p = embassy_stm32::init(config); | 33 | let mut p = embassy_stm32::init(config); |
| 34 | 34 | ||
| 35 | let mut adc = Adc::new(p.ADC1); | 35 | let mut adc = Adc::new(p.ADC1); |
| 36 | adc.set_sample_time(SampleTime::CYCLES247_5); | ||
| 37 | adc.set_differential(&mut p.PA0, true); //p:pa0,n:pa1 | 36 | adc.set_differential(&mut p.PA0, true); //p:pa0,n:pa1 |
| 38 | 37 | ||
| 39 | // can also use | 38 | // can also use |
| 40 | // adc.set_differential_channel(1, true); | 39 | // adc.set_differential_channel(1, true); |
| 41 | info!("adc initialized"); | 40 | info!("adc initialized"); |
| 42 | loop { | 41 | loop { |
| 43 | let measured = adc.blocking_read(&mut p.PA0); | 42 | let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES247_5); |
| 44 | info!("data: {}", measured); | 43 | info!("data: {}", measured); |
| 45 | Timer::after_millis(500).await; | 44 | Timer::after_millis(500).await; |
| 46 | } | 45 | } |
diff --git a/examples/stm32g4/src/bin/adc_oversampling.rs b/examples/stm32g4/src/bin/adc_oversampling.rs index 1e464183a..cb99ab2a7 100644 --- a/examples/stm32g4/src/bin/adc_oversampling.rs +++ b/examples/stm32g4/src/bin/adc_oversampling.rs | |||
| @@ -33,7 +33,6 @@ async fn main(_spawner: Spawner) { | |||
| 33 | let mut p = embassy_stm32::init(config); | 33 | let mut p = embassy_stm32::init(config); |
| 34 | 34 | ||
| 35 | let mut adc = Adc::new(p.ADC1); | 35 | let mut adc = Adc::new(p.ADC1); |
| 36 | adc.set_sample_time(SampleTime::CYCLES6_5); | ||
| 37 | // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf | 36 | // From https://www.st.com/resource/en/reference_manual/rm0440-stm32g4-series-advanced-armbased-32bit-mcus-stmicroelectronics.pdf |
| 38 | // page652 Oversampler | 37 | // page652 Oversampler |
| 39 | // Table 172. Maximum output results vs N and M. Grayed values indicates truncation | 38 | // Table 172. Maximum output results vs N and M. Grayed values indicates truncation |
| @@ -50,7 +49,7 @@ async fn main(_spawner: Spawner) { | |||
| 50 | adc.enable_regular_oversampling_mode(Rovsm::RESUMED, Trovs::AUTOMATIC, true); | 49 | adc.enable_regular_oversampling_mode(Rovsm::RESUMED, Trovs::AUTOMATIC, true); |
| 51 | 50 | ||
| 52 | loop { | 51 | loop { |
| 53 | let measured = adc.blocking_read(&mut p.PA0); | 52 | let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES6_5); |
| 54 | info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 | 53 | info!("data: 0x{:X}", measured); //max 0xFFF0 -> 65520 |
| 55 | Timer::after_millis(500).await; | 54 | Timer::after_millis(500).await; |
| 56 | } | 55 | } |
diff --git a/examples/stm32h5/src/bin/adc.rs b/examples/stm32h5/src/bin/adc.rs index 0566320d4..c919b1a95 100644 --- a/examples/stm32h5/src/bin/adc.rs +++ b/examples/stm32h5/src/bin/adc.rs | |||
| @@ -45,14 +45,12 @@ async fn main(_spawner: Spawner) { | |||
| 45 | 45 | ||
| 46 | let mut adc = Adc::new(p.ADC1); | 46 | let mut adc = Adc::new(p.ADC1); |
| 47 | 47 | ||
| 48 | adc.set_sample_time(SampleTime::CYCLES24_5); | ||
| 49 | |||
| 50 | let mut vrefint_channel = adc.enable_vrefint(); | 48 | let mut vrefint_channel = adc.enable_vrefint(); |
| 51 | 49 | ||
| 52 | loop { | 50 | loop { |
| 53 | let vrefint = adc.blocking_read(&mut vrefint_channel); | 51 | let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES24_5); |
| 54 | info!("vrefint: {}", vrefint); | 52 | info!("vrefint: {}", vrefint); |
| 55 | let measured = adc.blocking_read(&mut p.PA0); | 53 | let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES24_5); |
| 56 | info!("measured: {}", measured); | 54 | info!("measured: {}", measured); |
| 57 | Timer::after_millis(500).await; | 55 | Timer::after_millis(500).await; |
| 58 | } | 56 | } |
diff --git a/examples/stm32h7/src/bin/adc.rs b/examples/stm32h7/src/bin/adc.rs index a53c9d8d5..fc45541bf 100644 --- a/examples/stm32h7/src/bin/adc.rs +++ b/examples/stm32h7/src/bin/adc.rs | |||
| @@ -46,14 +46,12 @@ async fn main(_spawner: Spawner) { | |||
| 46 | 46 | ||
| 47 | let mut adc = Adc::new(p.ADC3); | 47 | let mut adc = Adc::new(p.ADC3); |
| 48 | 48 | ||
| 49 | adc.set_sample_time(SampleTime::CYCLES32_5); | ||
| 50 | |||
| 51 | let mut vrefint_channel = adc.enable_vrefint(); | 49 | let mut vrefint_channel = adc.enable_vrefint(); |
| 52 | 50 | ||
| 53 | loop { | 51 | loop { |
| 54 | let vrefint = adc.blocking_read(&mut vrefint_channel); | 52 | let vrefint = adc.blocking_read(&mut vrefint_channel, SampleTime::CYCLES32_5); |
| 55 | info!("vrefint: {}", vrefint); | 53 | info!("vrefint: {}", vrefint); |
| 56 | let measured = adc.blocking_read(&mut p.PC0); | 54 | let measured = adc.blocking_read(&mut p.PC0, SampleTime::CYCLES32_5); |
| 57 | info!("measured: {}", measured); | 55 | info!("measured: {}", measured); |
| 58 | Timer::after_millis(500).await; | 56 | Timer::after_millis(500).await; |
| 59 | } | 57 | } |
diff --git a/examples/stm32l0/src/bin/adc.rs b/examples/stm32l0/src/bin/adc.rs index 9dd09bc45..83be74ed9 100644 --- a/examples/stm32l0/src/bin/adc.rs +++ b/examples/stm32l0/src/bin/adc.rs | |||
| @@ -19,11 +19,10 @@ async fn main(_spawner: Spawner) { | |||
| 19 | info!("Hello World!"); | 19 | info!("Hello World!"); |
| 20 | 20 | ||
| 21 | let mut adc = Adc::new(p.ADC1, Irqs); | 21 | let mut adc = Adc::new(p.ADC1, Irqs); |
| 22 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 23 | let mut pin = p.PA1; | 22 | let mut pin = p.PA1; |
| 24 | 23 | ||
| 25 | let mut vrefint = adc.enable_vref(); | 24 | let mut vrefint = adc.enable_vref(); |
| 26 | let vrefint_sample = adc.read(&mut vrefint).await; | 25 | let vrefint_sample = adc.read(&mut vrefint, SampleTime::CYCLES79_5).await; |
| 27 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 28 | // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf |
| 29 | // 6.3.3 Embedded internal reference voltage | 28 | // 6.3.3 Embedded internal reference voltage |
| @@ -33,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 33 | }; | 32 | }; |
| 34 | 33 | ||
| 35 | loop { | 34 | loop { |
| 36 | let v = adc.read(&mut pin).await; | 35 | let v = adc.read(&mut pin, SampleTime::CYCLES79_5).await; |
| 37 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 38 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 39 | } | 38 | } |
diff --git a/examples/stm32l4/src/bin/adc.rs b/examples/stm32l4/src/bin/adc.rs index 40e907940..835bf5411 100644 --- a/examples/stm32l4/src/bin/adc.rs +++ b/examples/stm32l4/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::Config; | 5 | use embassy_stm32::Config; |
| 6 | use embassy_stm32::adc::{Adc, Resolution}; | 6 | use embassy_stm32::adc::{Adc, Resolution, SampleTime}; |
| 7 | use {defmt_rtt as _, panic_probe as _}; | 7 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 8 | ||
| 9 | #[cortex_m_rt::entry] | 9 | #[cortex_m_rt::entry] |
| @@ -23,7 +23,7 @@ fn main() -> ! { | |||
| 23 | let mut channel = p.PC0; | 23 | let mut channel = p.PC0; |
| 24 | 24 | ||
| 25 | loop { | 25 | loop { |
| 26 | let v = adc.blocking_read(&mut channel); | 26 | let v = adc.blocking_read(&mut channel, SampleTime::from_bits(0)); |
| 27 | info!("--> {}", v); | 27 | info!("--> {}", v); |
| 28 | } | 28 | } |
| 29 | } | 29 | } |
diff --git a/examples/stm32l4/src/bin/adc_dma.rs b/examples/stm32l4/src/bin/adc_dma.rs index 7a9200edd..ab1e9d2e9 100644 --- a/examples/stm32l4/src/bin/adc_dma.rs +++ b/examples/stm32l4/src/bin/adc_dma.rs | |||
| @@ -21,18 +21,14 @@ async fn main(_spawner: Spawner) { | |||
| 21 | let p = embassy_stm32::init(config); | 21 | let p = embassy_stm32::init(config); |
| 22 | 22 | ||
| 23 | let mut adc = Adc::new(p.ADC1); | 23 | let mut adc = Adc::new(p.ADC1); |
| 24 | let mut adc_pin0 = p.PA0.degrade_adc(); | 24 | let adc_pin0 = p.PA0.degrade_adc(); |
| 25 | let mut adc_pin1 = p.PA1.degrade_adc(); | 25 | let adc_pin1 = p.PA1.degrade_adc(); |
| 26 | let mut adc_dma_buf = [0u16; DMA_BUF_LEN]; | 26 | let mut adc_dma_buf = [0u16; DMA_BUF_LEN]; |
| 27 | let mut measurements = [0u16; DMA_BUF_LEN / 2]; | 27 | let mut measurements = [0u16; DMA_BUF_LEN / 2]; |
| 28 | let mut ring_buffered_adc = adc.into_ring_buffered( | 28 | let mut ring_buffered_adc = adc.into_ring_buffered( |
| 29 | p.DMA1_CH1, | 29 | p.DMA1_CH1, |
| 30 | &mut adc_dma_buf, | 30 | &mut adc_dma_buf, |
| 31 | [ | 31 | [(adc_pin0, SampleTime::CYCLES640_5), (adc_pin1, SampleTime::CYCLES640_5)].into_iter(), |
| 32 | (&mut adc_pin0, SampleTime::CYCLES640_5), | ||
| 33 | (&mut adc_pin1, SampleTime::CYCLES640_5), | ||
| 34 | ] | ||
| 35 | .into_iter(), | ||
| 36 | ); | 32 | ); |
| 37 | 33 | ||
| 38 | info!("starting measurement loop"); | 34 | info!("starting measurement loop"); |
diff --git a/examples/stm32u0/src/bin/adc.rs b/examples/stm32u0/src/bin/adc.rs index 32a54299d..4fbc6f17f 100644 --- a/examples/stm32u0/src/bin/adc.rs +++ b/examples/stm32u0/src/bin/adc.rs | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::Config; | 5 | use embassy_stm32::Config; |
| 6 | use embassy_stm32::adc::{Adc, Resolution}; | 6 | use embassy_stm32::adc::{Adc, Resolution, SampleTime}; |
| 7 | use embassy_time::Duration; | 7 | use embassy_time::Duration; |
| 8 | use {defmt_rtt as _, panic_probe as _}; | 8 | use {defmt_rtt as _, panic_probe as _}; |
| 9 | 9 | ||
| @@ -23,7 +23,7 @@ fn main() -> ! { | |||
| 23 | let mut channel = p.PC0; | 23 | let mut channel = p.PC0; |
| 24 | 24 | ||
| 25 | loop { | 25 | loop { |
| 26 | let v = adc.blocking_read(&mut channel); | 26 | let v = adc.blocking_read(&mut channel, SampleTime::CYCLES12_5); |
| 27 | info!("--> {}", v); | 27 | info!("--> {}", v); |
| 28 | embassy_time::block_for(Duration::from_millis(200)); | 28 | embassy_time::block_for(Duration::from_millis(200)); |
| 29 | } | 29 | } |
diff --git a/examples/stm32u5/src/bin/adc.rs b/examples/stm32u5/src/bin/adc.rs index 91e33053e..99944f7c7 100644 --- a/examples/stm32u5/src/bin/adc.rs +++ b/examples/stm32u5/src/bin/adc.rs | |||
| @@ -2,8 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_stm32::adc; | 5 | use embassy_stm32::adc::{self, AdcChannel, SampleTime, adc4}; |
| 6 | use embassy_stm32::adc::{AdcChannel, adc4}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | 6 | use {defmt_rtt as _, panic_probe as _}; |
| 8 | 7 | ||
| 9 | #[embassy_executor::main] | 8 | #[embassy_executor::main] |
| @@ -18,7 +17,6 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 18 | let mut adc1_pin2 = p.PA2; // A1 | 17 | let mut adc1_pin2 = p.PA2; // A1 |
| 19 | adc1.set_resolution(adc::Resolution::BITS14); | 18 | adc1.set_resolution(adc::Resolution::BITS14); |
| 20 | adc1.set_averaging(adc::Averaging::Samples1024); | 19 | adc1.set_averaging(adc::Averaging::Samples1024); |
| 21 | adc1.set_sample_time(adc::SampleTime::CYCLES160_5); | ||
| 22 | let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); | 20 | let max1 = adc::resolution_to_max_count(adc::Resolution::BITS14); |
| 23 | 21 | ||
| 24 | // **** ADC2 init **** | 22 | // **** ADC2 init **** |
| @@ -27,7 +25,6 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 27 | let mut adc2_pin2 = p.PB0; // A3 | 25 | let mut adc2_pin2 = p.PB0; // A3 |
| 28 | adc2.set_resolution(adc::Resolution::BITS14); | 26 | adc2.set_resolution(adc::Resolution::BITS14); |
| 29 | adc2.set_averaging(adc::Averaging::Samples1024); | 27 | adc2.set_averaging(adc::Averaging::Samples1024); |
| 30 | adc2.set_sample_time(adc::SampleTime::CYCLES160_5); | ||
| 31 | let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); | 28 | let max2 = adc::resolution_to_max_count(adc::Resolution::BITS14); |
| 32 | 29 | ||
| 33 | // **** ADC4 init **** | 30 | // **** ADC4 init **** |
| @@ -36,33 +33,32 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 36 | let mut adc4_pin2 = p.PC0; // A5 | 33 | let mut adc4_pin2 = p.PC0; // A5 |
| 37 | adc4.set_resolution(adc4::Resolution::BITS12); | 34 | adc4.set_resolution(adc4::Resolution::BITS12); |
| 38 | adc4.set_averaging(adc4::Averaging::Samples256); | 35 | adc4.set_averaging(adc4::Averaging::Samples256); |
| 39 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | ||
| 40 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 36 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 41 | 37 | ||
| 42 | // **** ADC1 blocking read **** | 38 | // **** ADC1 blocking read **** |
| 43 | let raw: u16 = adc1.blocking_read(&mut adc1_pin1); | 39 | let raw: u16 = adc1.blocking_read(&mut adc1_pin1, SampleTime::CYCLES160_5); |
| 44 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; | 40 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; |
| 45 | info!("Read adc1 pin 1 {}", volt); | 41 | info!("Read adc1 pin 1 {}", volt); |
| 46 | 42 | ||
| 47 | let raw: u16 = adc1.blocking_read(&mut adc1_pin2); | 43 | let raw: u16 = adc1.blocking_read(&mut adc1_pin2, SampleTime::CYCLES160_5); |
| 48 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; | 44 | let volt: f32 = 3.3 * raw as f32 / max1 as f32; |
| 49 | info!("Read adc1 pin 2 {}", volt); | 45 | info!("Read adc1 pin 2 {}", volt); |
| 50 | 46 | ||
| 51 | // **** ADC2 blocking read **** | 47 | // **** ADC2 blocking read **** |
| 52 | let raw: u16 = adc2.blocking_read(&mut adc2_pin1); | 48 | let raw: u16 = adc2.blocking_read(&mut adc2_pin1, SampleTime::CYCLES160_5); |
| 53 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; | 49 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; |
| 54 | info!("Read adc2 pin 1 {}", volt); | 50 | info!("Read adc2 pin 1 {}", volt); |
| 55 | 51 | ||
| 56 | let raw: u16 = adc2.blocking_read(&mut adc2_pin2); | 52 | let raw: u16 = adc2.blocking_read(&mut adc2_pin2, SampleTime::CYCLES160_5); |
| 57 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; | 53 | let volt: f32 = 3.3 * raw as f32 / max2 as f32; |
| 58 | info!("Read adc2 pin 2 {}", volt); | 54 | info!("Read adc2 pin 2 {}", volt); |
| 59 | 55 | ||
| 60 | // **** ADC4 blocking read **** | 56 | // **** ADC4 blocking read **** |
| 61 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 57 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 62 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 58 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 63 | info!("Read adc4 pin 1 {}", volt); | 59 | info!("Read adc4 pin 1 {}", volt); |
| 64 | 60 | ||
| 65 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 61 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 66 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 62 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 67 | info!("Read adc4 pin 2 {}", volt); | 63 | info!("Read adc4 pin 2 {}", volt); |
| 68 | 64 | ||
diff --git a/examples/stm32wba/src/bin/adc.rs b/examples/stm32wba/src/bin/adc.rs index 8c80470b8..177aab3f3 100644 --- a/examples/stm32wba/src/bin/adc.rs +++ b/examples/stm32wba/src/bin/adc.rs | |||
| @@ -17,15 +17,15 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 17 | let mut adc4_pin2 = p.PA1; // A5 | 17 | let mut adc4_pin2 = p.PA1; // A5 |
| 18 | adc4.set_resolution(adc4::Resolution::BITS12); | 18 | adc4.set_resolution(adc4::Resolution::BITS12); |
| 19 | adc4.set_averaging(adc4::Averaging::Samples256); | 19 | adc4.set_averaging(adc4::Averaging::Samples256); |
| 20 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | 20 | |
| 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 22 | 22 | ||
| 23 | // **** ADC4 blocking read **** | 23 | // **** ADC4 blocking read **** |
| 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; | 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; |
| 26 | info!("Read adc4 pin 1 {}", volt); | 26 | info!("Read adc4 pin 1 {}", volt); |
| 27 | 27 | ||
| 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 30 | info!("Read adc4 pin 2 {}", volt); | 30 | info!("Read adc4 pin 2 {}", volt); |
| 31 | 31 | ||
diff --git a/examples/stm32wba6/src/bin/adc.rs b/examples/stm32wba6/src/bin/adc.rs index 8c80470b8..0887e124c 100644 --- a/examples/stm32wba6/src/bin/adc.rs +++ b/examples/stm32wba6/src/bin/adc.rs | |||
| @@ -17,15 +17,14 @@ async fn main(_spawner: embassy_executor::Spawner) { | |||
| 17 | let mut adc4_pin2 = p.PA1; // A5 | 17 | let mut adc4_pin2 = p.PA1; // A5 |
| 18 | adc4.set_resolution(adc4::Resolution::BITS12); | 18 | adc4.set_resolution(adc4::Resolution::BITS12); |
| 19 | adc4.set_averaging(adc4::Averaging::Samples256); | 19 | adc4.set_averaging(adc4::Averaging::Samples256); |
| 20 | adc4.set_sample_time(adc4::SampleTime::CYCLES1_5); | ||
| 21 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); | 20 | let max4 = adc4::resolution_to_max_count(adc4::Resolution::BITS12); |
| 22 | 21 | ||
| 23 | // **** ADC4 blocking read **** | 22 | // **** ADC4 blocking read **** |
| 24 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1); | 23 | let raw: u16 = adc4.blocking_read(&mut adc4_pin1, adc4::SampleTime::CYCLES1_5); |
| 25 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; | 24 | let volt: f32 = 3.0 * raw as f32 / max4 as f32; |
| 26 | info!("Read adc4 pin 1 {}", volt); | 25 | info!("Read adc4 pin 1 {}", volt); |
| 27 | 26 | ||
| 28 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2); | 27 | let raw: u16 = adc4.blocking_read(&mut adc4_pin2, adc4::SampleTime::CYCLES1_5); |
| 29 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; | 28 | let volt: f32 = 3.3 * raw as f32 / max4 as f32; |
| 30 | info!("Read adc4 pin 2 {}", volt); | 29 | info!("Read adc4 pin 2 {}", volt); |
| 31 | 30 | ||
diff --git a/examples/stm32wl/src/bin/adc.rs b/examples/stm32wl/src/bin/adc.rs index 6b21b086b..adabe0df8 100644 --- a/examples/stm32wl/src/bin/adc.rs +++ b/examples/stm32wl/src/bin/adc.rs | |||
| @@ -18,11 +18,11 @@ async fn main(_spawner: Spawner) { | |||
| 18 | info!("Hello World!"); | 18 | info!("Hello World!"); |
| 19 | 19 | ||
| 20 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); | 20 | let mut adc = Adc::new_with_clock(p.ADC1, Clock::Sync { div: CkModePclk::DIV1 }); |
| 21 | adc.set_sample_time(SampleTime::CYCLES79_5); | 21 | |
| 22 | let mut pin = p.PB2; | 22 | let mut pin = p.PB2; |
| 23 | 23 | ||
| 24 | let mut vrefint = adc.enable_vrefint(); | 24 | let mut vrefint = adc.enable_vrefint(); |
| 25 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 25 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); |
| 26 | let convert_to_millivolts = |sample| { | 26 | let convert_to_millivolts = |sample| { |
| 27 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | 27 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf |
| 28 | // 6.3.3 Embedded internal reference voltage | 28 | // 6.3.3 Embedded internal reference voltage |
| @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { | |||
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | loop { | 34 | loop { |
| 35 | let v = adc.blocking_read(&mut pin); | 35 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); |
| 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 36 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 37 | Timer::after_millis(100).await; | 37 | Timer::after_millis(100).await; |
| 38 | } | 38 | } |
diff --git a/examples/stm32wle5/src/bin/adc.rs b/examples/stm32wle5/src/bin/adc.rs index 8b830a1e6..4e0574d97 100644 --- a/examples/stm32wle5/src/bin/adc.rs +++ b/examples/stm32wle5/src/bin/adc.rs | |||
| @@ -73,11 +73,10 @@ async fn async_main(_spawner: Spawner) { | |||
| 73 | info!("Hello World!"); | 73 | info!("Hello World!"); |
| 74 | 74 | ||
| 75 | let mut adc = Adc::new(p.ADC1); | 75 | let mut adc = Adc::new(p.ADC1); |
| 76 | adc.set_sample_time(SampleTime::CYCLES79_5); | ||
| 77 | let mut pin = p.PA10; | 76 | let mut pin = p.PA10; |
| 78 | 77 | ||
| 79 | let mut vrefint = adc.enable_vrefint(); | 78 | let mut vrefint = adc.enable_vrefint(); |
| 80 | let vrefint_sample = adc.blocking_read(&mut vrefint); | 79 | let vrefint_sample = adc.blocking_read(&mut vrefint, SampleTime::CYCLES79_5); |
| 81 | let convert_to_millivolts = |sample| { | 80 | let convert_to_millivolts = |sample| { |
| 82 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf | 81 | // From https://www.st.com/resource/en/datasheet/stm32g031g8.pdf |
| 83 | // 6.3.3 Embedded internal reference voltage | 82 | // 6.3.3 Embedded internal reference voltage |
| @@ -87,7 +86,7 @@ async fn async_main(_spawner: Spawner) { | |||
| 87 | }; | 86 | }; |
| 88 | 87 | ||
| 89 | loop { | 88 | loop { |
| 90 | let v = adc.blocking_read(&mut pin); | 89 | let v = adc.blocking_read(&mut pin, SampleTime::CYCLES79_5); |
| 91 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); | 90 | info!("--> {} - {} mV", v, convert_to_millivolts(v)); |
| 92 | Timer::after_secs(1).await; | 91 | Timer::after_secs(1).await; |
| 93 | } | 92 | } |
diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs index d34bbb255..747b11e7f 100644 --- a/tests/stm32/src/bin/dac.rs +++ b/tests/stm32/src/bin/dac.rs | |||
| @@ -10,7 +10,7 @@ use core::f32::consts::PI; | |||
| 10 | use common::*; | 10 | use common::*; |
| 11 | use defmt::assert; | 11 | use defmt::assert; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::adc::Adc; | 13 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 14 | use embassy_stm32::dac::{DacCh1, Value}; | 14 | use embassy_stm32::dac::{DacCh1, Value}; |
| 15 | use embassy_time::Timer; | 15 | use embassy_time::Timer; |
| 16 | use micromath::F32Ext; | 16 | use micromath::F32Ext; |
| @@ -37,7 +37,7 @@ async fn main(_spawner: Spawner) { | |||
| 37 | dac.set(Value::Bit8(0)); | 37 | dac.set(Value::Bit8(0)); |
| 38 | // Now wait a little to obtain a stable value | 38 | // Now wait a little to obtain a stable value |
| 39 | Timer::after_millis(30).await; | 39 | Timer::after_millis(30).await; |
| 40 | let offset = adc.blocking_read(&mut adc_pin); | 40 | let offset = adc.blocking_read(&mut adc_pin, SampleTime::from_bits(0)); |
| 41 | 41 | ||
| 42 | for v in 0..=255 { | 42 | for v in 0..=255 { |
| 43 | // First set the DAC output value | 43 | // First set the DAC output value |
| @@ -48,7 +48,10 @@ async fn main(_spawner: Spawner) { | |||
| 48 | Timer::after_millis(30).await; | 48 | Timer::after_millis(30).await; |
| 49 | 49 | ||
| 50 | // Need to steal the peripherals here because PA4 is obviously in use already | 50 | // Need to steal the peripherals here because PA4 is obviously in use already |
| 51 | let measured = adc.blocking_read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); | 51 | let measured = adc.blocking_read( |
| 52 | &mut unsafe { embassy_stm32::Peripherals::steal() }.PA4, | ||
| 53 | SampleTime::from_bits(0), | ||
| 54 | ); | ||
| 52 | // Calibrate and normalize the measurement to get close to the dac_output_val | 55 | // Calibrate and normalize the measurement to get close to the dac_output_val |
| 53 | let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; | 56 | let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; |
| 54 | 57 | ||
diff --git a/tests/stm32/src/bin/dac_l1.rs b/tests/stm32/src/bin/dac_l1.rs index e6400f28e..2fe0cf1f1 100644 --- a/tests/stm32/src/bin/dac_l1.rs +++ b/tests/stm32/src/bin/dac_l1.rs | |||
| @@ -10,7 +10,7 @@ use core::f32::consts::PI; | |||
| 10 | use common::*; | 10 | use common::*; |
| 11 | use defmt::assert; | 11 | use defmt::assert; |
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_stm32::adc::Adc; | 13 | use embassy_stm32::adc::{Adc, SampleTime}; |
| 14 | use embassy_stm32::dac::{DacCh1, Value}; | 14 | use embassy_stm32::dac::{DacCh1, Value}; |
| 15 | use embassy_stm32::{bind_interrupts, peripherals}; | 15 | use embassy_stm32::{bind_interrupts, peripherals}; |
| 16 | use embassy_time::Timer; | 16 | use embassy_time::Timer; |
| @@ -47,7 +47,7 @@ async fn main(_spawner: Spawner) { | |||
| 47 | dac.set(Value::Bit8(0)); | 47 | dac.set(Value::Bit8(0)); |
| 48 | // Now wait a little to obtain a stable value | 48 | // Now wait a little to obtain a stable value |
| 49 | Timer::after_millis(30).await; | 49 | Timer::after_millis(30).await; |
| 50 | let offset = adc.read(&mut adc_pin).await; | 50 | let offset = adc.read(&mut adc_pin, SampleTime::from_bits(0)).await; |
| 51 | 51 | ||
| 52 | for v in 0..=255 { | 52 | for v in 0..=255 { |
| 53 | // First set the DAC output value | 53 | // First set the DAC output value |
| @@ -58,7 +58,12 @@ async fn main(_spawner: Spawner) { | |||
| 58 | Timer::after_millis(30).await; | 58 | Timer::after_millis(30).await; |
| 59 | 59 | ||
| 60 | // Need to steal the peripherals here because PA4 is obviously in use already | 60 | // Need to steal the peripherals here because PA4 is obviously in use already |
| 61 | let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4).await; | 61 | let measured = adc |
| 62 | .read( | ||
| 63 | &mut unsafe { embassy_stm32::Peripherals::steal() }.PA4, | ||
| 64 | SampleTime::from_bits(0), | ||
| 65 | ) | ||
| 66 | .await; | ||
| 62 | // Calibrate and normalize the measurement to get close to the dac_output_val | 67 | // Calibrate and normalize the measurement to get close to the dac_output_val |
| 63 | let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; | 68 | let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; |
| 64 | 69 | ||
