cancel
Showing results for 
Search instead for 
Did you mean: 

Low level PWM problems

chichkinei
Associate II
Posted on January 05, 2013 at 01:51

I'm trying to implement PWM on TIM4_CH4 with output on PD15 using only low level register writes as I don't much care for all the high level functions provided. However, I tried to convert the functions to their basics at around 2 AM, and unsurprisingly it doesn't work. This is the code I low level'ified (https://my.st.com/public/STe2ecommunities/mcu/Lists/STM32Discovery/DispForm.aspx?ID=1816&Source=/public/STe2ecommunities/Tags.aspx?tags=stm32f4). I got rid of all the extra channels and this is what I was left with:

uint16_t BKPWM = 50;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN | RCC_AHB1ENR_GPIOEEN; 
// GPIOD and E enable
RCC->APB1ENR |= RCC_APB1Periph_TIM4; 
// timer 4 enable
GPIOE->MODER = 0x55555555; 
// portE all outputs
GPIOD->MODER = 0x91110000; 
// 8, 10, 12, 14 outputs. 15 alternate function (timer 4)
GPIOD->OSPEEDR = 0xFFFFFFFF;
GPIOE->OSPEEDR = 0xFFFFFFFF;
GPIOD->AFR[2] = 0x20000000; 
// PD15 to AF2
PrescalerValue = (uint16_t) ((168000000 /2) / 28000000) - 1;
TIM4->CR1 &= (uint16_t)~0x70;
TIM4->CR1 &= (uint16_t)(~TIM_CR1_CKD);
TIM4->ARR = 255;
TIM4->PSC = PrescalerValue;
TIM4->EGR = TIM_PSCReloadMode_Immediate;
TIM4->CCER &= (uint16_t)~TIM_CCER_CC4E;
TIM4->CCMR2 &= (uint16_t)~TIM_CCMR2_OC4M;
TIM4->CCMR2 &= (uint16_t)~TIM_CCMR2_CC4S;
TIM4->CCMR2 |= (uint16_t)(TIM_OCMode_PWM1 << 8);
TIM4->CCER &= (uint16_t)~TIM_CCER_CC4P;
TIM4->CCER |= (uint16_t)(TIM_OCPolarity_High << 12);
TIM4->CCER |= (uint16_t)(TIM_OutputState_Enable << 12);
TIM4->CCR4 = BKPWM;
// 200 / 255
TIM4->CCMR2 &= (uint16_t)(~TIM_CCMR2_OC4PE);
TIM4->CCMR2 |= (uint16_t)(TIM_OCPreload_Enable << 8);
TIM4->CR1 |= TIM_CR1_ARPE;
TIM4->CR1 |= TIM_CR1_CEN;

I'm sure it's just a simple mistake of accidentally deleting something while converting the code but I can't find it.
4 REPLIES 4
Posted on January 05, 2013 at 02:43

This looks wrong
 GPIOD->AFR[2] = 0x20000000; 
// PD15 to AF2

Should be, although I'd probably mask it on

GPIOD->AFR[1] = 0x20000000; 
// PD15 to AF2

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
chichkinei
Associate II
Posted on January 05, 2013 at 05:11

Ah, that did it. I swear I tried both [1] and [2] though, since the datasheet doesn't mention which one is the top half of the register. I guess there were other problems too when I tried [1]. Thanks.

Posted on January 05, 2013 at 05:53

[0] is the bottom half 0 .. 7

[1] is the top half 8 .. 15

[2] exceeds the bounds of the array
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
chichkinei
Associate II
Posted on January 05, 2013 at 06:05

Wow, I think this might be the first time in my life that I've been thrown off by a zero indexed array.