Skip to content

Commit

Permalink
improve pwm
Browse files Browse the repository at this point in the history
- dead time
- fix typo
- update changelog
  • Loading branch information
AdinAck committed Oct 1, 2023
1 parent eed06fb commit 461b136
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 50 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Provide getters to serial status flags idle/txe/rxne/tc.
- Provide ability to reset timer UIF interrupt flag
- PWM complementary output capability for TIM1 with new example to demonstrate
- Very simple dead time control of complementary PWM channels

### Fixed

- Wrong mode when using PWM channel 2 of a two-channel timer
- `adc_values` example conversion error
- Fixed typo in setup of complementary channels

## [v0.18.0] - 2021-11-14

Expand Down
9 changes: 8 additions & 1 deletion examples/pwm_complementary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ use cortex_m_rt::entry;

use stm32f0xx_hal as hal;

use hal::{delay::Delay, pac, prelude::*, pwm};
use hal::{
delay::Delay,
pac,
prelude::*,
pwm::{self, DTInterval::*, *},
};

#[entry]
fn main() -> ! {
Expand All @@ -31,6 +36,8 @@ fn main() -> ! {
let max_duty = ch1.get_max_duty();
ch1.set_duty(max_duty / 2);
ch1.enable();

ch1n.set_dead_time(DT_2);
ch1n.enable();

// simple duty sweep
Expand Down
80 changes: 31 additions & 49 deletions src/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@ pub struct C3;
pub struct C3N;
pub struct C4;

pub enum DTInterval {
DT_0 = 0,
DT_1 = 1,
DT_2 = 2,
DT_3 = 3,
DT_4 = 4,
DT_5 = 5,
DT_6 = 6,
DT_7 = 7,
}

pub trait ComplementaryPwm {
fn disable(&mut self);
fn enable(&mut self);

fn set_dead_time(&mut self, duration: DTInterval);
}

pub struct PwmChannels<TIM, CHANNELS> {
_channel: PhantomData<CHANNELS>,
_tim: PhantomData<TIM>,
Expand Down Expand Up @@ -321,7 +339,7 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().set_bit());
rcc.regs.$apbrstr.modify(|_, w| w.$timXrst().clear_bit());

if PINS::C1N | PINS::C1N | PINS::C1N {
if PINS::C1N | PINS::C2N | PINS::C3N {
tim.bdtr.modify(|_, w| w.ossr().set_bit());
}
if PINS::C1 {
Expand Down Expand Up @@ -406,9 +424,7 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C1N> {
type Duty = u16;

impl ComplementaryPwm for PwmChannels<$TIMX, C1N> {
//NOTE(unsafe) atomic write with no side effects
fn disable(&mut self) {
unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1ne().clear_bit()) };
Expand All @@ -419,19 +435,9 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc1ne().set_bit()) };
}

//NOTE(unsafe) atomic read with no side effects
fn get_duty(&self) -> u16 {
unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 }
}

//NOTE(unsafe) atomic read with no side effects
fn get_max_duty(&self) -> u16 {
unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
}

//NOTE(unsafe) atomic write with no side effects
fn set_duty(&mut self, duty: u16) {
unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) }
// NOTE: dead time insertion is per timer not per channel
fn set_dead_time(&mut self, duration: DTInterval) {
unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(duration as u8)) };
}
}

Expand Down Expand Up @@ -464,9 +470,7 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C2N> {
type Duty = u16;

impl ComplementaryPwm for PwmChannels<$TIMX, C2N> {
//NOTE(unsafe) atomic write with no side effects
fn disable(&mut self) {
unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc2ne().clear_bit()) };
Expand All @@ -477,19 +481,9 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc2ne().set_bit()) };
}

//NOTE(unsafe) atomic read with no side effects
fn get_duty(&self) -> u16 {
unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() as u16 }
}

//NOTE(unsafe) atomic read with no side effects
fn get_max_duty(&self) -> u16 {
unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
}

//NOTE(unsafe) atomic write with no side effects
fn set_duty(&mut self, duty: u16) {
unsafe { (*$TIMX::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) }
// NOTE: dead time insertion is per timer not per channel
fn set_dead_time(&mut self, duration: DTInterval) {
unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(duration as u8)) };
}
}

Expand Down Expand Up @@ -522,9 +516,7 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
}
}

impl hal::PwmPin for PwmChannels<$TIMX, C3N> {
type Duty = u16;

impl ComplementaryPwm for PwmChannels<$TIMX, C3N> {
//NOTE(unsafe) atomic write with no side effects
fn disable(&mut self) {
unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc3ne().clear_bit()) };
Expand All @@ -535,19 +527,9 @@ macro_rules! pwm_4_channels_with_3_complementary_outputs {
unsafe { (*($TIMX::ptr())).ccer.modify(|_, w| w.cc3ne().set_bit()) };
}

//NOTE(unsafe) atomic read with no side effects
fn get_duty(&self) -> u16 {
unsafe { (*$TIMX::ptr()).ccr3.read().ccr().bits() as u16 }
}

//NOTE(unsafe) atomic read with no side effects
fn get_max_duty(&self) -> u16 {
unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }
}

//NOTE(unsafe) atomic write with no side effects
fn set_duty(&mut self, duty: u16) {
unsafe { (*$TIMX::ptr()).ccr3.write(|w| w.ccr().bits(duty.into())) }
// NOTE: dead time insertion is per timer not per channel
fn set_dead_time(&mut self, duration: DTInterval) {
unsafe { (*($TIMX::ptr())).bdtr.modify(|_, w| w.dtg().bits(duration as u8)) };
}
}

Expand Down

0 comments on commit 461b136

Please sign in to comment.