aboutsummaryrefslogtreecommitdiff
path: root/examples/stm32h7/src/bin/low_level_timer_api.rs
diff options
context:
space:
mode:
authorMatous Hybl <[email protected]>2021-12-08 17:39:59 +0100
committerMatous Hybl <[email protected]>2022-01-13 16:53:55 +0100
commite056bedd553e7fbc7d28f8f516c87fcd12859aef (patch)
tree3a86254c58afa1ab790475b32b53debce7dcaec4 /examples/stm32h7/src/bin/low_level_timer_api.rs
parente07df92651f58eb001ea8c22cae0130435877b17 (diff)
Port the PWM example to H7, add low-level API example implementing 32-bit PWM.
Diffstat (limited to 'examples/stm32h7/src/bin/low_level_timer_api.rs')
-rw-r--r--examples/stm32h7/src/bin/low_level_timer_api.rs147
1 files changed, 147 insertions, 0 deletions
diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs
new file mode 100644
index 000000000..2640f249d
--- /dev/null
+++ b/examples/stm32h7/src/bin/low_level_timer_api.rs
@@ -0,0 +1,147 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7use core::marker::PhantomData;
8
9use embassy::executor::Spawner;
10use embassy::time::{Duration, Timer};
11use embassy::util::Unborrow;
12use embassy_hal_common::unborrow;
13use embassy_stm32::gpio::NoPin;
14use embassy_stm32::pwm::{pins::*, Channel, OutputCompareMode};
15use embassy_stm32::time::{Hertz, U32Ext};
16use embassy_stm32::timer::GeneralPurpose32bitInstance;
17use embassy_stm32::{Config, Peripherals};
18use example_common::*;
19
20pub fn config() -> Config {
21 let mut config = Config::default();
22 config.rcc.sys_ck = Some(400.mhz().into());
23 config.rcc.hclk = Some(400.mhz().into());
24 config.rcc.pll1.q_ck = Some(100.mhz().into());
25 config.rcc.pclk1 = Some(100.mhz().into());
26 config.rcc.pclk2 = Some(100.mhz().into());
27 config.rcc.pclk3 = Some(100.mhz().into());
28 config.rcc.pclk4 = Some(100.mhz().into());
29 config
30}
31
32#[embassy::main(config = "config()")]
33async fn main(_spawner: Spawner, p: Peripherals) {
34 info!("Hello World!");
35
36 let mut pwm = SimplePwm32::new(p.TIM5, p.PA0, NoPin, NoPin, NoPin, 10000.hz());
37 let max = pwm.get_max_duty();
38 pwm.enable(Channel::Ch1);
39
40 info!("PWM initialized");
41 info!("PWM max duty {}", max);
42
43 loop {
44 pwm.set_duty(Channel::Ch1, 0);
45 Timer::after(Duration::from_millis(300)).await;
46 pwm.set_duty(Channel::Ch1, max / 4);
47 Timer::after(Duration::from_millis(300)).await;
48 pwm.set_duty(Channel::Ch1, max / 2);
49 Timer::after(Duration::from_millis(300)).await;
50 pwm.set_duty(Channel::Ch1, max - 1);
51 Timer::after(Duration::from_millis(300)).await;
52 }
53}
54pub struct SimplePwm32<'d, T: GeneralPurpose32bitInstance> {
55 phantom: PhantomData<&'d mut T>,
56 inner: T,
57}
58
59impl<'d, T: GeneralPurpose32bitInstance> SimplePwm32<'d, T> {
60 pub fn new<F: Into<Hertz>>(
61 tim: impl Unborrow<Target = T> + 'd,
62 ch1: impl Unborrow<Target = impl Channel1Pin<T>> + 'd,
63 ch2: impl Unborrow<Target = impl Channel2Pin<T>> + 'd,
64 ch3: impl Unborrow<Target = impl Channel3Pin<T>> + 'd,
65 ch4: impl Unborrow<Target = impl Channel4Pin<T>> + 'd,
66 freq: F,
67 ) -> Self {
68 unborrow!(tim, ch1, ch2, ch3, ch4);
69
70 T::enable();
71 <T as embassy_stm32::rcc::low_level::RccPeripheral>::reset();
72
73 unsafe {
74 ch1.configure();
75 ch2.configure();
76 ch3.configure();
77 ch4.configure();
78 }
79
80 let mut this = Self {
81 inner: tim,
82 phantom: PhantomData,
83 };
84
85 this.set_freq(freq);
86 this.inner.start();
87
88 unsafe {
89 this.inner
90 .regs_gp32()
91 .ccmr_output(0)
92 .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into()));
93 this.inner
94 .regs_gp32()
95 .ccmr_output(0)
96 .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into()));
97 this.inner
98 .regs_gp32()
99 .ccmr_output(1)
100 .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into()));
101 this.inner
102 .regs_gp32()
103 .ccmr_output(1)
104 .modify(|w| w.set_ocm(1, OutputCompareMode::PwmMode1.into()));
105 }
106 this
107 }
108
109 pub fn enable(&mut self, channel: Channel) {
110 unsafe {
111 self.inner
112 .regs_gp32()
113 .ccer()
114 .modify(|w| w.set_cce(channel.raw(), true));
115 }
116 }
117
118 pub fn disable(&mut self, channel: Channel) {
119 unsafe {
120 self.inner
121 .regs_gp32()
122 .ccer()
123 .modify(|w| w.set_cce(channel.raw(), false));
124 }
125 }
126
127 pub fn set_freq<F: Into<Hertz>>(&mut self, freq: F) {
128 <T as embassy_stm32::timer::low_level::GeneralPurpose32bitInstance>::set_frequency(
129 &mut self.inner,
130 freq,
131 );
132 }
133
134 pub fn get_max_duty(&self) -> u32 {
135 unsafe { self.inner.regs_gp32().arr().read().arr() }
136 }
137
138 pub fn set_duty(&mut self, channel: Channel, duty: u32) {
139 defmt::assert!(duty < self.get_max_duty());
140 unsafe {
141 self.inner
142 .regs_gp32()
143 .ccr(channel.raw())
144 .modify(|w| w.set_ccr(duty))
145 }
146 }
147}