diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 3007cd1e..17320649 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -7,11 +7,11 @@ autobins = false [features] stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill -stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma"] # Nucleo "sdmmc" -stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo +stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma", "dac-adc-pin"] # Nucleo "sdmmc" +stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo -stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo +stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma", "dac-adc-pin"] # Nucleo stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board @@ -23,6 +23,7 @@ ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] embassy-stm32-wpan = [] not-gpdma = [] +dac-adc-pin = [] [dependencies] teleprobe-meta = "1" @@ -42,6 +43,7 @@ cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } embedded-hal-async = { version = "=0.2.0-alpha.2" } +micromath = "2.0.0" panic-probe = { version = "0.3.0", features = ["print-defmt"] } rand_core = { version = "0.6", default-features = false } rand_chacha = { version = "0.3", default-features = false } @@ -55,6 +57,11 @@ name = "can" path = "src/bin/can.rs" required-features = [ "can",] +[[bin]] +name = "dac" +path = "src/bin/dac.rs" +required-features = [ "dac-adc-pin",] + [[bin]] name = "gpio" path = "src/bin/gpio.rs" diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs new file mode 100644 index 00000000..67a7d5b5 --- /dev/null +++ b/tests/stm32/src/bin/dac.rs @@ -0,0 +1,81 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +// required-features: dac-adc-pin + +#[path = "../common.rs"] +mod common; +use common::*; +use defmt::assert; +use embassy_executor::Spawner; +use embassy_stm32::adc::Adc; +use embassy_stm32::dac::{DacCh1, DacChannel, Value}; +use embassy_stm32::dma::NoDma; +use embassy_time::{Delay, Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + // Initialize the board and obtain a Peripherals instance + let p: embassy_stm32::Peripherals = embassy_stm32::init(config()); + + #[cfg(feature = "stm32f429zi")] + let dac_peripheral = p.DAC; + + #[cfg(any(feature = "stm32h755zi", feature = "stm32g071rb"))] + let dac_peripheral = p.DAC1; + + let mut dac: DacCh1<'_, _, NoDma> = DacCh1::new(dac_peripheral, NoDma, p.PA4); + unwrap!(dac.set_trigger_enable(false)); + + let mut adc = Adc::new(p.ADC1, &mut Delay); + + #[cfg(feature = "stm32h755zi")] + let normalization_factor = 256; + #[cfg(any(feature = "stm32f429zi", feature = "stm32g071rb"))] + let normalization_factor: i32 = 16; + + unwrap!(dac.set(Value::Bit8(0))); + // Now wait a little to obtain a stable value + Timer::after(Duration::from_millis(30)).await; + let offset = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); + + for v in 0..=255 { + // First set the DAC output value + let dac_output_val = to_sine_wave(v); + unwrap!(dac.set(Value::Bit8(dac_output_val))); + + // Now wait a little to obtain a stable value + Timer::after(Duration::from_millis(30)).await; + + // Need to steal the peripherals here because PA4 is obviously in use already + let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); + // Calibrate and normalize the measurement to get close to the dac_output_val + let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; + + info!("value / measured: {} / {}", dac_output_val, measured_normalized); + + // The deviations are quite enormous but that does not matter since this is only a quick test + assert!((dac_output_val as i16 - measured_normalized).abs() < 15); + } + + info!("Test OK"); + cortex_m::asm::bkpt(); +} + +use core::f32::consts::PI; + +use micromath::F32Ext; + +fn to_sine_wave(v: u8) -> u8 { + if v >= 128 { + // top half + let r = PI * ((v - 128) as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } else { + // bottom half + let r = PI + PI * (v as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } +} diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 3d2a9b8e..ca5cb43a 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -33,6 +33,7 @@ pub fn config() -> Config { { config.rcc.sys_ck = Some(Hertz(400_000_000)); config.rcc.pll1.q_ck = Some(Hertz(100_000_000)); + config.rcc.adc_clock_source = embassy_stm32::rcc::AdcClockSource::PerCk; } #[cfg(feature = "stm32u585ai")]