aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32f411_adc/src
diff options
context:
space:
mode:
authorMilton Eduardo Sosa <31409391+snorkman88@users.noreply.github.com>2024-06-26 19:35:43 +0200
committerGitHub <noreply@github.com>2024-06-26 17:35:43 +0000
commit35891f4559cb2ec90128530ebd0ea74a65421b7a (patch)
treec47e6c8fb159c5c03c0d292f61393a1a54a76fc0 /examples/stm32f411_adc/src
parent861a63dbe31f8c1062bbc9a7eca012370ac26d76 (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')
-rw-r--r--examples/stm32f411_adc/src/main.rs159
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();
+ }
+}