Skip to content

Commit 7eb5b14

Browse files
committed
move adc docs on module level
1 parent 51022eb commit 7eb5b14

File tree

2 files changed

+124
-133
lines changed

2 files changed

+124
-133
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
99

1010
### Changed
1111

12-
- move gpio impls in subdir, remove unused `From` impls
12+
- move gpio, dma impls, adc pins in subdir, remove unused `From` impls [#658] [#664]
1313
- Bump `embedded-hal` to `1.0.0-alpha.10`. See [their changelog][embedded-hal-1.0.0-alpha.10] for further details. Note that this included breaking changes to the previous alpha APIs. [#663]
1414

15+
[#658]: https://github.com/stm32-rs/stm32f4xx-hal/pull/658
1516
[#663]: https://github.com/stm32-rs/stm32f4xx-hal/pull/663
17+
[#664]: https://github.com/stm32-rs/stm32f4xx-hal/pull/664
1618
[embedded-hal-1.0.0-alpha.10]: https://github.com/rust-embedded/embedded-hal/blob/v1.0.0-alpha.10/embedded-hal/CHANGELOG.md
1719

1820
## [v0.16.2] - 2023-06-27

src/adc.rs

Lines changed: 121 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,125 @@
11
//! Analog to digital converter configuration.
2-
//! According to CubeMx, all STM32F4 chips use the same ADC IP so this should be correct for all variants.
2+
//!
3+
//! # Status
4+
//! Most options relating to regular conversions are implemented. One-shot and sequences of conversions
5+
//! have been tested and work as expected.
6+
//!
7+
//! GPIO to channel mapping should be correct for all supported F4 devices. The mappings were taken from
8+
//! CubeMX. The mappings are feature gated per 4xx device but there are actually sub variants for some
9+
//! devices and some pins may be missing on some variants. The implementation has been split up and commented
10+
//! to show which pins are available on certain device variants but currently the library doesn't enforce this.
11+
//! To fully support the right pins would require 10+ more features for the various variants.
12+
//! ## Todo
13+
//! * Injected conversions
14+
//! * Analog watchdog config
15+
//! * Discontinuous mode
16+
//! # Examples
17+
//! ## One-shot conversion
18+
//! ```
19+
//! use stm32f4xx_hal::{
20+
//! gpio::gpioa,
21+
//! adc::{
22+
//! Adc,
23+
//! config::{AdcConfig, SampleTime},
24+
//! },
25+
//! };
26+
//!
27+
//! let mut adc = Adc::adc1(device.ADC1, true, AdcConfig::default());
28+
//! let pa3 = gpioa.pa3.into_analog();
29+
//! let sample = adc.convert(&pa3, SampleTime::Cycles_480);
30+
//! let millivolts = adc.sample_to_millivolts(sample);
31+
//! info!("pa3: {}mV", millivolts);
32+
//! ```
33+
//!
34+
//! ## Sequence conversion
35+
//! ```
36+
//! use stm32f4xx_hal::{
37+
//! gpio::gpioa,
38+
//! adc::{
39+
//! Adc,
40+
//! config::{AdcConfig, SampleTime, Sequence, Eoc, Scan, Clock},
41+
//! },
42+
//! };
43+
//!
44+
//! let config = AdcConfig::default()
45+
//! //We'll either need DMA or an interrupt per conversion to convert
46+
//! //multiple values in a sequence
47+
//! .end_of_conversion_interrupt(Eoc::Conversion)
48+
//! //Scan mode is also required to convert a sequence
49+
//! .scan(Scan::Enabled)
50+
//! //And since we're looking for one interrupt per conversion the
51+
//! //clock will need to be fairly slow to avoid overruns breaking
52+
//! //the sequence. If you are running in debug mode and logging in
53+
//! //the interrupt, good luck... try setting pclk2 really low.
54+
//! //(Better yet use DMA)
55+
//! .clock(Clock::Pclk2_div_8);
56+
//! let mut adc = Adc::adc1(device.ADC1, true, config);
57+
//! let pa0 = gpioa.pa0.into_analog();
58+
//! let pa3 = gpioa.pa3.into_analog();
59+
//! adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_112);
60+
//! adc.configure_channel(&pa3, Sequence::Two, SampleTime::Cycles_480);
61+
//! adc.configure_channel(&pa0, Sequence::Three, SampleTime::Cycles_112);
62+
//! adc.start_conversion();
63+
//! ```
64+
//!
65+
//! ## External trigger
66+
//!
67+
//! A common mistake on STM forums is enabling continuous mode but that causes it to start
68+
//! capturing on the first trigger and capture as fast as possible forever, regardless of
69+
//! future triggers. Continuous mode is disabled by default but I thought it was worth
70+
//! highlighting.
71+
//!
72+
//! Getting the timer config right to make sure it's sending the event the ADC is listening
73+
//! to can be a bit of a pain but the key fields are highlighted below. Try hooking a timer
74+
//! channel up to an external pin with an LED or oscilloscope attached to check it's really
75+
//! generating pulses if the ADC doesn't seem to be triggering.
76+
//! ```
77+
//! use stm32f4xx_hal::{
78+
//! gpio::gpioa,
79+
//! adc::{
80+
//! Adc,
81+
//! config::{AdcConfig, SampleTime, Sequence, Eoc, Scan, Clock},
82+
//! },
83+
//! };
84+
//!
85+
//! let config = AdcConfig::default()
86+
//! //Set the trigger you want
87+
//! .external_trigger(TriggerMode::RisingEdge, ExternalTrigger::Tim_1_cc_1);
88+
//! let mut adc = Adc::adc1(device.ADC1, true, config);
89+
//! let pa0 = gpioa.pa0.into_analog();
90+
//! adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_112);
91+
//! //Make sure it's enabled but don't start the conversion
92+
//! adc.enable();
93+
//!
94+
//! //Configure the timer
95+
//! let mut tim = Timer::tim1(device.TIM1, 1.hz(), clocks);
96+
//! unsafe {
97+
//! let tim = &(*TIM1::ptr());
98+
//!
99+
//! //Channel 1
100+
//! //Disable the channel before configuring it
101+
//! tim.ccer.modify(|_, w| w.cc1e().clear_bit());
102+
//!
103+
//! tim.ccmr1_output().modify(|_, w| w
104+
//! //Preload enable for channel
105+
//! .oc1pe().set_bit()
106+
//!
107+
//! //Set mode for channel, the default mode is "frozen" which won't work
108+
//! .oc1m().pwm_mode1()
109+
//! );
110+
//!
111+
//! //Set the duty cycle, 0 won't work in pwm mode but might be ok in
112+
//! //toggle mode or match mode
113+
//! let max_duty = tim.arr.read().arr().bits() as u16;
114+
//! tim.ccr1.modify(|_, w| w.ccr().bits(max_duty / 2));
115+
//!
116+
//! //Enable the channel
117+
//! tim.ccer.modify(|_, w| w.cc1e().set_bit());
118+
//!
119+
//! //Enable the TIM main Output
120+
//! tim.bdtr.modify(|_, w| w.moe().set_bit());
121+
//! }
122+
//! ```
3123
4124
#![deny(missing_docs)]
5125

@@ -424,137 +544,6 @@ pub mod config {
424544
}
425545

426546
/// Analog to Digital Converter
427-
/// # Status
428-
/// Most options relating to regular conversions are implemented. One-shot and sequences of conversions
429-
/// have been tested and work as expected.
430-
///
431-
/// GPIO to channel mapping should be correct for all supported F4 devices. The mappings were taken from
432-
/// CubeMX. The mappings are feature gated per 4xx device but there are actually sub variants for some
433-
/// devices and some pins may be missing on some variants. The implementation has been split up and commented
434-
/// to show which pins are available on certain device variants but currently the library doesn't enforce this.
435-
/// To fully support the right pins would require 10+ more features for the various variants.
436-
/// ## Todo
437-
/// * Injected conversions
438-
/// * Analog watchdog config
439-
/// * Discontinuous mode
440-
/// # Examples
441-
/// ## One-shot conversion
442-
/// ```
443-
/// use stm32f4xx_hal::{
444-
/// gpio::gpioa,
445-
/// adc::{
446-
/// Adc,
447-
/// config::AdcConfig,
448-
/// config::SampleTime,
449-
/// },
450-
/// };
451-
///
452-
/// let mut adc = Adc::adc1(device.ADC1, true, AdcConfig::default());
453-
/// let pa3 = gpioa.pa3.into_analog();
454-
/// let sample = adc.convert(&pa3, SampleTime::Cycles_480);
455-
/// let millivolts = adc.sample_to_millivolts(sample);
456-
/// info!("pa3: {}mV", millivolts);
457-
/// ```
458-
///
459-
/// ## Sequence conversion
460-
/// ```
461-
/// use stm32f4xx_hal::{
462-
/// gpio::gpioa,
463-
/// adc::{
464-
/// Adc,
465-
/// config::AdcConfig,
466-
/// config::SampleTime,
467-
/// config::Sequence,
468-
/// config::Eoc,
469-
/// config::Scan,
470-
/// config::Clock,
471-
/// },
472-
/// };
473-
///
474-
/// let config = AdcConfig::default()
475-
/// //We'll either need DMA or an interrupt per conversion to convert
476-
/// //multiple values in a sequence
477-
/// .end_of_conversion_interrupt(Eoc::Conversion)
478-
/// //Scan mode is also required to convert a sequence
479-
/// .scan(Scan::Enabled)
480-
/// //And since we're looking for one interrupt per conversion the
481-
/// //clock will need to be fairly slow to avoid overruns breaking
482-
/// //the sequence. If you are running in debug mode and logging in
483-
/// //the interrupt, good luck... try setting pclk2 really low.
484-
/// //(Better yet use DMA)
485-
/// .clock(Clock::Pclk2_div_8);
486-
/// let mut adc = Adc::adc1(device.ADC1, true, config);
487-
/// let pa0 = gpioa.pa0.into_analog();
488-
/// let pa3 = gpioa.pa3.into_analog();
489-
/// adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_112);
490-
/// adc.configure_channel(&pa3, Sequence::Two, SampleTime::Cycles_480);
491-
/// adc.configure_channel(&pa0, Sequence::Three, SampleTime::Cycles_112);
492-
/// adc.start_conversion();
493-
/// ```
494-
///
495-
/// ## External trigger
496-
///
497-
/// A common mistake on STM forums is enabling continuous mode but that causes it to start
498-
/// capturing on the first trigger and capture as fast as possible forever, regardless of
499-
/// future triggers. Continuous mode is disabled by default but I thought it was worth
500-
/// highlighting.
501-
///
502-
/// Getting the timer config right to make sure it's sending the event the ADC is listening
503-
/// to can be a bit of a pain but the key fields are highlighted below. Try hooking a timer
504-
/// channel up to an external pin with an LED or oscilloscope attached to check it's really
505-
/// generating pulses if the ADC doesn't seem to be triggering.
506-
/// ```
507-
/// use stm32f4xx_hal::{
508-
/// gpio::gpioa,
509-
/// adc::{
510-
/// Adc,
511-
/// config::AdcConfig,
512-
/// config::SampleTime,
513-
/// config::Sequence,
514-
/// config::Eoc,
515-
/// config::Scan,
516-
/// config::Clock,
517-
/// },
518-
/// };
519-
///
520-
/// let config = AdcConfig::default()
521-
/// //Set the trigger you want
522-
/// .external_trigger(TriggerMode::RisingEdge, ExternalTrigger::Tim_1_cc_1);
523-
/// let mut adc = Adc::adc1(device.ADC1, true, config);
524-
/// let pa0 = gpioa.pa0.into_analog();
525-
/// adc.configure_channel(&pa0, Sequence::One, SampleTime::Cycles_112);
526-
/// //Make sure it's enabled but don't start the conversion
527-
/// adc.enable();
528-
///
529-
/// //Configure the timer
530-
/// let mut tim = Timer::tim1(device.TIM1, 1.hz(), clocks);
531-
/// unsafe {
532-
/// let tim = &(*TIM1::ptr());
533-
///
534-
/// //Channel 1
535-
/// //Disable the channel before configuring it
536-
/// tim.ccer.modify(|_, w| w.cc1e().clear_bit());
537-
///
538-
/// tim.ccmr1_output().modify(|_, w| w
539-
/// //Preload enable for channel
540-
/// .oc1pe().set_bit()
541-
///
542-
/// //Set mode for channel, the default mode is "frozen" which won't work
543-
/// .oc1m().pwm_mode1()
544-
/// );
545-
///
546-
/// //Set the duty cycle, 0 won't work in pwm mode but might be ok in
547-
/// //toggle mode or match mode
548-
/// let max_duty = tim.arr.read().arr().bits() as u16;
549-
/// tim.ccr1.modify(|_, w| w.ccr().bits(max_duty / 2));
550-
///
551-
/// //Enable the channel
552-
/// tim.ccer.modify(|_, w| w.cc1e().set_bit());
553-
///
554-
/// //Enable the TIM main Output
555-
/// tim.bdtr.modify(|_, w| w.moe().set_bit());
556-
/// }
557-
/// ```
558547
#[derive(Clone, Copy)]
559548
pub struct Adc<ADC> {
560549
/// Current config of the ADC, kept up to date by the various set methods

0 commit comments

Comments
 (0)