2020-03-03 09:48 PM
I have a 10 mhz external clock. I want to generate a phased locked division down to 1hz exclusively with timers. In my current test setup I am generating the 10mhz using TIM1 from the internal clock (this is to simulate the external clock). I am putting that out on a pin and I see that on a scope and it looks reasonable.
So far I have tried bringing that signal into timer 2 etr2 as the clock source for TIM2_ch2 as the TIM2 clock source and setting up the timer to divide 10mhz down to 1hz but it is not working. Maybe I am missing something about using an external clock for a timer.
Also is there a better way to do this?
The actual external clock that will be used is a very high accuracy device.
This test board is an F4 discovery board
Here is the timer 2 initialization code:
static void MX_TIM2_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 1999;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 4999;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 1000;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim2);
}
Solved! Go to Solution.
2020-03-04 10:32 AM
The simplest way is to use External clock source mode 2. Setting the TIM_SMCR_ECE bit selects the TIMx_ETR pin instead of the internal clock source.
I could never figure out the HAL timer functions either, so I'm going to use the register interface, as documented in the reference manual. Look for External clock source mode 2 and PWM mode in the timer functional description section.
Necessary RCC clocks should be activated
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
Set TIM2_ETR and TIM2_CH2 pin mappings in GPIO.
Mapping TIM2_ETR to PA15 (AF1), and TIM2_CH2 to PA1 (AF1)
GPIOA->AFR[0] = (GPIOA->AFR[0] & 0xFFFFFF0F) | 0x00000010; // bitfield 4:7 = 1
GPIOA->AFR[1] = (GPIOA->AFR[1] & 0x0FFFFFFF) | 0x10000000; // bitfield 28:31 = 1
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER1|GPIO_MODER_MODER15))|
GPIO_MODER_MODER1_1 | GPIO_MODER_MODER15_1; // bit fields 2:3 and 30:31 = 0b10
Set external clock mode 2
TIM2->SMCR = TIM_SMCR_ECE;
Set the prescaler and period to get a 1 Hz signal
TIM2->PSC = 10000 - 1;
TIM2->EGR = TIM_EGR_UG; // update prescaler
TIM2->ARR = 1000 - 1;
Enable PWM with 50% duty on channel 2
TIM2->CCR2 = 500 - 1;
TIM2->CCMR1 = TIM_CCMR1_OC2M_1|TIM_CCMR1_OC2M_2; // OC2M = 0b110 PWM mode 1
TIM2->CCER = TIM_CCER_CC2E; // enable channel 2
Finally, start the timer.
TIM2->CR1 = TIM_CR1_CEN;
2020-03-03 11:21 PM
> TIM_CLOCKSOURCE_INTERNAL
I don't use Cube, but this doesn't sound right, once you want to use external clock source.
Read the TIM chapter in RM, search for External clock mode using ETR.
JW
2020-03-04 10:32 AM
The simplest way is to use External clock source mode 2. Setting the TIM_SMCR_ECE bit selects the TIMx_ETR pin instead of the internal clock source.
I could never figure out the HAL timer functions either, so I'm going to use the register interface, as documented in the reference manual. Look for External clock source mode 2 and PWM mode in the timer functional description section.
Necessary RCC clocks should be activated
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
Set TIM2_ETR and TIM2_CH2 pin mappings in GPIO.
Mapping TIM2_ETR to PA15 (AF1), and TIM2_CH2 to PA1 (AF1)
GPIOA->AFR[0] = (GPIOA->AFR[0] & 0xFFFFFF0F) | 0x00000010; // bitfield 4:7 = 1
GPIOA->AFR[1] = (GPIOA->AFR[1] & 0x0FFFFFFF) | 0x10000000; // bitfield 28:31 = 1
GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER1|GPIO_MODER_MODER15))|
GPIO_MODER_MODER1_1 | GPIO_MODER_MODER15_1; // bit fields 2:3 and 30:31 = 0b10
Set external clock mode 2
TIM2->SMCR = TIM_SMCR_ECE;
Set the prescaler and period to get a 1 Hz signal
TIM2->PSC = 10000 - 1;
TIM2->EGR = TIM_EGR_UG; // update prescaler
TIM2->ARR = 1000 - 1;
Enable PWM with 50% duty on channel 2
TIM2->CCR2 = 500 - 1;
TIM2->CCMR1 = TIM_CCMR1_OC2M_1|TIM_CCMR1_OC2M_2; // OC2M = 0b110 PWM mode 1
TIM2->CCER = TIM_CCER_CC2E; // enable channel 2
Finally, start the timer.
TIM2->CR1 = TIM_CR1_CEN;
2020-03-04 07:15 PM
Thanks allot for your very thorough answer!!! It works well in my test board, I can't wait to test it properly, the 10mhz clock is less than perfect over breadboard jumpers.