Skip to content

Commit 1024b61

Browse files
committed
Add example for using ADC1 and 2 together
Complete implementation of clock selection
1 parent db96799 commit 1024b61

File tree

4 files changed

+103
-9
lines changed

4 files changed

+103
-9
lines changed

examples/adc.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
//! Example of reading a voltage with ADC1
2+
//!
3+
//! For an example of using ADC3, see examples/temperature.rs
4+
//! For an example of using ADC1 and ADC2 together, see examples/adc12.rs
5+
16
#![no_main]
27
#![no_std]
38

@@ -50,25 +55,32 @@ fn main() -> ! {
5055
let mut delay = Delay::new(cp.SYST, ccdr.clocks);
5156

5257
// Setup ADC
53-
let mut adc3 =
54-
adc::Adc::adc3(dp.ADC3, &mut delay, ccdr.peripheral.ADC3, &ccdr.clocks)
55-
.enable();
56-
adc3.set_resolution(adc::Resolution::SIXTEENBIT);
58+
let mut adc1 = adc::Adc::adc1(
59+
dp.ADC1,
60+
&mut delay,
61+
ccdr.peripheral.ADC12,
62+
&ccdr.clocks,
63+
)
64+
.enable();
65+
adc1.set_resolution(adc::Resolution::SIXTEENBIT);
66+
67+
// We can't use ADC2 here because ccdr.peripheral.ADC12 has been
68+
// consumed. See examples/adc12.rs
5769

5870
// Setup GPIOC
5971
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
6072

6173
// Configure pc0 as an analog input
62-
let mut channel = gpioc.pc0.into_analog();
74+
let mut channel = gpioc.pc0.into_analog(); // ANALOG IN 10
6375

6476
loop {
65-
let data: u32 = adc3.read(&mut channel).unwrap();
77+
let data: u32 = adc1.read(&mut channel).unwrap();
6678
// voltage = reading * (vref/resolution)
6779
println!(
6880
log,
6981
"ADC reading: {}, voltage for nucleo: {}",
7082
data,
71-
data as f32 * (3.3 / adc3.max_sample() as f32)
83+
data as f32 * (3.3 / adc1.max_sample() as f32)
7284
);
7385
}
7486
}

examples/adc12.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
//! Example of using ADC1 and ADC2 together
2+
//!
3+
//! For an example of using ADC3, see examples/temperature.rs
4+
//! For an example of using ADC1 alone, see examples/adc.rs
5+
6+
#![deny(unsafe_code)]
7+
#![no_main]
8+
#![no_std]
9+
10+
extern crate panic_itm;
11+
12+
use cortex_m;
13+
use cortex_m_rt::entry;
14+
15+
use stm32h7xx_hal::{adc, delay::Delay, pac, prelude::*};
16+
17+
use cortex_m_log::println;
18+
use cortex_m_log::{
19+
destination::Itm, printer::itm::InterruptSync as InterruptSyncItm,
20+
};
21+
22+
#[entry]
23+
fn main() -> ! {
24+
let cp = cortex_m::Peripherals::take().unwrap();
25+
let dp = pac::Peripherals::take().unwrap();
26+
let mut log = InterruptSyncItm::new(Itm::new(cp.ITM));
27+
28+
// Constrain and Freeze power
29+
println!(log, "Setup PWR... ");
30+
let pwr = dp.PWR.constrain();
31+
let vos = pwr.freeze();
32+
33+
// Constrain and Freeze clock
34+
println!(log, "Setup RCC... ");
35+
let rcc = dp.RCC.constrain();
36+
37+
let ccdr = rcc
38+
.sys_ck(100.mhz())
39+
.pll2_p_ck(4.mhz()) // Default adc_ker_ck_input
40+
.freeze(vos, &dp.SYSCFG);
41+
42+
println!(log, "");
43+
println!(log, "stm32h7xx-hal example - ADC1 and ADC2");
44+
println!(log, "");
45+
46+
let mut delay = Delay::new(cp.SYST, ccdr.clocks);
47+
48+
// Setup ADC1 and ADC2
49+
let (adc1, adc2) = adc::adc12(
50+
dp.ADC1,
51+
dp.ADC2,
52+
&mut delay,
53+
ccdr.peripheral.ADC12,
54+
&ccdr.clocks,
55+
);
56+
57+
let mut adc1 = adc1.enable();
58+
adc1.set_resolution(adc::Resolution::SIXTEENBIT);
59+
60+
let mut adc2 = adc2.enable();
61+
adc2.set_resolution(adc::Resolution::SIXTEENBIT);
62+
63+
// Setup GPIOC
64+
// NOTE: PC2 and PC3 are only pinned out on TFBGA packages!!
65+
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
66+
let mut channel_pc2 = gpioc.pc2.into_analog(); // AIN 12
67+
let mut channel_pc3 = gpioc.pc3.into_analog(); // AIN 13
68+
69+
loop {
70+
let data_pc2: u32 = adc1.read(&mut channel_pc2).unwrap();
71+
let data_pc3: u32 = adc2.read(&mut channel_pc3).unwrap();
72+
// voltage = reading * (vref/resolution)
73+
println!(log, "ADC readings: {} {}", data_pc2, data_pc3);
74+
}
75+
}

examples/temperature.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
//! Example for using ADC3 to read the internal temperature sensor
2+
//!
3+
//! For an example of using ADC1, see examples/adc.rs
4+
//! For an example of using ADC1 and ADC2 together, see examples/adc12.rs
5+
16
#![deny(unsafe_code)]
27
#![no_main]
38
#![no_std]
@@ -37,7 +42,7 @@ fn main() -> ! {
3742

3843
let ccdr = rcc
3944
.sys_ck(100.mhz())
40-
.per_ck(4.mhz())
45+
.pll2_p_ck(4.mhz()) // Default adc_ker_ck_input
4146
.freeze(vos, &dp.SYSCFG);
4247

4348
println!(log, "");

src/adc.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Analog to Digital Converter (ADC)
22
//!
33
//! ADC1 and ADC2 share a reset line. To initialise both of them, use the
4-
//! `adc12` method.
4+
//! [`adc12`](adc12) method.
55
66
use crate::hal::adc::{Channel, OneShot};
77
use crate::hal::blocking::delay::DelayUs;
@@ -296,6 +296,8 @@ pub struct StoredConfig(AdcSampleTime, Resolution, AdcLshift);
296296
fn check_clock(prec: &impl AdcClkSelGetter, clocks: &CoreClocks) -> Hertz {
297297
// Select Kernel Clock
298298
let adc_clock = match prec.get_kernel_clk_mux() {
299+
Val(rec::AdcClkSel::PLL2_P) => clocks.pll2_p_ck(),
300+
Val(rec::AdcClkSel::PLL3_R) => clocks.pll3_r_ck(),
299301
Val(rec::AdcClkSel::PER) => clocks.per_ck(),
300302
_ => unreachable!(),
301303
}

0 commit comments

Comments
 (0)