aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/adc/g4.rs125
-rw-r--r--examples/stm32g4/src/bin/adc_differential.rs6
2 files changed, 51 insertions, 80 deletions
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index c0fb7c733..e622e2a23 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -241,35 +241,6 @@ impl<'d, T: Instance> Adc<'d, T> {
241 super::Vbat {} 241 super::Vbat {}
242 } 242 }
243 243
244 /// Enable differential channel.
245 /// Caution:
246 /// : When configuring the channel ā€œiā€ in differential input mode, its negative input voltage VINN[i]
247 /// is connected to another channel. As a consequence, this channel is no longer usable in
248 /// single-ended mode or in differential mode and must never be configured to be converted.
249 /// Some channels are shared between ADC1/ADC2/ADC3/ADC4/ADC5: this can make the
250 /// channel on the other ADC unusable. The only exception is when ADC master and the slave
251 /// operate in interleaved mode.
252 #[cfg(stm32g4)]
253 fn set_differential_channel(&mut self, ch: usize, enable: bool) {
254 T::regs().cr().modify(|w| w.set_aden(false)); // disable adc
255 T::regs().difsel().modify(|w| {
256 w.set_difsel(
257 ch,
258 if enable {
259 Difsel::DIFFERENTIAL
260 } else {
261 Difsel::SINGLE_ENDED
262 },
263 );
264 });
265 T::regs().cr().modify(|w| w.set_aden(true));
266 }
267
268 #[cfg(stm32g4)]
269 pub fn set_differential(&mut self, channel: &mut impl AdcChannel<T>, enable: bool) {
270 self.set_differential_channel(channel.channel() as usize, enable);
271 }
272
273 /// Set oversampling shift. 244 /// Set oversampling shift.
274 #[cfg(stm32g4)] 245 #[cfg(stm32g4)]
275 pub fn set_oversampling_shift(&mut self, shift: u8) { 246 pub fn set_oversampling_shift(&mut self, shift: u8) {
@@ -331,7 +302,17 @@ impl<'d, T: Instance> Adc<'d, T> {
331 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 { 302 pub fn blocking_read(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 {
332 channel.setup(); 303 channel.setup();
333 304
334 self.read_channel(channel, sample_time) 305 Self::configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter());
306
307 #[cfg(stm32h7)]
308 {
309 T::regs().cfgr2().modify(|w| w.set_lshift(0));
310 T::regs()
311 .pcsel()
312 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED));
313 }
314
315 self.convert()
335 } 316 }
336 317
337 /// Start regular adc conversion 318 /// Start regular adc conversion
@@ -404,11 +385,9 @@ impl<'d, T: Instance> Adc<'d, T> {
404 Self::stop_regular_conversions(); 385 Self::stop_regular_conversions();
405 Self::enable(); 386 Self::enable();
406 387
407 Self::configure_sequence(sequence.map(|(channel, sample_time)| { 388 Self::configure_sequence(
408 channel.setup(); 389 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
409 390 );
410 (channel.channel, sample_time)
411 }));
412 391
413 // Set continuous mode with oneshot dma. 392 // Set continuous mode with oneshot dma.
414 // Clear overrun flag before starting transfer. 393 // Clear overrun flag before starting transfer.
@@ -451,14 +430,14 @@ impl<'d, T: Instance> Adc<'d, T> {
451 }); 430 });
452 } 431 }
453 432
454 pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = (u8, SampleTime)>) { 433 pub(super) fn configure_sequence(sequence: impl ExactSizeIterator<Item = ((u8, bool), SampleTime)>) {
455 // Set sequence length 434 // Set sequence length
456 T::regs().sqr1().modify(|w| { 435 T::regs().sqr1().modify(|w| {
457 w.set_l(sequence.len() as u8 - 1); 436 w.set_l(sequence.len() as u8 - 1);
458 }); 437 });
459 438
460 // Configure channels and ranks 439 // Configure channels and ranks
461 for (_i, (ch, sample_time)) in sequence.enumerate() { 440 for (_i, ((ch, is_differential), sample_time)) in sequence.enumerate() {
462 let sample_time = sample_time.into(); 441 let sample_time = sample_time.into();
463 if ch <= 9 { 442 if ch <= 9 {
464 T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time)); 443 T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time));
@@ -489,6 +468,24 @@ impl<'d, T: Instance> Adc<'d, T> {
489 } 468 }
490 _ => unreachable!(), 469 _ => unreachable!(),
491 } 470 }
471
472 #[cfg(stm32g4)]
473 {
474 T::regs().cr().modify(|w| w.set_aden(false)); // disable adc
475
476 T::regs().difsel().modify(|w| {
477 w.set_difsel(
478 ch.into(),
479 if is_differential {
480 Difsel::DIFFERENTIAL
481 } else {
482 Difsel::SINGLE_ENDED
483 },
484 );
485 });
486
487 T::regs().cr().modify(|w| w.set_aden(true)); // enable adc
488 }
492 } 489 }
493 } 490 }
494 491
@@ -548,12 +545,9 @@ impl<'d, T: Instance> Adc<'d, T> {
548 Self::enable(); 545 Self::enable();
549 546
550 //adc side setup 547 //adc side setup
551 548 Self::configure_sequence(
552 Self::configure_sequence(sequence.map(|(mut channel, sample_time)| { 549 sequence.map(|(channel, sample_time)| ((channel.channel, channel.is_differential), sample_time)),
553 channel.setup(); 550 );
554
555 (channel.channel, sample_time)
556 }));
557 551
558 // Clear overrun flag before starting transfer. 552 // Clear overrun flag before starting transfer.
559 T::regs().isr().modify(|reg| { 553 T::regs().isr().modify(|reg| {
@@ -630,8 +624,17 @@ impl<'d, T: Instance> Adc<'d, T> {
630 624
631 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1)); 625 T::regs().jsqr().modify(|w| w.set_jl(N as u8 - 1));
632 626
633 for (n, (mut channel, sample_time)) in sequence.into_iter().enumerate() { 627 for (n, (channel, sample_time)) in sequence.into_iter().enumerate() {
634 Self::configure_channel(&mut channel, sample_time); 628 let sample_time = sample_time.into();
629 if channel.channel() <= 9 {
630 T::regs()
631 .smpr()
632 .modify(|reg| reg.set_smp(channel.channel() as _, sample_time));
633 } else {
634 T::regs()
635 .smpr2()
636 .modify(|reg| reg.set_smp((channel.channel() - 10) as _, sample_time));
637 }
635 638
636 let idx = match n { 639 let idx = match n {
637 0..=3 => n, 640 0..=3 => n,
@@ -733,38 +736,6 @@ impl<'d, T: Instance> Adc<'d, T> {
733 T::regs().ier().modify(|r| r.set_jeosie(enable)); 736 T::regs().ier().modify(|r| r.set_jeosie(enable));
734 } 737 }
735 738
736 fn configure_channel(channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
737 // Configure channel
738 Self::set_channel_sample_time(channel.channel(), sample_time);
739 }
740
741 fn read_channel(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) -> u16 {
742 Self::configure_channel(channel, sample_time);
743 #[cfg(stm32h7)]
744 {
745 T::regs().cfgr2().modify(|w| w.set_lshift(0));
746 T::regs()
747 .pcsel()
748 .write(|w| w.set_pcsel(channel.channel() as _, Pcsel::PRESELECTED));
749 }
750
751 T::regs().sqr1().write(|reg| {
752 reg.set_sq(0, channel.channel());
753 reg.set_l(0);
754 });
755
756 self.convert()
757 }
758
759 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
760 let sample_time = sample_time.into();
761 if ch <= 9 {
762 T::regs().smpr().modify(|reg| reg.set_smp(ch as _, sample_time));
763 } else {
764 T::regs().smpr2().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
765 }
766 }
767
768 // Stop regular conversions 739 // Stop regular conversions
769 fn stop_regular_conversions() { 740 fn stop_regular_conversions() {
770 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() { 741 if T::regs().cr().read().adstart() && !T::regs().cr().read().addis() {
diff --git a/examples/stm32g4/src/bin/adc_differential.rs b/examples/stm32g4/src/bin/adc_differential.rs
index a6e2f7d33..2773723e9 100644
--- a/examples/stm32g4/src/bin/adc_differential.rs
+++ b/examples/stm32g4/src/bin/adc_differential.rs
@@ -30,16 +30,16 @@ async fn main(_spawner: Spawner) {
30 config.rcc.mux.adc12sel = mux::Adcsel::SYS; 30 config.rcc.mux.adc12sel = mux::Adcsel::SYS;
31 config.rcc.sys = Sysclk::PLL1_R; 31 config.rcc.sys = Sysclk::PLL1_R;
32 } 32 }
33 let mut p = embassy_stm32::init(config); 33 let 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_differential(&mut p.PA0, true); //p:pa0,n:pa1 36 let mut differential_channel = (p.PA0, p.PA1);
37 37
38 // can also use 38 // can also use
39 // adc.set_differential_channel(1, true); 39 // adc.set_differential_channel(1, true);
40 info!("adc initialized"); 40 info!("adc initialized");
41 loop { 41 loop {
42 let measured = adc.blocking_read(&mut p.PA0, SampleTime::CYCLES247_5); 42 let measured = adc.blocking_read(&mut differential_channel, SampleTime::CYCLES247_5);
43 info!("data: {}", measured); 43 info!("data: {}", measured);
44 Timer::after_millis(500).await; 44 Timer::after_millis(500).await;
45 } 45 }