diff options
| author | Milton Eduardo Sosa <31409391+snorkman88@users.noreply.github.com> | 2024-06-26 19:35:43 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-26 17:35:43 +0000 |
| commit | 35891f4559cb2ec90128530ebd0ea74a65421b7a (patch) | |
| tree | c47e6c8fb159c5c03c0d292f61393a1a54a76fc0 /examples/stm32f411_adc/src/main.rs | |
| parent | 861a63dbe31f8c1062bbc9a7eca012370ac26d76 (diff) | |
Add ADC example for STM32F411 (#952)
* Add ADC example for STM32F411
* Update dependencies
* Update RTIC version
* example: f411-adc: prefer text over picture
* example: f411-adc: nit: typo
---------
Co-authored-by: Milton Eduardo Sosa <milton@Miltons-MacBook-Pro.local>
Co-authored-by: Henrik Tjäder <henrik@tjaders.com>
Diffstat (limited to 'examples/stm32f411_adc/src/main.rs')
| -rw-r--r-- | examples/stm32f411_adc/src/main.rs | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/examples/stm32f411_adc/src/main.rs b/examples/stm32f411_adc/src/main.rs new file mode 100644 index 0000000..830f5b6 --- /dev/null +++ b/examples/stm32f411_adc/src/main.rs @@ -0,0 +1,159 @@ +#![deny(unsafe_code)] +#![deny(warnings)] +#![no_main] +#![no_std] + +use panic_halt as _; + +#[rtic::app(device = stm32f4xx_hal::pac, peripherals = true)] +mod app { + + use stm32f4xx_hal::pac::ADC1; + use stm32f4xx_hal::{ + adc::{ + config::{AdcConfig, SampleTime}, + Adc, + }, + gpio::{self, Analog, Edge, Input, Output, PushPull}, + pac::TIM1, + prelude::*, + timer, + }; + + use defmt_rtt as _; + + // A simple placeholder for the analog pin + struct Potentiometer { + analog_input: gpio::PA1<Analog>, + } + + // Resources shared between tasks + #[shared] + struct Shared { + delayval: u32, + adc_module: Adc<ADC1>, + } + + // Local resources to specific tasks (cannot be shared) + #[local] + struct Local { + button: gpio::PA0<Input>, + pot_instance: Potentiometer, + led: gpio::PC13<Output<PushPull>>, + delay: timer::DelayMs<TIM1>, + } + + #[init] + fn init(ctx: init::Context) -> (Shared, Local) { + let mut dp = ctx.device; + + // Configure and obtain handle for delay abstraction + // 1) Promote RCC structure to HAL to be able to configure clocks + let rcc = dp.RCC.constrain(); + + // 2) Configure the system clocks + // 25 MHz must be used for HSE on the Blackpill-STM32F411CE board according to manual + let clocks = rcc.cfgr.use_hse(25.MHz()).freeze(); + + // 3) Create delay handle + let delay = dp.TIM1.delay_ms(&clocks); + + // Configure the LED pin as a push pull output and obtain handle + // On the Blackpill STM32F411CEU6 there is an on-board LED connected to pin PC13 + // 1) Promote the GPIOC PAC struct + let gpioc = dp.GPIOC.split(); + + // 2) Configure PORTC OUTPUT Pins and Obtain Handle + let led = gpioc.pc13.into_push_pull_output(); + + // Configure the button pin as input and obtain handle + // On the Blackpill STM32F411CEU6 there is a button connected to pin PA0 + // 3) Promote the GPIOA PAC struct + let gpioa: gpio::gpioa::Parts = dp.GPIOA.split(); + // 4) Configure Pin and Obtain Handle + let mut button = gpioa.pa0.into_pull_up_input(); + + // 5) Configure pin A1 of the blackpill to be of type analog + // the input does not need to be mutable since we are only reading it. + let analog_input = gpioa.pa1.into_analog(); + + // 6) Configure the ADC modulke for single-shot conversion + let mut adc = Adc::adc1(dp.ADC1, true, AdcConfig::default()); + // Calibrate by calculates the system VDDA by sampling the internal VREF + // channel and comparing the result with the value stored at the factory. + adc.calibrate(); + + let pot_instance = Potentiometer { + analog_input: analog_input, + }; + + // Configure Button Pin for Interrupts + // 7) Promote SYSCFG structure to HAL to be able to configure interrupts + let mut syscfg = dp.SYSCFG.constrain(); + // 8) Make button an interrupt source + button.make_interrupt_source(&mut syscfg); + // 9) Configure the interruption to be triggered on a rising edge + button.trigger_on_edge(&mut dp.EXTI, Edge::Rising); + // 10) Enable gpio interrupt for button + button.enable_interrupt(&mut dp.EXTI); + + ( + // Initialization of shared resources. In this case delay value and the ADC instance + Shared { + delayval: 2000_u32, + adc_module: adc, + }, + // Initialization of task local resources + Local { + button, + pot_instance, + led, + delay, + }, + ) + } + + // Background task, runs whenever no other tasks are running + #[idle(local = [led, delay], shared = [delayval])] + fn idle(mut ctx: idle::Context) -> ! { + let led = ctx.local.led; + let delay = ctx.local.delay; + loop { + // Turn On LED + led.set_high(); + // Obtain shared delay variable and delay + delay.delay_ms(ctx.shared.delayval.lock(|del| *del)); + // Turn off LED + led.set_low(); + // Obtain shared delay variable and delay + delay.delay_ms(ctx.shared.delayval.lock(|del| *del)); + } + } + + // Handle the IRQ generated when the button is pressed and interact with local and shared resources. + #[task(binds = EXTI0, local = [button, pot_instance], shared=[delayval, adc_module])] + fn gpio_interrupt_handler(mut ctx: gpio_interrupt_handler::Context) { + ctx.shared.delayval.lock(|del| { + *del = *del - 100_u32; + if *del < 200_u32 { + *del = 2000_u32; + } + *del + }); + + ctx.shared.delayval.lock(|del| { + defmt::info!("Current delay value {:?}", del); + }); + + // Obtain the Potentiometer instance that belongs to this task ONLY + let analog_input = &ctx.local.pot_instance.analog_input; + + // Obtain the shared instance of Adc and do one conversion of the value seen + ctx.shared.adc_module.lock(|adc_module| { + let sample = adc_module.convert(analog_input, SampleTime::Cycles_480); + defmt::info!("Current ADC value {:?}\n", sample); + }); + + ctx.local.button.clear_interrupt_pending_bit(); + } +} |
