2021-01-21 08:31 PM
Set the APB2 timer to 180MHz to generate a 25MHz clock signal in output compare mode.
And it tries to increase the decoder signal by 1 by counting every 513 rising edges.
However, the decoder input signal is toggled on more than 513 signals.
By changing the timer counter period(Auto Reload Reg.) to lower the signal to 240Khz, the decoder input signal will toggle according to the number of counts accurately.
In my opinion, iterations and conditional statements within the interrupt callback function affect, and it doesn't seem to keep up with speeds above 1Mhz.
Is there a way to accurately count and stop by making a 25Mhz signal with a timer?
Part of the program source, timer setting value, and clock setting value are attached.
uint32_t gclkcnt = 0;
uint32_t change_scan = 513;
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1 && htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
if(gclkcnt++ == (change_scan*2)-1)
{
//HAL_GPIO_TogglePin(A_IN_GPIO_Port, A_IN_Pin);
HAL_TIM_OC_Stop_IT(&htim1, TIM_CHANNEL_2);
if(GPIOD->ODR != 0x00000017) GPIOD->ODR = GPIOD->ODR + 0x1;
else GPIOD->ODR = 0x00000000;
gclkcnt = 0;
}
}
}
int main (void)
{
...
...
HAL_TIM_OC_Start_IT(&htim1, TIM_CHANNEL_2);
while(1)
}
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN TIM1_Init 1 */
/* USER CODE END TIM1_Init 1 */
htim1.Instance = TIM1;
htim1.Init.Prescaler = 1;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 1;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_TOGGLE;
sConfigOC.Pulse = 1;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
}
2021-01-21 08:47 PM
It is unrealistic to interrupt at MHz rates, and especially so with all the HAL callback baggage eating cycles.
Want to count 25 MHz pulses, use the TIM in External Clock mode. It is not going to feed-thru the clock signal, use wire. Clocks and flip-flops are always going to divide by at least two.
Having a TIM Period of 1 [0, 1] states is not recommended, use the full width of the counter. For high rates use a 32-bit TIM, in maximal mode.
2021-01-21 10:22 PM
Thank you for providing information on how to solve the problem.
I will try again as you said.