cancel
Showing results for 
Search instead for 
Did you mean: 

Stm32F411 Output Compare Mode Does not Work as Expected

akoluacik
Senior

I implemented a code of output compare mode for TIM3. However, it does not work as I expected.

ky017ledmodule_config.h

#ifndef KY017LEDMODULE_CONFIG_H_
#define KY017LEDMODULE_CONFIG_H_
 
#include <stddef.h>
#include "stm32f4xx_hal.h"
 
#define RED_LED 	GPIO_PIN_0
#define GREEN_LED 	GPIO_PIN_1
#define BLUE_LED 	GPIO_PIN_4
 
 
void KY017_Module_Init(void);
void KY017_Module_Led_Blinker(uint16_t Pin);
void KY017_Module_Toggle_Led(GPIO_TypeDef *Port, uint16_t Pin);
#endif /* KY017LEDMODULE_CONFIG_H_ */

tim_oc_config.h

/*
 * tim_ic_config.h
 *
 *  Created on: 2 Mar 2023
 *      Author: anil
 */
 
 
#ifndef TIM_IC_CONFIG
#define TIM_IC_CONFIG
 
#define		__HAL_RCC_TIMx_CLK_ENABLE		__HAL_RCC_TIM3_CLK_ENABLE()
//#define 	TIMx					TIM3
//#define		TIMx				TIM3
 
void tim_oc_init(void);
void tim_oc_start(void);
void tim_oc_start_it(void);
 
#endif

tim_oc_config.c

#include "stm32f4xx_hal.h"
#include "tim_oc_config.h"
#include "ky017ledmodule_config.h"
 
TIM_HandleTypeDef htim3;
 
void tim_oc_init(void)
{
	__HAL_RCC_TIMx_CLK_ENABLE;
 
	htim3.Instance = TIM3;
	htim3.Init.Prescaler = 16000 - 1;
	htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
	htim3.Init.Period = 1000;
	htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 
	HAL_TIM_Base_Init(&htim3);
 
	HAL_TIM_OC_Init(&htim3);
 
	TIM_OC_InitTypeDef sConfig = {0};
	sConfig.OCMode = TIM_OCMODE_TOGGLE;
	sConfig.Pulse = 500;
	sConfig.OCPolarity = TIM_OCPOLARITY_HIGH;
	HAL_TIM_OC_ConfigChannel(&htim3, &sConfig, TIM_CHANNEL_1);
}
 
void tim_oc_start(void)
{
	HAL_TIM_OC_Start(&htim3, TIM_CHANNEL_1);
}

ky017ledmodule_config.c

#include "ky017ledmodule_config.h"
void KY017_Module_Init(void)
{
	__HAL_RCC_GPIOB_CLK_ENABLE();
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_PULLDOWN;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
	GPIO_InitStruct.Pin = BLUE_LED;
	GPIO_InitStruct.Alternate = GPIO_AF2_TIM3;
	HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
 
void KY017_Module_Led_Blinker(uint16_t Pin)
{
 
	for(uint16_t pin = 0; pin < 3; ++pin)
	{
		if(KY017_LED_PINS[pin] == Pin)
			HAL_GPIO_WritePin(GPIOA, KY017_LED_PINS[pin], SET);
		else
			HAL_GPIO_WritePin(GPIOA, KY017_LED_PINS[pin], RESET);
	}
}
 
void KY017_Module_Toggle_Led(GPIO_TypeDef * Port, uint16_t Pin)
{
	HAL_GPIO_TogglePin(Port, Pin);
}

main.c

#include <tim_oc_config.h>
#include "stm32f4xx_hal.h"
#include "ky017ledmodule_config.h"
 
uint32_t counter;
extern TIM_HandleTypeDef htim3;
 
int main(int argc, char **argv) {
	KY017_Module_Init();
	tim_oc_init();
	tim_oc_start();
	while(1)
	{
//		counter = __HAL_TIM_GET_COUNTER(&htim3);
//		if(counter == 750)
//		{
//			HAL_GPIO_TogglePin(GPIOB, BLUE_LED);
//		}
	}
}

I connect everything correctly, I am saying this because I test my code by putting a variable named counter whose type is uint32_t in main code and get the counter value with __HAL_TIM_GET_COUNTER(&htim3) macro(of course I defined htim3 in main code with extern keyword) and I could blink the led with an if condition in while loop. But this was not my intention. I want my code to toggle the led as my configuration. What is the problem?

Not: I am using HAL API but not cubemx tool.I am importing the related libraries and works fine. I mean I don't get any error like undefined refrence or something else.

1 ACCEPTED SOLUTION

Accepted Solutions
akoluacik
Senior

OK, I found my mistake.

Since I forgot to re-implement SysTick_Handler function so it leads to some inappropriate behaviour in my code.

Furthermore, if your code get stucked in .InfiniteLoop branch in .s file while you are debugging, then this may be a problem for your case. So double check you call HAL_Init function, which just initialize the SysTick Timer and configure its interrupts adjustmentsi just before using any other HAL functions and re-implement SysTick_Handler function in the main code.

Your SysTick_Handler function should look like:

void  SysTick_Handler(void)
{
	HAL_IncTick();
}

View solution in original post

8 REPLIES 8
gbm
Lead II

Why don't you simply use timer PWM output?

Honestly, I don't understand how your code is supposed to work. It sets the timer, then what? How do you want to toggle the outputs?

As far as I know, output compare mode keeps a value in timer registers and when counter value matches with the value in the register, then the pin generates an output according to the behaviour the user specify.

0693W00000aIBjlQAG.pngI am learning these concepts so that's why I am using output compare. I do not need pwm signal for now.

I hope everything now is correct and dont misunderstand something about these concepts. I looked at reference manual and knew these modes of timers. I then wanted to use it now am trying to implement.

RED_LED is PB0, and that is TIM3_CH3. You are setting up and enabling TIM3_CH1.

JW

Sorry sir, but it still doesn't work.

gbm
Lead II

You didn't write a word about pin configurations. Do you set the pins as timer outputs or you want to control them with software from timer interrupt service routine?

Also, I still don't understand why you don't use PWM mode for LED control. It's the only natural choice here.

Read out and check/post content of TIM and relevant GPIO registers.

JW

Sory for that, KY017_Module_Init function does the pin configuration, if I didn't do anything wrong.

Actually I could do this with ISR but I dont wanna do with that way if I can do this without any line of code, and I saw that there are lots of video on YouTube that they toggle LED with output compare mode.

Because as I said, this is not a big project. I made this up my mind to learn timer modes. I am planning to work with PWM later to learn that as well. But as far as I know, PWM is used for generating analog signal according to Ton/T, right? Why should I use PWM to toggle an LED? Maybe I miss a point about PWM and I am sure you are completely right for this issue and please let me know if so that I can try this way also later.

akoluacik
Senior

OK, I found my mistake.

Since I forgot to re-implement SysTick_Handler function so it leads to some inappropriate behaviour in my code.

Furthermore, if your code get stucked in .InfiniteLoop branch in .s file while you are debugging, then this may be a problem for your case. So double check you call HAL_Init function, which just initialize the SysTick Timer and configure its interrupts adjustmentsi just before using any other HAL functions and re-implement SysTick_Handler function in the main code.

Your SysTick_Handler function should look like:

void  SysTick_Handler(void)
{
	HAL_IncTick();
}