diff options
| -rw-r--r-- | embassy-stm32/src/pwm/advanced_pwm.rs | 87 | ||||
| -rw-r--r-- | embassy-stm32/src/pwm/mod.rs | 37 | ||||
| -rw-r--r-- | examples/stm32f334/src/bin/button.rs | 27 | ||||
| -rw-r--r-- | examples/stm32f334/src/bin/pwm.rs | 65 |
4 files changed, 160 insertions, 56 deletions
diff --git a/embassy-stm32/src/pwm/advanced_pwm.rs b/embassy-stm32/src/pwm/advanced_pwm.rs index 65f4e7ca7..fa34b2e18 100644 --- a/embassy-stm32/src/pwm/advanced_pwm.rs +++ b/embassy-stm32/src/pwm/advanced_pwm.rs | |||
| @@ -144,6 +144,18 @@ impl<'d, T: HighResolutionCaptureCompare16bitInstance> AdvancedPwm<'d, T> { | |||
| 144 | T::enable(); | 144 | T::enable(); |
| 145 | <T as crate::rcc::sealed::RccPeripheral>::reset(); | 145 | <T as crate::rcc::sealed::RccPeripheral>::reset(); |
| 146 | 146 | ||
| 147 | // // Enable and and stabilize the DLL | ||
| 148 | // T::regs().dllcr().modify(|w| { | ||
| 149 | // // w.set_calen(true); | ||
| 150 | // // w.set_calrte(11); | ||
| 151 | // w.set_cal(true); | ||
| 152 | // }); | ||
| 153 | // | ||
| 154 | // debug!("wait for dll calibration"); | ||
| 155 | // while !T::regs().isr().read().dllrdy() {} | ||
| 156 | // | ||
| 157 | // debug!("dll calibration complete"); | ||
| 158 | |||
| 147 | Self { | 159 | Self { |
| 148 | _inner: tim, | 160 | _inner: tim, |
| 149 | master: Master { phantom: PhantomData }, | 161 | master: Master { phantom: PhantomData }, |
| @@ -173,12 +185,14 @@ impl<T: HighResolutionCaptureCompare16bitInstance> BurstController<T> { | |||
| 173 | /// light loading conditions, and that the low-side switch must be active for a short time to drive | 185 | /// light loading conditions, and that the low-side switch must be active for a short time to drive |
| 174 | /// a bootstrapped high-side switch. | 186 | /// a bootstrapped high-side switch. |
| 175 | pub struct BridgeConverter<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> { | 187 | pub struct BridgeConverter<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> { |
| 176 | phantom: PhantomData<T>, | 188 | timer: PhantomData<T>, |
| 177 | pub ch: C, | 189 | channel: PhantomData<C>, |
| 190 | dead_time: u16, | ||
| 191 | primary_duty: u16, | ||
| 178 | } | 192 | } |
| 179 | 193 | ||
| 180 | impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> BridgeConverter<T, C> { | 194 | impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> BridgeConverter<T, C> { |
| 181 | pub fn new(channel: C, frequency: Hertz) -> Self { | 195 | pub fn new(_channel: C, frequency: Hertz) -> Self { |
| 182 | use crate::pac::hrtim::vals::{Activeeffect, Cont, Inactiveeffect}; | 196 | use crate::pac::hrtim::vals::{Activeeffect, Cont, Inactiveeffect}; |
| 183 | 197 | ||
| 184 | T::set_channel_frequency(C::raw(), frequency); | 198 | T::set_channel_frequency(C::raw(), frequency); |
| @@ -186,15 +200,21 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 186 | // Always enable preload | 200 | // Always enable preload |
| 187 | T::regs().tim(C::raw()).cr().modify(|w| { | 201 | T::regs().tim(C::raw()).cr().modify(|w| { |
| 188 | w.set_preen(true); | 202 | w.set_preen(true); |
| 203 | w.set_repu(true); | ||
| 189 | 204 | ||
| 190 | w.set_cont(Cont::CONTINUOUS); | 205 | w.set_cont(Cont::CONTINUOUS); |
| 191 | }); | 206 | }); |
| 192 | 207 | ||
| 208 | // Enable timer outputs | ||
| 193 | T::regs().oenr().modify(|w| { | 209 | T::regs().oenr().modify(|w| { |
| 194 | w.set_t1oen(C::raw(), true); | 210 | w.set_t1oen(C::raw(), true); |
| 195 | w.set_t2oen(C::raw(), true); | 211 | w.set_t2oen(C::raw(), true); |
| 196 | }); | 212 | }); |
| 197 | 213 | ||
| 214 | // The dead-time generation unit cannot be used because it forces the other output | ||
| 215 | // to be completely complementary to the first output, which restricts certain waveforms | ||
| 216 | // Therefore, software-implemented dead time must be used when setting the duty cycles | ||
| 217 | |||
| 198 | // Set output 1 to active on a period event | 218 | // Set output 1 to active on a period event |
| 199 | T::regs() | 219 | T::regs() |
| 200 | .tim(C::raw()) | 220 | .tim(C::raw()) |
| @@ -207,21 +227,23 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 207 | .rstr(0) | 227 | .rstr(0) |
| 208 | .modify(|w| w.set_cmp(0, Inactiveeffect::SETINACTIVE)); | 228 | .modify(|w| w.set_cmp(0, Inactiveeffect::SETINACTIVE)); |
| 209 | 229 | ||
| 210 | // Set output 2 to active on a compare 1 event | 230 | // Set output 2 to active on a compare 2 event |
| 211 | T::regs() | 231 | T::regs() |
| 212 | .tim(C::raw()) | 232 | .tim(C::raw()) |
| 213 | .setr(1) | 233 | .setr(1) |
| 214 | .modify(|w| w.set_cmp(0, Activeeffect::SETACTIVE)); | 234 | .modify(|w| w.set_cmp(1, Activeeffect::SETACTIVE)); |
| 215 | 235 | ||
| 216 | // Set output 2 to inactive on a compare 2 event | 236 | // Set output 2 to inactive on a compare 3 event |
| 217 | T::regs() | 237 | T::regs() |
| 218 | .tim(C::raw()) | 238 | .tim(C::raw()) |
| 219 | .rstr(1) | 239 | .rstr(1) |
| 220 | .modify(|w| w.set_cmp(1, Inactiveeffect::SETINACTIVE)); | 240 | .modify(|w| w.set_cmp(2, Inactiveeffect::SETINACTIVE)); |
| 221 | 241 | ||
| 222 | Self { | 242 | Self { |
| 223 | phantom: PhantomData, | 243 | timer: PhantomData, |
| 224 | ch: channel, | 244 | channel: PhantomData, |
| 245 | dead_time: 0, | ||
| 246 | primary_duty: 0, | ||
| 225 | } | 247 | } |
| 226 | } | 248 | } |
| 227 | 249 | ||
| @@ -236,7 +258,6 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 236 | pub fn enable_burst_mode(&mut self) { | 258 | pub fn enable_burst_mode(&mut self) { |
| 237 | use crate::pac::hrtim::vals::{Idlem, Idles}; | 259 | use crate::pac::hrtim::vals::{Idlem, Idles}; |
| 238 | 260 | ||
| 239 | // TODO: fix metapac | ||
| 240 | T::regs().tim(C::raw()).outr().modify(|w| { | 261 | T::regs().tim(C::raw()).outr().modify(|w| { |
| 241 | w.set_idlem(0, Idlem::SETIDLE); | 262 | w.set_idlem(0, Idlem::SETIDLE); |
| 242 | w.set_idlem(1, Idlem::SETIDLE); | 263 | w.set_idlem(1, Idlem::SETIDLE); |
| @@ -258,9 +279,18 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 258 | }) | 279 | }) |
| 259 | } | 280 | } |
| 260 | 281 | ||
| 282 | fn update_primary_duty_or_dead_time(&mut self) { | ||
| 283 | T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(self.primary_duty)); | ||
| 284 | T::regs() | ||
| 285 | .tim(C::raw()) | ||
| 286 | .cmp(1) | ||
| 287 | .modify(|w| w.set_cmp(self.primary_duty + self.dead_time)); | ||
| 288 | } | ||
| 289 | |||
| 261 | /// Set the dead time as a proportion of the maximum compare value | 290 | /// Set the dead time as a proportion of the maximum compare value |
| 262 | pub fn set_dead_time(&mut self, value: u16) { | 291 | pub fn set_dead_time(&mut self, dead_time: u16) { |
| 263 | T::set_channel_dead_time(C::raw(), value); | 292 | self.dead_time = dead_time; |
| 293 | self.update_primary_duty_or_dead_time(); | ||
| 264 | } | 294 | } |
| 265 | 295 | ||
| 266 | /// Get the maximum compare value of a duty cycle | 296 | /// Get the maximum compare value of a duty cycle |
| @@ -272,15 +302,17 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 272 | /// | 302 | /// |
| 273 | /// In the case of a buck converter, this is the high-side switch | 303 | /// In the case of a buck converter, this is the high-side switch |
| 274 | /// In the case of a boost converter, this is the low-side switch | 304 | /// In the case of a boost converter, this is the low-side switch |
| 275 | pub fn set_primary_duty(&mut self, primary: u16) { | 305 | pub fn set_primary_duty(&mut self, primary_duty: u16) { |
| 276 | T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(primary)); | 306 | self.primary_duty = primary_duty; |
| 307 | self.update_primary_duty_or_dead_time(); | ||
| 277 | } | 308 | } |
| 278 | 309 | ||
| 279 | /// The primary duty is the period in any switch is active | 310 | /// The secondary duty is the period in any switch is active |
| 280 | /// | 311 | /// |
| 281 | /// If less than or equal to the primary duty, the secondary switch will never be active | 312 | /// If less than or equal to the primary duty, the secondary switch will never be active |
| 282 | pub fn set_secondary_duty(&mut self, secondary: u16) { | 313 | /// If a fully complementary output is desired, the secondary duty can be set to the max compare |
| 283 | T::regs().tim(C::raw()).cmp(1).modify(|w| w.set_cmp(secondary)); | 314 | pub fn set_secondary_duty(&mut self, secondary_duty: u16) { |
| 315 | T::regs().tim(C::raw()).cmp(2).modify(|w| w.set_cmp(secondary_duty)); | ||
| 284 | } | 316 | } |
| 285 | } | 317 | } |
| 286 | 318 | ||
| @@ -290,14 +322,14 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Bridge | |||
| 290 | /// but does not include secondary rectification, which is appropriate for applications | 322 | /// but does not include secondary rectification, which is appropriate for applications |
| 291 | /// with a low-voltage on the secondary side. | 323 | /// with a low-voltage on the secondary side. |
| 292 | pub struct ResonantConverter<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> { | 324 | pub struct ResonantConverter<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> { |
| 293 | phantom: PhantomData<T>, | 325 | timer: PhantomData<T>, |
| 326 | channel: PhantomData<C>, | ||
| 294 | min_period: u16, | 327 | min_period: u16, |
| 295 | max_period: u16, | 328 | max_period: u16, |
| 296 | pub ch: C, | ||
| 297 | } | 329 | } |
| 298 | 330 | ||
| 299 | impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> ResonantConverter<T, C> { | 331 | impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> ResonantConverter<T, C> { |
| 300 | pub fn new(channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self { | 332 | pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self { |
| 301 | use crate::pac::hrtim::vals::Cont; | 333 | use crate::pac::hrtim::vals::Cont; |
| 302 | 334 | ||
| 303 | T::set_channel_frequency(C::raw(), min_frequency); | 335 | T::set_channel_frequency(C::raw(), min_frequency); |
| @@ -305,19 +337,30 @@ impl<T: HighResolutionCaptureCompare16bitInstance, C: AdvancedChannel<T>> Resona | |||
| 305 | // Always enable preload | 337 | // Always enable preload |
| 306 | T::regs().tim(C::raw()).cr().modify(|w| { | 338 | T::regs().tim(C::raw()).cr().modify(|w| { |
| 307 | w.set_preen(true); | 339 | w.set_preen(true); |
| 340 | w.set_repu(true); | ||
| 308 | 341 | ||
| 309 | w.set_cont(Cont::CONTINUOUS); | 342 | w.set_cont(Cont::CONTINUOUS); |
| 310 | w.set_half(true); | 343 | w.set_half(true); |
| 311 | }); | 344 | }); |
| 312 | 345 | ||
| 346 | // Enable timer outputs | ||
| 347 | T::regs().oenr().modify(|w| { | ||
| 348 | w.set_t1oen(C::raw(), true); | ||
| 349 | w.set_t2oen(C::raw(), true); | ||
| 350 | }); | ||
| 351 | |||
| 352 | // Dead-time generator can be used in this case because the primary fets | ||
| 353 | // of a resonant converter are always complementary | ||
| 354 | T::regs().tim(C::raw()).outr().modify(|w| w.set_dten(true)); | ||
| 355 | |||
| 313 | let max_period = T::regs().tim(C::raw()).per().read().per(); | 356 | let max_period = T::regs().tim(C::raw()).per().read().per(); |
| 314 | let min_period = max_period * (min_frequency.0 / max_frequency.0) as u16; | 357 | let min_period = max_period * (min_frequency.0 / max_frequency.0) as u16; |
| 315 | 358 | ||
| 316 | Self { | 359 | Self { |
| 360 | timer: PhantomData, | ||
| 361 | channel: PhantomData, | ||
| 317 | min_period: min_period, | 362 | min_period: min_period, |
| 318 | max_period: max_period, | 363 | max_period: max_period, |
| 319 | phantom: PhantomData, | ||
| 320 | ch: channel, | ||
| 321 | } | 364 | } |
| 322 | } | 365 | } |
| 323 | 366 | ||
diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs index d09e38d0e..429a290ee 100644 --- a/embassy-stm32/src/pwm/mod.rs +++ b/embassy-stm32/src/pwm/mod.rs | |||
| @@ -123,7 +123,7 @@ impl From<u8> for HighResolutionControlPrescaler { | |||
| 123 | 123 | ||
| 124 | #[cfg(hrtim_v1)] | 124 | #[cfg(hrtim_v1)] |
| 125 | impl HighResolutionControlPrescaler { | 125 | impl HighResolutionControlPrescaler { |
| 126 | pub fn compute_min(val: u32) -> Self { | 126 | pub fn compute_min_high_res(val: u32) -> Self { |
| 127 | *[ | 127 | *[ |
| 128 | HighResolutionControlPrescaler::Div1, | 128 | HighResolutionControlPrescaler::Div1, |
| 129 | HighResolutionControlPrescaler::Div2, | 129 | HighResolutionControlPrescaler::Div2, |
| @@ -139,6 +139,18 @@ impl HighResolutionControlPrescaler { | |||
| 139 | .next() | 139 | .next() |
| 140 | .unwrap() | 140 | .unwrap() |
| 141 | } | 141 | } |
| 142 | |||
| 143 | pub fn compute_min_low_res(val: u32) -> Self { | ||
| 144 | *[ | ||
| 145 | HighResolutionControlPrescaler::Div32, | ||
| 146 | HighResolutionControlPrescaler::Div64, | ||
| 147 | HighResolutionControlPrescaler::Div128, | ||
| 148 | ] | ||
| 149 | .iter() | ||
| 150 | .skip_while(|psc| <HighResolutionControlPrescaler as Into<u32>>::into(**psc) <= val) | ||
| 151 | .next() | ||
| 152 | .unwrap() | ||
| 153 | } | ||
| 142 | } | 154 | } |
| 143 | 155 | ||
| 144 | pub(crate) mod sealed { | 156 | pub(crate) mod sealed { |
| @@ -367,10 +379,14 @@ foreach_interrupt! { | |||
| 367 | let f = frequency.0; | 379 | let f = frequency.0; |
| 368 | let timer_f = Self::frequency().0; | 380 | let timer_f = Self::frequency().0; |
| 369 | let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); | 381 | let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); |
| 370 | let psc = HighResolutionControlPrescaler::compute_min(psc_min); | 382 | let psc = if Self::regs().isr().read().dllrdy() { |
| 383 | HighResolutionControlPrescaler::compute_min_high_res(psc_min) | ||
| 384 | } else { | ||
| 385 | HighResolutionControlPrescaler::compute_min_low_res(psc_min) | ||
| 386 | }; | ||
| 371 | 387 | ||
| 372 | let psc_val: u32 = psc.into(); | 388 | let psc_val: u32 = psc.into(); |
| 373 | let timer_f = timer_f / psc_val; | 389 | let timer_f = 32 * (timer_f / psc_val); |
| 374 | let per: u16 = (timer_f / f) as u16; | 390 | let per: u16 = (timer_f / f) as u16; |
| 375 | 391 | ||
| 376 | let regs = Self::regs(); | 392 | let regs = Self::regs(); |
| @@ -386,10 +402,14 @@ foreach_interrupt! { | |||
| 386 | let f = frequency.0; | 402 | let f = frequency.0; |
| 387 | let timer_f = Self::frequency().0; | 403 | let timer_f = Self::frequency().0; |
| 388 | let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); | 404 | let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); |
| 389 | let psc = HighResolutionControlPrescaler::compute_min(psc_min); | 405 | let psc = if Self::regs().isr().read().dllrdy() { |
| 406 | HighResolutionControlPrescaler::compute_min_high_res(psc_min) | ||
| 407 | } else { | ||
| 408 | HighResolutionControlPrescaler::compute_min_low_res(psc_min) | ||
| 409 | }; | ||
| 390 | 410 | ||
| 391 | let psc_val: u32 = psc.into(); | 411 | let psc_val: u32 = psc.into(); |
| 392 | let timer_f = timer_f / psc_val; | 412 | let timer_f = 32 * (timer_f / psc_val); |
| 393 | let per: u16 = (timer_f / f) as u16; | 413 | let per: u16 = (timer_f / f) as u16; |
| 394 | 414 | ||
| 395 | let regs = Self::regs(); | 415 | let regs = Self::regs(); |
| @@ -410,7 +430,12 @@ foreach_interrupt! { | |||
| 410 | // The dead-time base clock runs 4 times slower than the hrtim base clock | 430 | // The dead-time base clock runs 4 times slower than the hrtim base clock |
| 411 | // u9::MAX = 511 | 431 | // u9::MAX = 511 |
| 412 | let psc_min = (psc_val * dead_time as u32) / (4 * 511); | 432 | let psc_min = (psc_val * dead_time as u32) / (4 * 511); |
| 413 | let psc = HighResolutionControlPrescaler::compute_min(psc_min); | 433 | let psc = if Self::regs().isr().read().dllrdy() { |
| 434 | HighResolutionControlPrescaler::compute_min_high_res(psc_min) | ||
| 435 | } else { | ||
| 436 | HighResolutionControlPrescaler::compute_min_low_res(psc_min) | ||
| 437 | }; | ||
| 438 | |||
| 414 | let dt_psc_val: u32 = psc.into(); | 439 | let dt_psc_val: u32 = psc.into(); |
| 415 | let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val); | 440 | let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val); |
| 416 | 441 | ||
diff --git a/examples/stm32f334/src/bin/button.rs b/examples/stm32f334/src/bin/button.rs new file mode 100644 index 000000000..599c0f27d --- /dev/null +++ b/examples/stm32f334/src/bin/button.rs | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::*; | ||
| 6 | use embassy_executor::Spawner; | ||
| 7 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 8 | use embassy_time::{Duration, Timer}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | ||
| 10 | |||
| 11 | #[embassy_executor::main] | ||
| 12 | async fn main(_spawner: Spawner) { | ||
| 13 | info!("Hello World!"); | ||
| 14 | |||
| 15 | let p = embassy_stm32::init(Default::default()); | ||
| 16 | |||
| 17 | let mut out1 = Output::new(p.PA8, Level::Low, Speed::High); | ||
| 18 | |||
| 19 | out1.set_high(); | ||
| 20 | Timer::after(Duration::from_millis(500)).await; | ||
| 21 | out1.set_low(); | ||
| 22 | |||
| 23 | Timer::after(Duration::from_millis(500)).await; | ||
| 24 | info!("end program"); | ||
| 25 | |||
| 26 | cortex_m::asm::bkpt(); | ||
| 27 | } | ||
diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs index 1b5d509e7..364119744 100644 --- a/examples/stm32f334/src/bin/pwm.rs +++ b/examples/stm32f334/src/bin/pwm.rs | |||
| @@ -5,12 +5,20 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_stm32::pwm::advanced_pwm::*; | 7 | use embassy_stm32::pwm::advanced_pwm::*; |
| 8 | use embassy_stm32::time::khz; | 8 | use embassy_stm32::time::{khz, mhz}; |
| 9 | use embassy_stm32::Config; | ||
| 10 | use embassy_time::{Duration, Timer}; | ||
| 9 | use {defmt_rtt as _, panic_probe as _}; | 11 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 12 | ||
| 11 | #[embassy_executor::main] | 13 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 14 | async fn main(_spawner: Spawner) { |
| 13 | let p = embassy_stm32::init(Default::default()); | 15 | let mut config: Config = Default::default(); |
| 16 | config.rcc.sysclk = Some(mhz(64)); | ||
| 17 | config.rcc.hclk = Some(mhz(64)); | ||
| 18 | config.rcc.pclk1 = Some(mhz(32)); | ||
| 19 | config.rcc.pclk2 = Some(mhz(64)); | ||
| 20 | |||
| 21 | let p = embassy_stm32::init(config); | ||
| 14 | info!("Hello World!"); | 22 | info!("Hello World!"); |
| 15 | 23 | ||
| 16 | let ch1 = PwmPin::new_cha(p.PA8); | 24 | let ch1 = PwmPin::new_cha(p.PA8); |
| @@ -29,34 +37,35 @@ async fn main(_spawner: Spawner) { | |||
| 29 | None, | 37 | None, |
| 30 | ); | 38 | ); |
| 31 | 39 | ||
| 32 | let mut buck_converter = BridgeConverter::new(pwm.ch_a, khz(100)); | 40 | info!("pwm constructed"); |
| 33 | |||
| 34 | buck_converter.set_primary_duty(0); | ||
| 35 | buck_converter.set_secondary_duty(0); | ||
| 36 | buck_converter.set_dead_time(0); | ||
| 37 | |||
| 38 | // note: if the pins are not passed into the advanced pwm struct, they will not be output | ||
| 39 | let mut boost_converter = BridgeConverter::new(pwm.ch_b, khz(100)); | ||
| 40 | 41 | ||
| 41 | boost_converter.set_primary_duty(0); | 42 | let mut buck_converter = BridgeConverter::new(pwm.ch_a, khz(5)); |
| 42 | boost_converter.set_secondary_duty(0); | ||
| 43 | 43 | ||
| 44 | // let max = pwm.get_max_duty(); | 44 | // embassy_stm32::pac::HRTIM1 |
| 45 | // pwm.set_dead_time(max / 1024); | 45 | // .tim(0) |
| 46 | // .setr(0) | ||
| 47 | // .modify(|w| w.set_sst(Activeeffect::SETACTIVE)); | ||
| 46 | // | 48 | // |
| 47 | // pwm.enable(Channel::Ch1); | 49 | // Timer::after(Duration::from_millis(500)).await; |
| 48 | // | 50 | // |
| 49 | // info!("PWM initialized"); | 51 | // embassy_stm32::pac::HRTIM1 |
| 50 | // info!("PWM max duty {}", max); | 52 | // .tim(0) |
| 51 | // | 53 | // .rstr(0) |
| 52 | // loop { | 54 | // .modify(|w| w.set_srt(Inactiveeffect::SETINACTIVE)); |
| 53 | // pwm.set_duty(Channel::Ch1, 0); | 55 | |
| 54 | // Timer::after(Duration::from_millis(300)).await; | 56 | let max_duty = buck_converter.get_max_compare_value(); |
| 55 | // pwm.set_duty(Channel::Ch1, max / 4); | 57 | |
| 56 | // Timer::after(Duration::from_millis(300)).await; | 58 | info!("max compare value: {}", max_duty); |
| 57 | // pwm.set_duty(Channel::Ch1, max / 2); | 59 | |
| 58 | // Timer::after(Duration::from_millis(300)).await; | 60 | buck_converter.set_dead_time(max_duty / 20); |
| 59 | // pwm.set_duty(Channel::Ch1, max - 1); | 61 | buck_converter.set_primary_duty(max_duty / 2); |
| 60 | // Timer::after(Duration::from_millis(300)).await; | 62 | buck_converter.set_secondary_duty(3 * max_duty / 4); |
| 61 | // } | 63 | |
| 64 | buck_converter.start(); | ||
| 65 | |||
| 66 | Timer::after(Duration::from_millis(500)).await; | ||
| 67 | |||
| 68 | info!("end program"); | ||
| 69 | |||
| 70 | cortex_m::asm::bkpt(); | ||
| 62 | } | 71 | } |
