diff options
| -rw-r--r-- | embassy-stm32/src/timer/input_capture.rs | 39 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/low_level.rs | 28 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/timer/pwm_input.rs | 114 | ||||
| -rw-r--r-- | examples/stm32f1/src/bin/input_capture.rs | 52 | ||||
| -rw-r--r-- | examples/stm32f1/src/bin/pwm_input.rs | 54 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/pwm_input.rs | 54 |
7 files changed, 314 insertions, 28 deletions
diff --git a/embassy-stm32/src/timer/input_capture.rs b/embassy-stm32/src/timer/input_capture.rs index a1c1486f9..0258d4077 100644 --- a/embassy-stm32/src/timer/input_capture.rs +++ b/embassy-stm32/src/timer/input_capture.rs | |||
| @@ -7,7 +7,7 @@ use core::task::{Context, Poll}; | |||
| 7 | 7 | ||
| 8 | use embassy_hal_internal::{into_ref, PeripheralRef}; | 8 | use embassy_hal_internal::{into_ref, PeripheralRef}; |
| 9 | 9 | ||
| 10 | use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, Timer}; | 10 | use super::low_level::{CountingMode, FilterValue, InputCaptureMode, InputTISelection, Timer}; |
| 11 | use super::{ | 11 | use super::{ |
| 12 | CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, | 12 | CaptureCompareInterruptHandler, Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, |
| 13 | GeneralInstance4Channel, | 13 | GeneralInstance4Channel, |
| @@ -40,11 +40,9 @@ macro_rules! channel_impl { | |||
| 40 | #[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")] | 40 | #[doc = concat!("Create a new ", stringify!($channel), " capture pin instance.")] |
| 41 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, pull_type: Pull) -> Self { | 41 | pub fn $new_chx(pin: impl Peripheral<P = impl $pin_trait<T>> + 'd, pull_type: Pull) -> Self { |
| 42 | into_ref!(pin); | 42 | into_ref!(pin); |
| 43 | critical_section::with(|_| { | 43 | |
| 44 | pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); | 44 | pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); |
| 45 | #[cfg(gpio_v2)] | 45 | |
| 46 | pin.set_speed(crate::gpio::Speed::VeryHigh); | ||
| 47 | }); | ||
| 48 | CapturePin { | 46 | CapturePin { |
| 49 | _pin: pin.map_into(), | 47 | _pin: pin.map_into(), |
| 50 | phantom: PhantomData, | 48 | phantom: PhantomData, |
| @@ -83,7 +81,7 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { | |||
| 83 | let mut this = Self { inner: Timer::new(tim) }; | 81 | let mut this = Self { inner: Timer::new(tim) }; |
| 84 | 82 | ||
| 85 | this.inner.set_counting_mode(counting_mode); | 83 | this.inner.set_counting_mode(counting_mode); |
| 86 | this.set_tick_freq(freq); | 84 | this.inner.set_tick_freq(freq); |
| 87 | this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details | 85 | this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details |
| 88 | this.inner.start(); | 86 | this.inner.start(); |
| 89 | 87 | ||
| @@ -109,24 +107,6 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { | |||
| 109 | self.inner.get_channel_enable_state(channel) | 107 | self.inner.get_channel_enable_state(channel) |
| 110 | } | 108 | } |
| 111 | 109 | ||
| 112 | /// Set tick frequency. | ||
| 113 | /// | ||
| 114 | /// Note: when you call this, the max period value changes | ||
| 115 | pub fn set_tick_freq(&mut self, freq: Hertz) { | ||
| 116 | let f = freq; | ||
| 117 | assert!(f.0 > 0); | ||
| 118 | let timer_f = self.inner.get_clock_frequency(); | ||
| 119 | |||
| 120 | let pclk_ticks_per_timer_period = timer_f / f; | ||
| 121 | let psc: u16 = unwrap!((pclk_ticks_per_timer_period - 1).try_into()); | ||
| 122 | |||
| 123 | let regs = self.inner.regs_core(); | ||
| 124 | regs.psc().write_value(psc); | ||
| 125 | |||
| 126 | // Generate an Update Request | ||
| 127 | regs.egr().write(|r| r.set_ug(true)); | ||
| 128 | } | ||
| 129 | |||
| 130 | /// Set the input capture mode for a given channel. | 110 | /// Set the input capture mode for a given channel. |
| 131 | pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { | 111 | pub fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { |
| 132 | self.inner.set_input_capture_mode(channel, mode); | 112 | self.inner.set_input_capture_mode(channel, mode); |
| @@ -148,10 +128,13 @@ impl<'d, T: GeneralInstance4Channel> InputCapture<'d, T> { | |||
| 148 | } | 128 | } |
| 149 | 129 | ||
| 150 | fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> { | 130 | fn new_future(&self, channel: Channel, mode: InputCaptureMode, tisel: InputTISelection) -> InputCaptureFuture<T> { |
| 151 | self.inner.enable_channel(channel, true); | 131 | // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.5 |
| 152 | self.inner.set_input_capture_mode(channel, mode); | 132 | // or ST RM0008 (STM32F103) chapter 15.3.5 Input capture mode |
| 153 | self.inner.set_input_ti_selection(channel, tisel); | 133 | self.inner.set_input_ti_selection(channel, tisel); |
| 154 | self.inner.clear_input_interrupt(channel); | 134 | self.inner.set_input_capture_filter(channel, FilterValue::NOFILTER); |
| 135 | self.inner.set_input_capture_mode(channel, mode); | ||
| 136 | self.inner.set_input_capture_prescaler(channel, 0); | ||
| 137 | self.inner.enable_channel(channel, true); | ||
| 155 | self.inner.enable_input_interrupt(channel, true); | 138 | self.inner.enable_input_interrupt(channel, true); |
| 156 | 139 | ||
| 157 | InputCaptureFuture { | 140 | InputCaptureFuture { |
diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs index 9932c04cd..e643722aa 100644 --- a/embassy-stm32/src/timer/low_level.rs +++ b/embassy-stm32/src/timer/low_level.rs | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | //! The available functionality depends on the timer type. | 7 | //! The available functionality depends on the timer type. |
| 8 | 8 | ||
| 9 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; | 9 | use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; |
| 10 | // Re-export useful enums | ||
| 11 | pub use stm32_metapac::timer::vals::{FilterValue, Sms as SlaveMode, Ts as TriggerSource}; | ||
| 10 | 12 | ||
| 11 | use super::*; | 13 | use super::*; |
| 12 | use crate::pac::timer::vals; | 14 | use crate::pac::timer::vals; |
| @@ -274,6 +276,22 @@ impl<'d, T: CoreInstance> Timer<'d, T> { | |||
| 274 | } | 276 | } |
| 275 | } | 277 | } |
| 276 | 278 | ||
| 279 | /// Set tick frequency. | ||
| 280 | pub fn set_tick_freq(&mut self, freq: Hertz) { | ||
| 281 | let f = freq; | ||
| 282 | assert!(f.0 > 0); | ||
| 283 | let timer_f = self.get_clock_frequency(); | ||
| 284 | |||
| 285 | let pclk_ticks_per_timer_period = timer_f / f; | ||
| 286 | let psc: u16 = unwrap!((pclk_ticks_per_timer_period - 1).try_into()); | ||
| 287 | |||
| 288 | let regs = self.regs_core(); | ||
| 289 | regs.psc().write_value(psc); | ||
| 290 | |||
| 291 | // Generate an Update Request | ||
| 292 | regs.egr().write(|r| r.set_ug(true)); | ||
| 293 | } | ||
| 294 | |||
| 277 | /// Clear update interrupt. | 295 | /// Clear update interrupt. |
| 278 | /// | 296 | /// |
| 279 | /// Returns whether the update interrupt flag was set. | 297 | /// Returns whether the update interrupt flag was set. |
| @@ -573,6 +591,16 @@ impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { | |||
| 573 | pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { | 591 | pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { |
| 574 | self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) | 592 | self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) |
| 575 | } | 593 | } |
| 594 | |||
| 595 | /// Set Timer Slave Mode | ||
| 596 | pub fn set_slave_mode(&self, sms: SlaveMode) { | ||
| 597 | self.regs_gp16().smcr().modify(|r| r.set_sms(sms)); | ||
| 598 | } | ||
| 599 | |||
| 600 | /// Set Timer Trigger Source | ||
| 601 | pub fn set_trigger_source(&self, ts: TriggerSource) { | ||
| 602 | self.regs_gp16().smcr().modify(|r| r.set_ts(ts)); | ||
| 603 | } | ||
| 576 | } | 604 | } |
| 577 | 605 | ||
| 578 | #[cfg(not(stm32l0))] | 606 | #[cfg(not(stm32l0))] |
diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 314b6006b..25782ee13 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs | |||
| @@ -8,6 +8,7 @@ use embassy_sync::waitqueue::AtomicWaker; | |||
| 8 | pub mod complementary_pwm; | 8 | pub mod complementary_pwm; |
| 9 | pub mod input_capture; | 9 | pub mod input_capture; |
| 10 | pub mod low_level; | 10 | pub mod low_level; |
| 11 | pub mod pwm_input; | ||
| 11 | pub mod qei; | 12 | pub mod qei; |
| 12 | pub mod simple_pwm; | 13 | pub mod simple_pwm; |
| 13 | 14 | ||
diff --git a/embassy-stm32/src/timer/pwm_input.rs b/embassy-stm32/src/timer/pwm_input.rs new file mode 100644 index 000000000..dcf098a78 --- /dev/null +++ b/embassy-stm32/src/timer/pwm_input.rs | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | //! PWM Input driver. | ||
| 2 | |||
| 3 | use embassy_hal_internal::into_ref; | ||
| 4 | |||
| 5 | use super::low_level::{CountingMode, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource}; | ||
| 6 | use super::{Channel, Channel1Pin, Channel2Pin, GeneralInstance4Channel}; | ||
| 7 | use crate::gpio::{AFType, Pull}; | ||
| 8 | use crate::time::Hertz; | ||
| 9 | use crate::Peripheral; | ||
| 10 | |||
| 11 | /// PWM Input driver. | ||
| 12 | pub struct PwmInput<'d, T: GeneralInstance4Channel> { | ||
| 13 | channel: Channel, | ||
| 14 | inner: Timer<'d, T>, | ||
| 15 | } | ||
| 16 | |||
| 17 | impl<'d, T: GeneralInstance4Channel> PwmInput<'d, T> { | ||
| 18 | /// Create a new PWM input driver. | ||
| 19 | pub fn new( | ||
| 20 | tim: impl Peripheral<P = T> + 'd, | ||
| 21 | pin: impl Peripheral<P = impl Channel1Pin<T>> + 'd, | ||
| 22 | pull_type: Pull, | ||
| 23 | freq: Hertz, | ||
| 24 | ) -> Self { | ||
| 25 | into_ref!(pin); | ||
| 26 | |||
| 27 | pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); | ||
| 28 | |||
| 29 | Self::new_inner(tim, freq, Channel::Ch1, Channel::Ch2) | ||
| 30 | } | ||
| 31 | |||
| 32 | /// Create a new PWM input driver. | ||
| 33 | pub fn new_alt( | ||
| 34 | tim: impl Peripheral<P = T> + 'd, | ||
| 35 | pin: impl Peripheral<P = impl Channel2Pin<T>> + 'd, | ||
| 36 | pull_type: Pull, | ||
| 37 | freq: Hertz, | ||
| 38 | ) -> Self { | ||
| 39 | into_ref!(pin); | ||
| 40 | |||
| 41 | pin.set_as_af_pull(pin.af_num(), AFType::Input, pull_type); | ||
| 42 | |||
| 43 | Self::new_inner(tim, freq, Channel::Ch2, Channel::Ch1) | ||
| 44 | } | ||
| 45 | |||
| 46 | fn new_inner(tim: impl Peripheral<P = T> + 'd, freq: Hertz, ch1: Channel, ch2: Channel) -> Self { | ||
| 47 | let mut inner = Timer::new(tim); | ||
| 48 | |||
| 49 | inner.set_counting_mode(CountingMode::EdgeAlignedUp); | ||
| 50 | inner.set_tick_freq(freq); | ||
| 51 | inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details | ||
| 52 | inner.start(); | ||
| 53 | |||
| 54 | // Configuration steps from ST RM0390 (STM32F446) chapter 17.3.6 | ||
| 55 | // or ST RM0008 (STM32F103) chapter 15.3.6 Input capture mode | ||
| 56 | inner.set_input_ti_selection(ch1, InputTISelection::Normal); | ||
| 57 | inner.set_input_capture_mode(ch1, InputCaptureMode::Rising); | ||
| 58 | |||
| 59 | inner.set_input_ti_selection(ch2, InputTISelection::Alternate); | ||
| 60 | inner.set_input_capture_mode(ch2, InputCaptureMode::Falling); | ||
| 61 | |||
| 62 | inner.set_trigger_source(match ch1 { | ||
| 63 | Channel::Ch1 => TriggerSource::TI1FP1, | ||
| 64 | Channel::Ch2 => TriggerSource::TI2FP2, | ||
| 65 | _ => panic!("Invalid channel for PWM input"), | ||
| 66 | }); | ||
| 67 | |||
| 68 | inner.set_slave_mode(SlaveMode::RESET_MODE); | ||
| 69 | |||
| 70 | // Must call the `enable` function after | ||
| 71 | |||
| 72 | Self { channel: ch1, inner } | ||
| 73 | } | ||
| 74 | |||
| 75 | /// Enable the given channel. | ||
| 76 | pub fn enable(&mut self) { | ||
| 77 | self.inner.enable_channel(Channel::Ch1, true); | ||
| 78 | self.inner.enable_channel(Channel::Ch2, true); | ||
| 79 | } | ||
| 80 | |||
| 81 | /// Disable the given channel. | ||
| 82 | pub fn disable(&mut self) { | ||
| 83 | self.inner.enable_channel(Channel::Ch1, false); | ||
| 84 | self.inner.enable_channel(Channel::Ch2, false); | ||
| 85 | } | ||
| 86 | |||
| 87 | /// Check whether given channel is enabled | ||
| 88 | pub fn is_enabled(&self) -> bool { | ||
| 89 | self.inner.get_channel_enable_state(Channel::Ch1) | ||
| 90 | } | ||
| 91 | |||
| 92 | /// Get the period tick count | ||
| 93 | pub fn get_period_ticks(&self) -> u32 { | ||
| 94 | self.inner.get_capture_value(self.channel) | ||
| 95 | } | ||
| 96 | |||
| 97 | /// Get the pulse width tick count | ||
| 98 | pub fn get_width_ticks(&self) -> u32 { | ||
| 99 | self.inner.get_capture_value(match self.channel { | ||
| 100 | Channel::Ch1 => Channel::Ch2, | ||
| 101 | Channel::Ch2 => Channel::Ch1, | ||
| 102 | _ => panic!("Invalid channel for PWM input"), | ||
| 103 | }) | ||
| 104 | } | ||
| 105 | |||
| 106 | /// Get the duty cycle in 100% | ||
| 107 | pub fn get_duty_cycle(&self) -> f32 { | ||
| 108 | let period = self.get_period_ticks(); | ||
| 109 | if period == 0 { | ||
| 110 | return 0.; | ||
| 111 | } | ||
| 112 | 100. * (self.get_width_ticks() as f32) / (period as f32) | ||
| 113 | } | ||
| 114 | } | ||
diff --git a/examples/stm32f1/src/bin/input_capture.rs b/examples/stm32f1/src/bin/input_capture.rs new file mode 100644 index 000000000..5e2dab9e6 --- /dev/null +++ b/examples/stm32f1/src/bin/input_capture.rs | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | ||
| 7 | use embassy_stm32::time::khz; | ||
| 8 | use embassy_stm32::timer::input_capture::{CapturePin, InputCapture}; | ||
| 9 | use embassy_stm32::timer::{self, Channel}; | ||
| 10 | use embassy_stm32::{bind_interrupts, peripherals}; | ||
| 11 | use embassy_time::Timer; | ||
| 12 | use {defmt_rtt as _, panic_probe as _}; | ||
| 13 | |||
| 14 | /// Connect PA2 and PC13 with a 1k Ohm resistor | ||
| 15 | |||
| 16 | #[embassy_executor::task] | ||
| 17 | async fn blinky(led: peripherals::PC13) { | ||
| 18 | let mut led = Output::new(led, Level::High, Speed::Low); | ||
| 19 | |||
| 20 | loop { | ||
| 21 | info!("high"); | ||
| 22 | led.set_high(); | ||
| 23 | Timer::after_millis(300).await; | ||
| 24 | |||
| 25 | info!("low"); | ||
| 26 | led.set_low(); | ||
| 27 | Timer::after_millis(300).await; | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | bind_interrupts!(struct Irqs { | ||
| 32 | TIM2 => timer::CaptureCompareInterruptHandler<peripherals::TIM2>; | ||
| 33 | }); | ||
| 34 | |||
| 35 | #[embassy_executor::main] | ||
| 36 | async fn main(spawner: Spawner) { | ||
| 37 | let p = embassy_stm32::init(Default::default()); | ||
| 38 | info!("Hello World!"); | ||
| 39 | |||
| 40 | unwrap!(spawner.spawn(blinky(p.PC13))); | ||
| 41 | |||
| 42 | let ch3 = CapturePin::new_ch3(p.PA2, Pull::None); | ||
| 43 | let mut ic = InputCapture::new(p.TIM2, None, None, Some(ch3), None, Irqs, khz(1000), Default::default()); | ||
| 44 | |||
| 45 | loop { | ||
| 46 | info!("wait for rising edge"); | ||
| 47 | ic.wait_for_rising_edge(Channel::Ch3).await; | ||
| 48 | |||
| 49 | let capture_value = ic.get_capture_value(Channel::Ch3); | ||
| 50 | info!("new capture! {}", capture_value); | ||
| 51 | } | ||
| 52 | } | ||
diff --git a/examples/stm32f1/src/bin/pwm_input.rs b/examples/stm32f1/src/bin/pwm_input.rs new file mode 100644 index 000000000..f74853d4e --- /dev/null +++ b/examples/stm32f1/src/bin/pwm_input.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | ||
| 7 | use embassy_stm32::time::khz; | ||
| 8 | use embassy_stm32::timer::pwm_input::PwmInput; | ||
| 9 | use embassy_stm32::{bind_interrupts, peripherals, timer}; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | /// Connect PA0 and PC13 with a 1k Ohm resistor | ||
| 14 | |||
| 15 | #[embassy_executor::task] | ||
| 16 | async fn blinky(led: peripherals::PC13) { | ||
| 17 | let mut led = Output::new(led, Level::High, Speed::Low); | ||
| 18 | |||
| 19 | loop { | ||
| 20 | info!("high"); | ||
| 21 | led.set_high(); | ||
| 22 | Timer::after_millis(300).await; | ||
| 23 | |||
| 24 | info!("low"); | ||
| 25 | led.set_low(); | ||
| 26 | Timer::after_millis(300).await; | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | TIM2 => timer::CaptureCompareInterruptHandler<peripherals::TIM2>; | ||
| 32 | }); | ||
| 33 | |||
| 34 | #[embassy_executor::main] | ||
| 35 | async fn main(spawner: Spawner) { | ||
| 36 | let p = embassy_stm32::init(Default::default()); | ||
| 37 | info!("Hello World!"); | ||
| 38 | |||
| 39 | unwrap!(spawner.spawn(blinky(p.PC13))); | ||
| 40 | |||
| 41 | let mut pwm_input = PwmInput::new(p.TIM2, p.PA0, Pull::None, khz(10)); | ||
| 42 | pwm_input.enable(); | ||
| 43 | |||
| 44 | loop { | ||
| 45 | Timer::after_millis(500).await; | ||
| 46 | let period = pwm_input.get_period_ticks(); | ||
| 47 | let width = pwm_input.get_width_ticks(); | ||
| 48 | let duty_cycle = pwm_input.get_duty_cycle(); | ||
| 49 | info!( | ||
| 50 | "period ticks: {} width ticks: {} duty cycle: {}", | ||
| 51 | period, width, duty_cycle | ||
| 52 | ); | ||
| 53 | } | ||
| 54 | } | ||
diff --git a/examples/stm32f4/src/bin/pwm_input.rs b/examples/stm32f4/src/bin/pwm_input.rs new file mode 100644 index 000000000..ce200549d --- /dev/null +++ b/examples/stm32f4/src/bin/pwm_input.rs | |||
| @@ -0,0 +1,54 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::gpio::{Level, Output, Pull, Speed}; | ||
| 7 | use embassy_stm32::time::khz; | ||
| 8 | use embassy_stm32::timer::pwm_input::PwmInput; | ||
| 9 | use embassy_stm32::{bind_interrupts, peripherals, timer}; | ||
| 10 | use embassy_time::Timer; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | /// Connect PB2 and PA6 with a 1k Ohm resistor | ||
| 14 | |||
| 15 | #[embassy_executor::task] | ||
| 16 | async fn blinky(led: peripherals::PB2) { | ||
| 17 | let mut led = Output::new(led, Level::High, Speed::Low); | ||
| 18 | |||
| 19 | loop { | ||
| 20 | info!("high"); | ||
| 21 | led.set_high(); | ||
| 22 | Timer::after_millis(300).await; | ||
| 23 | |||
| 24 | info!("low"); | ||
| 25 | led.set_low(); | ||
| 26 | Timer::after_millis(300).await; | ||
| 27 | } | ||
| 28 | } | ||
| 29 | |||
| 30 | bind_interrupts!(struct Irqs { | ||
| 31 | TIM2 => timer::CaptureCompareInterruptHandler<peripherals::TIM2>; | ||
| 32 | }); | ||
| 33 | |||
| 34 | #[embassy_executor::main] | ||
| 35 | async fn main(spawner: Spawner) { | ||
| 36 | let p = embassy_stm32::init(Default::default()); | ||
| 37 | info!("Hello World!"); | ||
| 38 | |||
| 39 | unwrap!(spawner.spawn(blinky(p.PB2))); | ||
| 40 | |||
| 41 | let mut pwm_input = PwmInput::new(p.TIM3, p.PA6, Pull::None, khz(10)); | ||
| 42 | pwm_input.enable(); | ||
| 43 | |||
| 44 | loop { | ||
| 45 | Timer::after_millis(500).await; | ||
| 46 | let period = pwm_input.get_period_ticks(); | ||
| 47 | let width = pwm_input.get_width_ticks(); | ||
| 48 | let duty_cycle = pwm_input.get_duty_cycle(); | ||
| 49 | info!( | ||
| 50 | "period ticks: {} width ticks: {} duty cycle: {}", | ||
| 51 | period, width, duty_cycle | ||
| 52 | ); | ||
| 53 | } | ||
| 54 | } | ||
