2024-07-20 02:10 PM
Hi,
My one microsecond timer configured by CubeMx running on NUCLEO-C031C6 (STM32C031C6) is 3 times slower than it should be. The code is attached below.
the call "delay_us(60000000);" takes 3+ minutes to complete - it should be done in one minute.
The LL timer (TIM3) init and interrupt code is generated by CubeMx..The system clock is 48 MHZ in CubeMx.
How to fix it?
Thanks,
Rong
void MX_TIM3_Init(void)
{
LL_TIM_InitTypeDef TIM_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
/* TIM3 interrupt Init */
NVIC_SetPriority(TIM3_IRQn, 0);
NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
TIM_InitStruct.Prescaler = 0;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 48;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_EnableARRPreload(TIM3);
LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(TIM3);
/* TIM3 interrupt Init */
}
/* USER CODE BEGIN 1 */
unsigned long u_Count = 0;
/* USER CODE END 1 */
/**
* @brief This function handles TIM3 global interrupt.
*/
void TIM3_IRQHandler(void)
{
/* USER CODE BEGIN TIM3_IRQn 0 */
if (u_Count)
{
u_Count--;
}
if (LL_TIM_IsActiveFlag_UPDATE(TIM3))
LL_TIM_ClearFlag_UPDATE(TIM3);
/* USER CODE END TIM3_IRQn 0 */
}
void delay_us(const unsigned long us_Count)
{
u_Count = us_Count;
LL_TIM_EnableIT_UPDATE(TIM3);
LL_TIM_EnableCounter(TIM3);
while (u_Count !=0)
{
}
LL_TIM_DisableIT_UPDATE(TIM3);
LL_TIM_DisableCounter(TIM3);
}
int main(void)
{
static unsigned int i = 0;
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM3_Init();
MX_SPI1_Init();
MX_USART2_UART_Init();
delay_us(60000000);
}
Solved! Go to Solution.
2024-07-21 06:37 AM
Perhaps you could review examples?
STM32Cube_FW_C0_V1.0.1\Projects\NUCLEO-C031C6\Examples_LL\TIM\TIM_TimeBase_Init
/* Enable counter */
LL_TIM_EnableCounter(TIM3);
2024-07-20 02:32 PM - edited 2024-07-20 02:33 PM
The chip cannot process interrupts at 1 MHz. It will fall behind. Set your interrupt frequency to a max of about 10 kHz so one interrupt can finish before the next one is triggered.
Also note that if you have a timer frequency of 48 MHz, you want ARR=47 in order to have an update interval of 1 us. So for 10 kHz, it should be 4799.
2024-07-20 02:37 PM - edited 2024-07-20 02:38 PM
As repeatedly covered on this forum, you can't sustain 1 MHz interrupt rate, it will saturated the processor just trying to do that. So don't do it that way.
Configure the TIM in maximal mode, say 0xFFFF or 0xFFFFFFFF with a prescaler that clocks the count at 1 MHz, and then delta the entry and exit points.
uint16_t start =TIM3->CNT;
while((TIM3->CNT - start) < usdelay);
For finer resolution clock faster. For longer delays with 16-bit counters, decompose into 60 ms (60000 us) intervals
2024-07-20 03:01 PM
Hi, Guru,
So I can not have a 1 us timer, which I need,in STM32C031C6?,
What is the fastest timer I can have in this micro ?
Thanks
Rong
2024-07-20 03:09 PM
Hi, Tesla,
Could you give me the detail code for having 1 us timers?
I used CubeMx to generate the code.
"Configure the TIM in maximal mode," - How to do this?
Thanks,
Rong
void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
LL_TIM_InitTypeDef TIM_InitStruct = {0};
/* Peripheral clock enable */
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM3);
/* TIM3 interrupt Init */
NVIC_SetPriority(TIM3_IRQn, 0);
NVIC_EnableIRQ(TIM3_IRQn);
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
TIM_InitStruct.Prescaler = 0;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 48;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_EnableARRPreload(TIM3);
LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(TIM3);
/* USER CODE BEGIN TIM3_Init 2 */
/* TIM3 interrupt Init */
/* USER CODE END TIM3_Init 2 */
}
2024-07-20 04:45 PM - edited 2024-07-20 04:47 PM
Not using interrupts
TIM_InitStruct.Prescaler = 48 - 1; // Divider 48 MHz to 1 MHz (1 us ticks)
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 0xFFFF; // Maximal Count 0..65535
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
You're using it to count elapsed time, up to 65.535 ms per update period
2024-07-20 05:02 PM - edited 2024-07-21 04:54 PM
[withdrawn]
2024-07-20 05:05 PM
2024-07-21 05:40 AM
Hi, Tesla,
The execution stucks in while((TIM3->CNT - start) < us_Count);
Because TIM3->CNT does not increase.
I follow your email to have the initialization below.
Looks like need to add some API call to start running the counter?
Please help, thanks,
TIM_InitStruct.Prescaler = 48-1;
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
TIM_InitStruct.Autoreload = 0xFFFF;
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
LL_TIM_Init(TIM3, &TIM_InitStruct);
LL_TIM_EnableARRPreload(TIM3);
LL_TIM_SetClockSource(TIM3, LL_TIM_CLOCKSOURCE_INTERNAL);
LL_TIM_SetTriggerOutput(TIM3, LL_TIM_TRGO_RESET);
LL_TIM_DisableMasterSlaveMode(TIM3);
2024-07-21 06:00 AM
Hi, Tesla,
(Continue) - Looks like need to add some API call to start running the counter?
HAL has "HAL_TIM_Base_Start() ".
What is the function for LL?
. Please help, thanks,
Rong