Skip to content

Commit d0f8630

Browse files
committed
Add adc examples
1 parent c819b92 commit d0f8630

File tree

2 files changed

+173
-0
lines changed

2 files changed

+173
-0
lines changed

examples/adc.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
//! Example of reading a voltage with ADC1
2+
//!
3+
//! For an example of using ADC1 and ADC2 together, see examples/adc12.rs
4+
5+
#![no_main]
6+
#![no_std]
7+
8+
use cortex_m_rt::entry;
9+
10+
use embedded_hal_02::adc::OneShot;
11+
use stm32h5xx_hal::{
12+
adc, delay::Delay, pac, prelude::*, rcc::rec::AdcDacClkSel,
13+
};
14+
use utilities::logger::info;
15+
16+
#[macro_use]
17+
mod utilities;
18+
19+
#[entry]
20+
fn main() -> ! {
21+
utilities::logger::init();
22+
let cp = cortex_m::Peripherals::take().unwrap();
23+
let dp = pac::Peripherals::take().unwrap();
24+
25+
// Constrain and Freeze power
26+
info!("Setup PWR... ");
27+
let pwr = dp.PWR.constrain();
28+
let pwrcfg = pwr.freeze();
29+
30+
// Constrain and Freeze clock
31+
info!("Setup RCC... ");
32+
let rcc = dp.RCC.constrain();
33+
34+
// We need to configure a clock for adc_ker_ck_input. The default
35+
// adc_ker_ck_input is pll2_p_ck, but we will use per_ck. per_ck is sourced
36+
// from the 64MHz HSI
37+
//
38+
// adc_ker_ck_input is then divided by the ADC prescaler to give f_adc. The
39+
// maximum f_adc is 50MHz
40+
let mut ccdr = rcc
41+
.sys_ck(192.MHz())
42+
.pll1_q_ck(64.MHz())
43+
.freeze(&pwrcfg, &dp.SBS);
44+
45+
// Switch adc_ker_ck_input multiplexer to per_ck
46+
ccdr.peripheral.kernel_adcdac_clk_mux(AdcDacClkSel::HsiKer);
47+
48+
info!("");
49+
info!("stm32h5xx-hal example - ADC");
50+
info!("");
51+
52+
let mut delay = Delay::new(cp.SYST, &ccdr.clocks);
53+
54+
// Setup ADC
55+
let mut adc1 = adc::Adc::new(
56+
dp.ADC1,
57+
4.MHz(),
58+
&mut delay,
59+
ccdr.peripheral.ADC,
60+
&ccdr.clocks,
61+
&pwrcfg,
62+
);
63+
64+
let mut temp = adc::Temperature::new();
65+
temp.enable(&mut adc1);
66+
let mut adc1: adc::Adc<
67+
stm32h5::Periph<pac::adc1::RegisterBlock, 1107460096>,
68+
adc::Enabled,
69+
> = adc1.enable();
70+
71+
// We can't use ADC2 here because ccdr.peripheral.ADC12 has been
72+
// consumed. See examples/adc12.rs
73+
74+
// Setup GPIOC
75+
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
76+
77+
// Configure pc0 as an analog input
78+
let mut channel = gpioc.pc0.into_analog(); // ANALOG IN 10
79+
80+
loop {
81+
let data = adc1.read(&mut channel).unwrap();
82+
// voltage = reading * (vref/resolution)
83+
info!(
84+
"ADC reading: {}, voltage for nucleo: {}V. Temp reading: {}",
85+
data,
86+
data as f32 * (3.3 / adc1.slope() as f32),
87+
adc1.read(&mut temp).unwrap()
88+
);
89+
}
90+
}

examples/adc12.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//! Example of using ADC1 and ADC2 together
2+
//!
3+
//! This is not available for H503 since it only has ADC1
4+
//!
5+
//! For an example of using ADC1 alone, see examples/adc.rs
6+
7+
#![no_main]
8+
#![no_std]
9+
10+
use cortex_m_rt::entry;
11+
12+
use embedded_hal_02::adc::OneShot;
13+
use stm32h5xx_hal::{
14+
adc, delay::Delay, pac, prelude::*, rcc::rec::AdcDacClkSel,
15+
};
16+
use utilities::logger::info;
17+
18+
#[macro_use]
19+
mod utilities;
20+
21+
#[entry]
22+
fn main() -> ! {
23+
utilities::logger::init();
24+
let cp = cortex_m::Peripherals::take().unwrap();
25+
let dp = pac::Peripherals::take().unwrap();
26+
27+
// Constrain and Freeze power
28+
info!("Setup PWR... ");
29+
let pwr = dp.PWR.constrain();
30+
let pwrcfg = pwr.freeze();
31+
32+
// Constrain and Freeze clock
33+
info!("Setup RCC... ");
34+
let rcc = dp.RCC.constrain();
35+
36+
// We need to configure a clock for adc_ker_ck_input. The default
37+
// adc_ker_ck_input is pll2_p_ck, but we will use per_ck. per_ck is sourced
38+
// from the 64MHz HSI
39+
//
40+
// adc_ker_ck_input is then divided by the ADC prescaler to give f_adc. The
41+
// maximum f_adc is 50MHz
42+
let mut ccdr = rcc
43+
.sys_ck(192.MHz())
44+
.pll1_q_ck(64.MHz())
45+
.freeze(&pwrcfg, &dp.SBS);
46+
47+
// Switch adc_ker_ck_input multiplexer to per_ck
48+
ccdr.peripheral.kernel_adcdac_clk_mux(AdcDacClkSel::HsiKer);
49+
50+
info!("");
51+
info!("stm32h5xx-hal example - ADC1 and ADC2");
52+
info!("");
53+
54+
let mut delay = Delay::new(cp.SYST, &ccdr.clocks);
55+
56+
// Setup ADC
57+
// Setup ADC1 and ADC2
58+
let (adc1, adc2) = adc::adc12(
59+
dp.ADC1,
60+
dp.ADC2,
61+
4.MHz(),
62+
&mut delay,
63+
ccdr.peripheral.ADC,
64+
&ccdr.clocks,
65+
&pwrcfg,
66+
);
67+
68+
let mut adc1 = adc1.enable();
69+
let mut adc2 = adc2.enable();
70+
71+
// Setup GPIOC
72+
// NOTE: PC2 and PC3 are only pinned out on TFBGA packages!!
73+
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
74+
let mut channel_pc2 = gpioc.pc2.into_analog(); // AIN 12
75+
let mut channel_pc3 = gpioc.pc3.into_analog(); // AIN 13
76+
77+
loop {
78+
let data_pc2: u32 = adc1.read(&mut channel_pc2).unwrap();
79+
let data_pc3: u32 = adc2.read(&mut channel_pc3).unwrap();
80+
// voltage = reading * (vref/resolution)
81+
info!("ADC readings: {} {}", data_pc2, data_pc3);
82+
}
83+
}

0 commit comments

Comments
 (0)