I'm using a stm32F429ZGT6 with a 25MHz quartz and i have some difficulty with the speed measurement of my rotary encoder.
I can measure speed until around 35KHz but after the speed seem to reduce even though it is still increasing.
This show the number of ticks received in a step of time. The second one is just empty (not related).
Here is how I initialize my timer and the clock.
void MX_TIM1_Init(void)
{
TIM_Encoder_InitTypeDef sConfig;
TIM_MasterConfigTypeDef sMasterConfig;
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 0xFFFF;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
HAL_TIM_Encoder_Init(&htim1, &sConfig);
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig);
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
__PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 25;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);
}
Does anyone have any idea why i get this result?
Related
Please help advice.
I am fighting several days with option ADC.
I am using 2 channels ADC IN0 and IN1 on STM32L010RB microcontroler via HAL library.
If checking apart then everything are good but when I am checking together it I have all time the same problem: first channel rewrite data on second channel and I have the same data on IN0 and IN1 in terminal
Function for select IN0.
#include "main.h"
#include <stdio.h>
#include <string.h> //Library for work with string
/* USER CODE BEGIN Includes */
char Tx_Data[31] = {0};
volatile uint32_t Axis[2] = {0};
ADC_HandleTypeDef hadc;
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_ADC_Init(void);
void ADC_Select_CH0(void)
{
ADC_ChannelConfTypeDef sConfig_0 = {0};
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig_0.Channel = ADC_CHANNEL_0;
sConfig_0.Rank = 0;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig_0) != HAL_OK)
{
Error_Handler();
}
}
void ADC_Select_CH1(void)
{
ADC_ChannelConfTypeDef sConfig_1 = {0};
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig_1.Channel = ADC_CHANNEL_1;
sConfig_1.Rank = 1;
if (HAL_ADC_ConfigChannel(&hadc, &sConfig_1) != HAL_OK)
{
Error_Handler();
}
}
void ADC_Check_CH0(void)
{
HAL_ADC_Start(&hadc); // start ADC
HAL_ADC_PollForConversion(&hadc, 100);
Axis[0] = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop(&hadc);
}
void ADC_Check_CH1(void)
{
HAL_ADC_Start(&hadc); // start ADC
HAL_ADC_PollForConversion(&hadc, 100);
Axis[1] = HAL_ADC_GetValue(&hadc);
HAL_ADC_Stop(&hadc);
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_ADC_Init();
HAL_ADCEx_Calibration_Start(&hadc, ADC_SINGLE_ENDED); // simple channel
while(1)
{
/* USER CODE END WHILE */
ADC_Select_CH0();
ADC_Check_CH0();
ADC_Select_CH1();
ADC_Check_CH1();
sprintf(Tx_Data, "Axis X: %d;\nAxis Y: %d;\r\n\n\n", (int)Axis[0], (int)Axis[1]);
HAL_UART_Transmit(&huart2, (uint8_t*)Tx_Data, strlen(Tx_Data), 1000);
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_8;
RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
static void MX_ADC_Init(void)
{
hadc.Instance = ADC1;
hadc.Init.OversamplingMode = DISABLE;
hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc.Init.Resolution = ADC_RESOLUTION_12B;
hadc.Init.SamplingTime = ADC_SAMPLETIME_79CYCLES_5;
hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc.Init.ContinuousConvMode = ENABLE;
hadc.Init.DiscontinuousConvMode = DISABLE;
hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc.Init.DMAContinuousRequests = DISABLE;
hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc.Init.LowPowerAutoWait = DISABLE;
hadc.Init.LowPowerFrequencyMode = DISABLE;
hadc.Init.LowPowerAutoPowerOff = DISABLE;
if (HAL_ADC_Init(&hadc) != HAL_OK)
{
Error_Handler();
}
}
static void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 9600;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
HAL_GPIO_WritePin(Green_LED_GPIO_Port, Green_LED_Pin, GPIO_PIN_RESET);
GPIO_InitStruct.Pin = SW_Button_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(SW_Button_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = Green_LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(Green_LED_GPIO_Port, &GPIO_InitStruct);
}
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */
enter image description here
I am using STM32F401RCT6 chip, and I am trying to do some controlled PWM outputs. I am using TIM1, 2, 3, and 11 for PWM.
The thing is, when I set the same period for timer 1 as for any other timer, the period is the same length but the pulse is different. For example, TIM1 is pulse 6.9us and for others 82.4us when using period 4999.
The picture shows that the period is the same.
The next picture shows the difference in the pulse length.
When I change the pulse from 10 to 1000 the pulse for TIM1 is 720us and for TIM2 794us.
When I saw the difference, the first thing which comes to my mind was that the timers have a different frequency, but the thing is that it would have different frequency of PWM pulse too, but it is not the case.
Can anyone say, what can cause the pulse length to be shorter for timer 1?
My settings are the following:
void MX_TIM11_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim11.Instance = TIM11;
htim11.Init.Prescaler = HAL_RCC_GetPCLK2Freq()/124999;
htim11.Init.CounterMode = TIM_COUNTERMODE_UP;
htim11.Init.Period = 0;
htim11.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim11.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim11) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim11) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim11, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim11);
}
void MX_TIM2_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = HAL_RCC_GetPCLK1Freq()/124999;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 0;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim2);
}
void MX_TIM3_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = HAL_RCC_GetPCLK1Freq()/124999;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 0;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
HAL_TIM_MspPostInit(&htim3);
}
void MX_TIM1_Init(void)
{
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = HAL_RCC_GetPCLK2Freq()/124999;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 0;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_ENABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
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_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != 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();
}
HAL_TIM_MspPostInit(&htim1);
}
I have following function to set parameters for PWM and for starting it:
void setPWM(TIM_HandleTypeDef timer, uint32_t channel, uint16_t period)
{
// stop generation of PWM
HAL_TIM_PWM_Stop(&timer, channel);
TIM_OC_InitTypeDef sConfigOC;
// set the period duration
timer.Init.Period = period;
// re-initialize with new period value
HAL_TIM_PWM_Init(&timer);
sConfigOC.OCMode = TIM_OCMODE_PWM1;
// set the pulse duration
sConfigOC.Pulse = 10;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&timer, &sConfigOC, channel);
// start PWM generation
HAL_TIM_PWM_Start(&timer, channel);
}
UPDATE:
I need to change the period during the run, and it seems like if I call the setPWM function more then once, the problem occurs. The first call appears to be behaving as it should. The weird thing is that I call it the same way for all of the timers but only one will lose the length of the pulse. But right now I have run out of ideas about what to try to find the core of my problem.
Any Idea what I can try to find what cause it?
Thank you,
Hana
I have now all timers are working the same way. I am not sure why it was reacting differently on timer 1, but if I do not call setPWM() again and instead I just set the ARR register while running, it behaves the same for all timers.
timer.Instance->ARR = period;
I am using STM32L476 Nucleo board and STM32CubeMX. I want to use Output Compare channel 1 for timeout of 2 ms. I have configured the timer, but the timer is not giving interrupts for Output Compare. I am getting interrupts for the period I gave to the timer, but not for output compare.
Here is my timer configuration:
static void MX_TIM1_Init(void)
{
/* USER CODE BEGIN TIM1_Init 0 */
/* USER CODE END TIM1_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_SlaveConfigTypeDef sSlaveConfig = {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 = TIMER1_PRESCALER_VAL;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = TIMER_PERIOD;
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();
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_DISABLE;
sSlaveConfig.InputTrigger = TIM_TS_ITR0;
if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC1REF;
sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_ACTIVE;
sConfigOC.Pulse = 1000 * TIMER_OC_1_VAL;
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_1) != 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.BreakFilter = 0;
sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
sBreakDeadTimeConfig.Break2Filter = 0;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM1_Init 2 */
HAL_TIM_OC_Start_IT(&htim1,TIM_IT_CC1);
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
}
I tried changing the sConfigOC.Pulse value but I don't see the expected behavior.
Do you check for the right interrupt flag in the interrupt handler?
Also keep in mind that you have to clear the flag right away.
My IRQHandler looks like this, if this is any help for you.
void TIM3_IRQHandler(void) {
if(LL_TIM_IsActiveFlag_CC1(TIM3) == 1) {
LL_TIM_ClearFlag_CC1(TIM3);
TimerCaptureCompare_Callback();
}
}
Edit:
OK as it seems, the HAL_TIM_OC_DelayElapsedCallback interrupt is only fired when the timer overflows (i. e., resets).
This means that you have to enable the overflow interrupt, as the HAL_TIM_OC_Start_IT only enables the capture/compare interrupt.
You only need to enable it before enabling the timer.
__HAL_TIM_ENABLE_IT(&tim3, TIM_IT_UPDATE );
Try to replace "TIM_IT_CC1" with "TIM_CHANNEL_1".
First, you have to initialize the output pin before starting the timer like that:
/* USER CODE END TIM1_Init 2 */
HAL_TIM_MspPostInit(&htim1);
/* USER CODE BEGIN TIM1_Init 2 */
HAL_TIM_OC_Start_IT(&htim1,TIM_IT_CC1);
Second, you have to start the Output timer
HAL_TIM_OC_Start_IT( &htim1, TIM_CHANNEL_1 );
HAL_TIM_Base_Start_IT( &htim1 );
Yyour output pin are enable like that:
(this code is for Stm32F4xx)
GPIO_InitStruct.Pin = GPIO_PIN_9; // channel 1
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
I am not sure you need the BREAK code. Have a look 17.3.12 Using the break function in the Reference Manual
I am using a STM32F401RE board and I want a timer interrupt to happen every X seconds (let's say 60 seconds).
The interrupt callback works. The problem is the interrupt does not happen every 60 seconds (it does every 34 seconds). I have tried different values for prescaler and period but nothing I try is working as I want.
I am using the functions generated by CubeMX in another project:
main.c
TIM_HandleTypeDef htim10;
int main(void)
{
HAL_Init();
SystemClock_Config();
// Some other code
MX_TIM10_Init();
HAL_TIM_Base_Start_IT(&htim10);
while (1)
{
}
}
static void MX_TIM10_Init(void)
{
htim10.Instance = TIM10;
htim10.Init.Prescaler = 35999;
htim10.Init.CounterMode = TIM_COUNTERMODE_UP;
htim10.Init.Period = 60000;
htim10.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
if (HAL_TIM_Base_Init(&htim10) != HAL_OK)
{
Error_Handler();
}
}
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance==TIM10)
{
printf("ABCDEFG\n\r");
}
}
void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = 16;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 16;
RCC_OscInitStruct.PLL.PLLN = 288;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
RCC_OscInitStruct.PLL.PLLQ = 6;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
__HAL_RCC_SYSCFG_CLK_ENABLE();
}
stm32f4xx_hal_msp.c
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM10)
{
__HAL_RCC_TIM10_CLK_ENABLE();
HAL_NVIC_SetPriority(TIM1_UP_TIM10_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn);
}
}
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM10)
{
__HAL_RCC_TIM10_CLK_DISABLE();
HAL_NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn);
}
}
stm32f4xx_it.c
void TIM1_UP_TIM10_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim10);
}
Can anyone explain me what I am doing wrong? How do I configure the timer parameters to achieve the period that I want?
Thank you in advance!
can you capture your CubeMX's Clock Configuration screen of your project, it make me diagnose your issue easier!
EDIT 1: I check your code, the Timer 10 is run by APB2 clock source so your timer 10's clock is running twice times faster. You should config your code like this:
static void MX_TIM10_Init(void)
{
htim10.Instance = TIM10;
htim10.Init.Prescaler = 35999;
htim10.Init.CounterMode = TIM_COUNTERMODE_UP;
htim10.Init.Period = 60000;
htim10.Init.ClockDivision = TIM_CLOCKDIVISION_DIV2; //TIM_CLOCKDIVISION_DIV1
if (HAL_TIM_Base_Init(&htim10) != HAL_OK)
{
Error_Handler();
}
}
Frankie
add the function below called MX_NVIC_Init(); to the main() function
static void MX_NVIC_Init(void)
{
HAL_NVIC_SetPriority(TIM1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(TIM10_IRQn);
}
I can't seem to get TIM8 PWM to work with anything that I try. I've tried all timers and they all work with my PWM driver, except TIM8. All timers are generated with CubeMx and there are no conflicts.
Here are some snipits of the code. The driver is fairly large so I cut out parts of it:
Pin config:
//Tim 8 Chan 1 IN1A
GPIO_InitStructure.Pin = GPIO_PIN_6;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
//Tim 8 Chan 2 IN1B
GPIO_InitStructure.Pin = GPIO_PIN_7;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
//Tim 8 Chan 3 IN2A
GPIO_InitStructure.Pin = GPIO_PIN_8;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
//Tim 8 Chan 4 IN2B
GPIO_InitStructure.Pin = GPIO_PIN_9;
GPIO_InitStructure.Mode = GPIO_MODE_AF_PP;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;
GPIO_InitStructure.Alternate = GPIO_AF3_TIM8;
HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
Timer setup:
static PWM_ERC_T Timer8_Init(PWM_HANDLE_T *pwmHandle_, uint16_t prescaler_, uint16_t period_, uint16_t pulse_)
{
PWM_ERC_T erc = PWM_ERC_NO_ERROR;
__TIM8_CLK_ENABLE();
pwmHandle_->TimerHandle.Instance = TIM8;
TIM_MasterConfigTypeDef masterConfig;
TIM_BreakDeadTimeConfigTypeDef breakDeadTimeConfig;
TIM_OC_InitTypeDef configOC;
pwmHandle_->TimerHandle.Init.Prescaler = prescaler_;
pwmHandle_->TimerHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
pwmHandle_->TimerHandle.Init.Period = period_;
pwmHandle_->TimerHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
pwmHandle_->TimerHandle.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&pwmHandle_->TimerHandle);
masterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
masterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
masterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&pwmHandle_->TimerHandle, &masterConfig);
breakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
breakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
breakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
breakDeadTimeConfig.DeadTime = 0;
breakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
breakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
breakDeadTimeConfig.BreakFilter = 0;
breakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
breakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
breakDeadTimeConfig.Break2Filter = 0;
breakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
HAL_TIMEx_ConfigBreakDeadTime(&pwmHandle_->TimerHandle, &breakDeadTimeConfig);
configOC.OCMode = TIM_OCMODE_PWM1;
configOC.Pulse = pulse_;
configOC.OCPolarity = TIM_OCPOLARITY_HIGH;
configOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
configOC.OCFastMode = TIM_OCFAST_DISABLE;
configOC.OCIdleState = TIM_OCIDLESTATE_RESET;
configOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if(pwmHandle_->Init.Channels & PWM_CHANNEL_1)
{
HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_1);
}
if(pwmHandle_->Init.Channels & PWM_CHANNEL_2)
{
HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_2);
}
if(pwmHandle_->Init.Channels & PWM_CHANNEL_3)
{
HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_3);
}
if(pwmHandle_->Init.Channels & PWM_CHANNEL_4)
{
HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_4);
}
I assure you each of the channels are being enabled and the prescaller/period and period are being calculated correctly.
Any thoughts? This is the only timer that has issues.
Solution:
Finally figured out what was wrong.
HAL_TIM_OC_Init(&pwmHandle_->TimerHandle);
has to be added for TIM8 for some reason... not sure why and
HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_1);
needs to be used instead of
HAL_TIM_PWM_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_1);
Correct Timer Setup:
static PWM_ERC_T Timer8_Init(PWM_HANDLE_T *pwmHandle_, uint16_t prescaler_, uint16_t period_, uint16_t pulse_)
{
PWM_ERC_T erc = PWM_ERC_NO_ERROR;
TIM_MasterConfigTypeDef masterConfig;
TIM_BreakDeadTimeConfigTypeDef breakDeadTimeConfig;
TIM_OC_InitTypeDef configOC;
pwmHandle_->TimerHandle.Init.Prescaler = prescaler_;
pwmHandle_->TimerHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
pwmHandle_->TimerHandle.Init.Period = period_;
pwmHandle_->TimerHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
pwmHandle_->TimerHandle.Init.RepetitionCounter = 0;
HAL_TIM_OC_Init(&pwmHandle_->TimerHandle);
HAL_TIM_PWM_Init(&pwmHandle_->TimerHandle);
masterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
masterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
masterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&pwmHandle_->TimerHandle, &masterConfig);
breakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
breakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
breakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
breakDeadTimeConfig.DeadTime = 0;
breakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
breakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
breakDeadTimeConfig.BreakFilter = 0;
breakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
breakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
breakDeadTimeConfig.Break2Filter = 0;
breakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
HAL_TIMEx_ConfigBreakDeadTime(&pwmHandle_->TimerHandle, &breakDeadTimeConfig);
configOC.OCMode = TIM_OCMODE_PWM1;
configOC.Pulse = pulse_;
configOC.OCPolarity = TIM_OCPOLARITY_HIGH;
configOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
configOC.OCFastMode = TIM_OCFAST_DISABLE;
configOC.OCIdleState = TIM_OCIDLESTATE_RESET;
configOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if(pwmHandle_->Init.Channels & PWM_CHANNEL_1)
{
HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_1);
}
if(pwmHandle_->Init.Channels & PWM_CHANNEL_2)
{
HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_2);
}
if(pwmHandle_->Init.Channels & PWM_CHANNEL_3)
{
HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_3);
}
if(pwmHandle_->Init.Channels & PWM_CHANNEL_4)
{
HAL_TIM_OC_ConfigChannel(&pwmHandle_->TimerHandle, &configOC, TIM_CHANNEL_4);
}
return erc;
}
TIM1 and TIM8 have a bit MOE (Main Output Enable) in the TIMx_BDTR register that is unique to these timers. The PWM is not output unless that bit is set to 1.