|
| 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 | +} |
0 commit comments