2 #include "../hardware_api.h"
4 #if defined(_STM32_DEF_)
6 #define _PWM_RESOLUTION 12 // 12bit
7 #define _PWM_RANGE 4095.0// 2^12 -1 = 4095
8 #define _PWM_FREQUENCY 25000 // 25khz
9 #define _PWM_FREQUENCY_MAX 50000 // 50khz
12 #define _HARDWARE_6PWM 1
13 #define _SOFTWARE_6PWM 0
14 #define _ERROR_6PWM -1
18 void _setPwm(
int ulPin, uint32_t value,
int resolution)
20 PinName pin = digitalPinToPinName(ulPin);
21 TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin, PinMap_PWM);
22 uint32_t index = get_timer_index(Instance);
23 HardwareTimer *HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
25 uint32_t channel = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_PWM));
26 HT->setCaptureCompare(channel, value, (TimerCompareFormat_t)resolution);
31 HardwareTimer* _initPinPWM(uint32_t PWM_freq,
int ulPin)
33 PinName pin = digitalPinToPinName(ulPin);
34 TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin, PinMap_PWM);
36 uint32_t index = get_timer_index(Instance);
37 if (HardwareTimer_Handle[index] == NULL) {
38 HardwareTimer_Handle[index]->__this =
new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin, PinMap_PWM));
39 HardwareTimer_Handle[index]->handle.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
40 HAL_TIM_Base_Init(&(HardwareTimer_Handle[index]->handle));
42 HardwareTimer *HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
43 uint32_t channel = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_PWM));
44 HT->setMode(channel, TIMER_OUTPUT_COMPARE_PWM1, pin);
45 HT->setOverflow(PWM_freq, HERTZ_FORMAT);
53 HardwareTimer* _initPinPWMHigh(uint32_t PWM_freq,
int ulPin)
55 return _initPinPWM(PWM_freq, ulPin);
59 HardwareTimer* _initPinPWMLow(uint32_t PWM_freq,
int ulPin)
61 PinName pin = digitalPinToPinName(ulPin);
62 TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(pin, PinMap_PWM);
63 uint32_t index = get_timer_index(Instance);
65 if (HardwareTimer_Handle[index] == NULL) {
66 HardwareTimer_Handle[index]->__this =
new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(pin, PinMap_PWM));
67 HardwareTimer_Handle[index]->handle.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
68 HAL_TIM_Base_Init(&(HardwareTimer_Handle[index]->handle));
69 TIM_OC_InitTypeDef sConfigOC = TIM_OC_InitTypeDef();
70 sConfigOC.OCMode = TIM_OCMODE_PWM2;
71 sConfigOC.Pulse = 100;
72 sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
73 sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
74 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
75 sConfigOC.OCIdleState = TIM_OCIDLESTATE_SET;
76 sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
77 uint32_t channel = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_PWM));
78 HAL_TIM_PWM_ConfigChannel(&(HardwareTimer_Handle[index]->handle), &sConfigOC, channel);
80 HardwareTimer *HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
81 uint32_t channel = STM_PIN_CHANNEL(pinmap_function(pin, PinMap_PWM));
82 HT->setMode(channel, TIMER_OUTPUT_COMPARE_PWM2, pin);
83 HT->setOverflow(PWM_freq, HERTZ_FORMAT);
91 void _alignPWMTimers(HardwareTimer *HT1,HardwareTimer *HT2,HardwareTimer *HT3)
105 void _alignPWMTimers(HardwareTimer *HT1,HardwareTimer *HT2,HardwareTimer *HT3,HardwareTimer *HT4)
122 HardwareTimer* _initHardware6PWMInterface(uint32_t PWM_freq,
float dead_zone,
int pinA_h,
int pinA_l,
int pinB_h,
int pinB_l,
int pinC_h,
int pinC_l)
124 PinName uhPinName = digitalPinToPinName(pinA_h);
125 PinName ulPinName = digitalPinToPinName(pinA_l);
126 PinName vhPinName = digitalPinToPinName(pinB_h);
127 PinName vlPinName = digitalPinToPinName(pinB_l);
128 PinName whPinName = digitalPinToPinName(pinC_h);
129 PinName wlPinName = digitalPinToPinName(pinC_l);
131 TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(uhPinName, PinMap_PWM);
133 uint32_t index = get_timer_index(Instance);
135 if (HardwareTimer_Handle[index] == NULL) {
136 HardwareTimer_Handle[index]->__this =
new HardwareTimer((TIM_TypeDef *)pinmap_peripheral(uhPinName, PinMap_PWM));
137 HardwareTimer_Handle[index]->handle.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
138 HAL_TIM_Base_Init(&(HardwareTimer_Handle[index]->handle));
139 ((HardwareTimer *)HardwareTimer_Handle[index]->__this)->setOverflow(PWM_freq, HERTZ_FORMAT);
141 HardwareTimer *HT = (HardwareTimer *)(HardwareTimer_Handle[index]->__this);
143 HT->setMode(STM_PIN_CHANNEL(pinmap_function(uhPinName, PinMap_PWM)), TIMER_OUTPUT_COMPARE_PWM1, uhPinName);
144 HT->setMode(STM_PIN_CHANNEL(pinmap_function(ulPinName, PinMap_PWM)), TIMER_OUTPUT_COMPARE_PWM1, ulPinName);
145 HT->setMode(STM_PIN_CHANNEL(pinmap_function(vhPinName, PinMap_PWM)), TIMER_OUTPUT_COMPARE_PWM1, vhPinName);
146 HT->setMode(STM_PIN_CHANNEL(pinmap_function(vlPinName, PinMap_PWM)), TIMER_OUTPUT_COMPARE_PWM1, vlPinName);
147 HT->setMode(STM_PIN_CHANNEL(pinmap_function(whPinName, PinMap_PWM)), TIMER_OUTPUT_COMPARE_PWM1, whPinName);
148 HT->setMode(STM_PIN_CHANNEL(pinmap_function(wlPinName, PinMap_PWM)), TIMER_OUTPUT_COMPARE_PWM1, wlPinName);
151 uint32_t dead_time_ns = (float)(1e9/PWM_freq)*dead_zone;
152 uint32_t dead_time = __LL_TIM_CALC_DEADTIME(SystemCoreClock, LL_TIM_GetClockDivision(HT->getHandle()->Instance), dead_time_ns);
153 LL_TIM_OC_SetDeadTime(HT->getHandle()->Instance, dead_time);
154 LL_TIM_CC_EnableChannel(HT->getHandle()->Instance, LL_TIM_CHANNEL_CH1 | LL_TIM_CHANNEL_CH1N | LL_TIM_CHANNEL_CH2 | LL_TIM_CHANNEL_CH2N | LL_TIM_CHANNEL_CH3 | LL_TIM_CHANNEL_CH3N);
166 int _interfaceType(
const int pinA_h,
const int pinA_l,
const int pinB_h,
const int pinB_l,
const int pinC_h,
const int pinC_l){
167 PinName nameAH = digitalPinToPinName(pinA_h);
168 PinName nameAL = digitalPinToPinName(pinA_l);
169 PinName nameBH = digitalPinToPinName(pinB_h);
170 PinName nameBL = digitalPinToPinName(pinB_l);
171 PinName nameCH = digitalPinToPinName(pinC_h);
172 PinName nameCL = digitalPinToPinName(pinC_l);
173 int tim1 = get_timer_index((TIM_TypeDef *)pinmap_peripheral(nameAH, PinMap_PWM));
174 int tim2 = get_timer_index((TIM_TypeDef *)pinmap_peripheral(nameAL, PinMap_PWM));
175 int tim3 = get_timer_index((TIM_TypeDef *)pinmap_peripheral(nameBH, PinMap_PWM));
176 int tim4 = get_timer_index((TIM_TypeDef *)pinmap_peripheral(nameBL, PinMap_PWM));
177 int tim5 = get_timer_index((TIM_TypeDef *)pinmap_peripheral(nameCH, PinMap_PWM));
178 int tim6 = get_timer_index((TIM_TypeDef *)pinmap_peripheral(nameCL, PinMap_PWM));
179 if(tim1 == tim2 && tim2==tim3 && tim3==tim4 && tim4==tim5 && tim5==tim6)
180 return _HARDWARE_6PWM;
181 else if(tim1 == tim2 && tim3==tim4 && tim5==tim6)
182 return _SOFTWARE_6PWM;
192 void _configure2PWM(
long pwm_frequency,
const int pinA,
const int pinB) {
193 if( !pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
194 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
198 HardwareTimer* HT1 = _initPinPWM(pwm_frequency, pinA);
199 HardwareTimer* HT2 = _initPinPWM(pwm_frequency, pinB);
201 _alignPWMTimers(HT1, HT2, HT2);
208 void _configure3PWM(
long pwm_frequency,
const int pinA,
const int pinB,
const int pinC) {
209 if( !pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
210 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
214 HardwareTimer* HT1 = _initPinPWM(pwm_frequency, pinA);
215 HardwareTimer* HT2 = _initPinPWM(pwm_frequency, pinB);
216 HardwareTimer* HT3 = _initPinPWM(pwm_frequency, pinC);
218 _alignPWMTimers(HT1, HT2, HT3);
224 void _configure4PWM(
long pwm_frequency,
const int pinA,
const int pinB,
const int pinC,
const int pinD) {
225 if( !pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
226 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
230 HardwareTimer* HT1 = _initPinPWM(pwm_frequency, pinA);
231 HardwareTimer* HT2 = _initPinPWM(pwm_frequency, pinB);
232 HardwareTimer* HT3 = _initPinPWM(pwm_frequency, pinC);
233 HardwareTimer* HT4 = _initPinPWM(pwm_frequency, pinD);
235 _alignPWMTimers(HT1, HT2, HT3, HT4);
243 _setPwm(pinA, _PWM_RANGE*dc_a, _PWM_RESOLUTION);
244 _setPwm(pinB, _PWM_RANGE*dc_b, _PWM_RESOLUTION);
250 void _writeDutyCycle3PWM(
float dc_a,
float dc_b,
float dc_c,
int pinA,
int pinB,
int pinC){
252 _setPwm(pinA, _PWM_RANGE*dc_a, _PWM_RESOLUTION);
253 _setPwm(pinB, _PWM_RANGE*dc_b, _PWM_RESOLUTION);
254 _setPwm(pinC, _PWM_RANGE*dc_c, _PWM_RESOLUTION);
261 void _writeDutyCycle4PWM(
float dc_1a,
float dc_1b,
float dc_2a,
float dc_2b,
int pin1A,
int pin1B,
int pin2A,
int pin2B){
263 _setPwm(pin1A, _PWM_RANGE*dc_1a, _PWM_RESOLUTION);
264 _setPwm(pin1B, _PWM_RANGE*dc_1b, _PWM_RESOLUTION);
265 _setPwm(pin2A, _PWM_RANGE*dc_2a, _PWM_RESOLUTION);
266 _setPwm(pin2B, _PWM_RANGE*dc_2b, _PWM_RESOLUTION);
275 int _configure6PWM(
long pwm_frequency,
float dead_zone,
const int pinA_h,
const int pinA_l,
const int pinB_h,
const int pinB_l,
const int pinC_h,
const int pinC_l){
276 if( !pwm_frequency || !
_isset(pwm_frequency) ) pwm_frequency = _PWM_FREQUENCY;
277 else pwm_frequency =
_constrain(pwm_frequency, 0, _PWM_FREQUENCY_MAX);
282 int config = _interfaceType(pinA_h, pinA_l, pinB_h, pinB_l, pinC_h, pinC_l);
289 _initHardware6PWMInterface(pwm_frequency, dead_zone, pinA_h, pinA_l, pinB_h, pinB_l, pinC_h, pinC_l);
292 HardwareTimer* HT1 = _initPinPWMHigh(pwm_frequency, pinA_h);
293 _initPinPWMLow(pwm_frequency, pinA_l);
294 HardwareTimer* HT2 = _initPinPWMHigh(pwm_frequency,pinB_h);
295 _initPinPWMLow(pwm_frequency, pinB_l);
296 HardwareTimer* HT3 = _initPinPWMHigh(pwm_frequency,pinC_h);
297 _initPinPWMLow(pwm_frequency, pinC_l);
298 _alignPWMTimers(HT1, HT2, HT3);
307 void _writeDutyCycle6PWM(
float dc_a,
float dc_b,
float dc_c,
float dead_zone,
int pinA_h,
int pinA_l,
int pinB_h,
int pinB_l,
int pinC_h,
int pinC_l){
309 int config = _interfaceType(pinA_h, pinA_l, pinB_h, pinB_l, pinC_h, pinC_l);
313 _setPwm(pinA_h, _PWM_RANGE*dc_a, _PWM_RESOLUTION);
314 _setPwm(pinB_h, _PWM_RANGE*dc_b, _PWM_RESOLUTION);
315 _setPwm(pinC_h, _PWM_RANGE*dc_c, _PWM_RESOLUTION);
318 _setPwm(pinA_l,
_constrain(dc_a + dead_zone/2, 0, 1)*_PWM_RANGE, _PWM_RESOLUTION);
319 _setPwm(pinA_h,
_constrain(dc_a - dead_zone/2, 0, 1)*_PWM_RANGE, _PWM_RESOLUTION);
320 _setPwm(pinB_l,
_constrain(dc_b + dead_zone/2, 0, 1)*_PWM_RANGE, _PWM_RESOLUTION);
321 _setPwm(pinB_h,
_constrain(dc_b - dead_zone/2, 0, 1)*_PWM_RANGE, _PWM_RESOLUTION);
322 _setPwm(pinC_l,
_constrain(dc_c + dead_zone/2, 0, 1)*_PWM_RANGE, _PWM_RESOLUTION);
323 _setPwm(pinC_h,
_constrain(dc_c - dead_zone/2, 0, 1)*_PWM_RANGE, _PWM_RESOLUTION);