1MHz output compare
Hello,
I would like to ask regarding the highest speed I can toggle using output compare.
When I try to toggle the output with the frequency of 1M Hz, I do not get what I expect.
As attached program, I can get the correct frequency for Channel 1 to 3, but not channel 4. Could you please take a look at it and explain what could be the issue?
I attached the logic analyzer output screen for reference.
I am using Windows 7 64 bit, STM32f4Discovery Board & System Workbench Version: 1.13.1.201701261206
Thank you.
/* Includes ----------------------*/
- include “myTimer4.h”
/* Private variables ---------------------*/
TIM_TimeBaseInitTypeDef TIM4_TimeBaseStructure;
TIM_OCInitTypeDef TIM4_OCInitStructure;
static uint16_t TIM4_PrescalerValue = 0;
static uint32_t TIM4_Frequency = 42000000;
static uint16_t uhCapture = 0;
//static uint16_t myTimer = RCC_APB1Periph_TIM4;
__IO uint16_t TIM4_CCR1_Val = 42000;
__IO uint16_t TIM4_CCR2_Val = 4200;
__IO uint16_t TIM4_CCR3_Val = 420;
__IO uint16_t TIM4_CCR4_Val = 42;
/* Private function prototypes -------------------*/
void TIM4_OC_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
/* TIM4 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
/* GPIOC clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
/* GPIOC Configuration: TIM4 CH1 (PD12), TIM4 CH2 (PD13), TIM4 CH2 (PD14) and TIM4 CH4 (PD15) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Connect TIM Channels to AF2 */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource14, GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource15, GPIO_AF_TIM4);
/* Enable the TIM4 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* ---------------------------
TIM4 Configuration: Output Compare Toggle Mode:
In this example TIM4 input clock (TIM4CLK) is set to 2 * APB1 clock (PCLK1),
since APB1 prescaler is different from 1.
TIM4CLK = 2 * PCLK1
PCLK1 = HCLK / 4
=> TIM4CLK = HCLK / 2 = SystemCoreClock /2
To get TIM4 counter clock at 42 MHz, the prescaler is computed as follows:
Prescaler = (TIM4CLK / TIM4 counter clock) - 1
Prescaler = ((SystemCoreClock /2) /42 MHz) - 1
CC1 update rate = TIM4 counter clock / TM4_CCR1_Val = 1k Hz
==> So the TIM4 Channel 1 generates a periodic signal with a
frequency equal to 500 Hz.
CC2 update rate = TIM4 counter clock / TM4_CCR2_Val = 10k Hz
==> So the TIM4 Channel 2 generates a periodic signal with a
frequency equal to 5k Hz.
CC3 update rate = TIM4 counter clock / TM4_CCR3_Val = 100k Hz
==> So the TIM4 Channel 3 generates a periodic signal with a
frequency equal to 50k Hz.
CC4 update rate = TIM4 counter clock / TM4_CCR4_Val = 1M Hz
==> So the TIM4 Channel 4 generates a periodic signal with a
frequency equal to 500k Hz.
Note:
SystemCoreClock variable holds HCLK frequency and is defined in system_stm32f4xx.c file.
Each time the core clock (HCLK) changes, user had to call SystemCoreClockUpdate()
function to update SystemCoreClock variable value. Otherwise, any configuration
based on this variable will be incorrect.
--------------------------- */
/* Compute the prescaler value */
TIM4_PrescalerValue = (uint16_t) ((SystemCoreClock / 2) / TIM4_Frequency) - 1;
/* Time base configuration */
TIM4_TimeBaseStructure.TIM_Period = 65535;
TIM4_TimeBaseStructure.TIM_Prescaler = TIM4_PrescalerValue;
TIM4_TimeBaseStructure.TIM_ClockDivision = 0;
TIM4_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM4_TimeBaseStructure);
/* Output Compare Toggle Mode configuration: Channel1 */
TIM4_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;
TIM4_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM4_OCInitStructure.TIM_Pulse = TIM4_CCR1_Val;
TIM4_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
TIM_OC1Init(TIM4, &TIM4_OCInitStructure);
TIM_OC1PreloadConfig(TIM4, TIM_OCPreload_Disable);
/* Output Compare Toggle Mode configuration: Channel2 */
TIM4_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM4_OCInitStructure.TIM_Pulse = TIM4_CCR2_Val;
TIM_OC2Init(TIM4, &TIM4_OCInitStructure);
TIM_OC2PreloadConfig(TIM4, TIM_OCPreload_Disable);
/* Output Compare Toggle Mode configuration: Channel3 */
TIM4_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM4_OCInitStructure.TIM_Pulse = TIM4_CCR3_Val;
TIM_OC3Init(TIM4, &TIM4_OCInitStructure);
TIM_OC3PreloadConfig(TIM4, TIM_OCPreload_Disable);
/* Output Compare Toggle Mode configuration: Channel4 */
TIM4_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM4_OCInitStructure.TIM_Pulse = TIM4_CCR4_Val;
TIM_OC4Init(TIM4, &TIM4_OCInitStructure);
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Disable);
/* TIM enable counter */
TIM_Cmd(TIM4, ENABLE);
/* TIM IT enable */
TIM_ITConfig(TIM4, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);
}
void TIM4_InterruptHandler()
{
if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1 );
uhCapture = TIM_GetCapture1(TIM4);
TIM_SetCompare1(TIM4, uhCapture + TIM4_CCR1_Val );
}
if (TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);
uhCapture = TIM_GetCapture2(TIM4);
TIM_SetCompare2(TIM4, uhCapture + TIM4_CCR2_Val);
}
if (TIM_GetITStatus(TIM4, TIM_IT_CC3) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_CC3);
uhCapture = TIM_GetCapture3(TIM4);
TIM_SetCompare3(TIM4, uhCapture + TIM4_CCR3_Val);
}
if (TIM_GetITStatus(TIM4, TIM_IT_CC4) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_CC4);
uhCapture = TIM_GetCapture4(TIM4);
TIM_SetCompare4(TIM4, uhCapture + TIM4_CCR4_Val);
}
}