2015-01-19 12:22 PM
The complete project is
https://my.st.com//public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Attachments/49654/TIM8_OC.zip
.I've made a simple test-program, which toggles some LEDs.I'd like PC6-PC9 to toggle automatically when a compare/match occurs.On the STM32F407 Discovery board, I had similar code working for TIM3, but even on my third try, I can't seem to get TIM8 to update the OC1...OC4 pins.&sharpinclude ''stm32f4xx_hal_conf.h''
&sharpdefine CPU_FREQUENCY 168 MHz
&sharpdefine MHz * 1000000
&sharpdefine ms * ((CPU_FREQUENCY / 1000) / 5)
void
setupTimer(void
);//&sharpdefine PC8_GPO
int
main(void
){
/* Set up GPIOC for our Output Compare pins on PC6..PC9: */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
/* enable Port C clock power for OC output */
GPIOC->MODER = (GPIOC->MODER &
0xfff00fff
) |
0x000AA000
;
/* PC6, PC7, PC8 and PC9 are using alternate functions (mode 2) */GPIOC->AFR[
0
] = (GPIOC->AFR[0
] &0x00ffffff
) |0x33000000
;/* set PC6 and PC7 to AF3 */
GPIOC->AFR[
1
] = (GPIOC->AFR[1
] &0xffffff00
) |0x00000033
;/* set PC8 and PC9 to AF3 */
&sharpifdef PC8_GPO
GPIOC->MODER = (GPIOC->MODER &
0xfffcffff
) |
0x00010000
;
/* change PC8 to plain output (mode 1) - this works, LED blinks when toggled manually. */&sharpendif
/* Set up GPIOD for our 4 LEDs on PD12..PD15 */
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
/* enable Port D clock power */
GPIOD->MODER = (GPIOD->MODER &
0x00ffffff
) |
0x55000000
;
/* PD12, PD13, PD14 and PD15 are outputs */GPIOD->ODR = (GPIOD->ODR &
0x0fff
) |
0x8000
;
/* set PD15 high, set PD14, PD13 and PD12 low */setupTimer();
while
(
1
)
{
&sharpifdef PC8_GPO
GPIOC->ODR ^=
0x0100
;
/* toggle PC8 (only when configured as output, this works) */&sharpendif
for
(uint32_t k =0
; k <450
ms; k++){volatile
uint32_t dummy; (void
) dummy; }GPIOD->ODR ^=
0xc000
;/* toggle PD14 and PD15 */
for
(uint32_t k =0
; k <50
ms; k++){volatile
uint32_t dummy; (void
) dummy; }GPIOD->ODR ^=
0xc000
;/* toggle PD14 and PD15 */
// __WFI(); /* (temporarily disabled) */
}
return
(
0
);
}
void
setupTimer(void
){
__TIM8_CLK_ENABLE();
/* enable TIM8 clock power */
TIM8->CR1 =
0
;
/* stop timer, while we're configuring it. */TIM8->PSC =
16800
-
1
;
/* set prescaler to divide by 16800, so we get a 168 MHz / 16800 = 10.0 kHz counter frequency */TIM8->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1;
/* OC2REF is active as long as TIM8->CNT < TIM8->CCR3, otherwise it's inactive. */TIM8->ARR =
10000
;
/* set the frame length (one second) */TIM8->CCR3 =
10000
/
4
;
/* a short on pulse and a long off pulse */TIM8->CCER = TIM_CCER_CC3E | TIM_CCER_CC3P;
/* enable output for pulse, set polarity negative */
&sharpif 01
TIM8->CCR1 =
10000
/
4
;
/* a short on pulse and a long off pulse */TIM8->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1P;
/* enable output for pulse, set polarity negative */
TIM8->CCR2 =
10000
/
4
;
/* a short on pulse and a long off pulse */TIM8->CCER |= TIM_CCER_CC2E;
/* enable output for pulse, set polarity positive */TIM8->CCR4 =
10000
/
4
;
/* a short on pulse and a long off pulse */TIM8->CCER |= TIM_CCER_CC4E;
/* enable output for pulse, set polarity positive */&sharpendif
TIM8->DIER = TIM_DIER_UIE | TIM_DIER_CC3IE;
/* enable Interrupt on Update Event and Compare 3. (Interrupt is invoked) */NVIC_EnableIRQ(TIM8_CC_IRQn);
/* enable Timer8 Capture Compare interrupt */TIM8->CR1 = TIM_CR1_URS | TIM_CR1_CEN;
/* enable timer. Only generate update on counter overflow. */}
void
TIM8_CC_IRQHandler(
void
)
/* Capture and Compare interrupt */{
TIM8->SR = ~(TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF);
/* Clear interrupt pending bits. */
GPIOD->ODR ^=
0x1000
;/* toggle PD12 */
}
#solved-bdtr-moe-tim_bdtr_moe #tim8-oc3-ccr3-toggle-output2015-01-19 12:32 PM
TIM1 and TIM8 are special, they have more registers to correctly configure.
/**
* @brief Enables or disables the TIM peripheral Main Outputs.
* @param TIMx: where x can be 1 or 8 to select the TIMx peripheral.
* @param NewState: new state of the TIM peripheral Main Outputs.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_LIST4_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the TIM Main Output */
TIMx->BDTR |= TIM_BDTR_MOE;
}
else
{
/* Disable the TIM Main Output */
TIMx->BDTR &= (uint16_t)~TIM_BDTR_MOE;
}
}
2015-01-19 12:48 PM
Thank you so much, Clive.
This was exactly what was wrong. After adding ...TIM8->BDTR |= TIM_BDTR_MOE;
/* enable main output */
... it works the way I intended it to work.