-1

My board is the NUCLEO-H743ZI2

I configured TIM4,CH2 as PWM such that TIM4 output should be HI for half a second and LO for half a second. Here is the block.ioc clock and pin configuration enter image description here enter image description here enter image description here

I auto generated the code and tried to add my own to toggle the LED with the H/L of PWM. What I want to do is this:

if(timer_4 == HIGH) LED_state = !LED_state

Here is the actual code:

HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_ETH_Init();
  MX_USART3_UART_Init();
  MX_USB_OTG_FS_PCD_Init();
  MX_DAC1_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */

  HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);
  uint16_t timer_init_val = __HAL_TIM_GET_COUNTER(&htim4);
  uint16_t timer_poll;

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

      timer_poll = __HAL_TIM_GET_COUNTER(&htim4);
      if(timer_poll - timer_init_val >= 500) {
          HAL_GPIO_TogglePin(GPIOB,LD1_Pin);
      }



    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

I know that this most likely does not work. In fact. I was confused because replacing the >=500 with <=100 actually made it seem like it was working..but the LED just blinks at seemingly random intervals. I have tried to test if !timer{..} (timer reached 0) to toggle the LED but none of my methods have seemed to work.

Am I misunderstanding something about timers? Is there something super obvious I am missing? It does not seem like it would be difficult to blink an LED with a 1sec PWM

user P520
  • 317
  • 2
  • 10

1 Answers1

0

What you have written does the following:

  1. for 500 counts of the timer do nothing
  2. after that turn the LED repeatedly on and off (faster than the eye can see) until the timer wraps
  3. when the timer wraps (65.536 seconds?) goto (1).

You can't really do this with GPIO_TogglePin because you will call it many many times during the same value of the counter.

Try something like:

if (((timer_poll - timer_init_val) % 1000) < 500)
{
    HAL_GPIO_WritePin(GPIOB, LD1_Pin, 0);
}
else
{
    HAL_GPIO_WritePin(GPIOB, LD1_Pin, 1);
}

But this still isn't completely clean when the timer wraps. To sort that out you can adjust the period of the timer to be a multiple of the period of your sequence.

Tom V
  • 4,827
  • 2
  • 5
  • 22
  • This does work! What I dont understand however is why I should have to use this mod and subtraction. Didnt I set it up in the block.ioc so that timer 4 is either high or low with 50% duty, 1sec period PWM?..such that I can just write the LED state 1 whenever the timer 4 is high? – user P520 Mar 16 '21 at 15:56
  • You aren't using PWM at all! PWM is a hardware output direct from the the timer to a pin in alternate function mode. You are reading the timer in software and then outputting from software to a pin in GPIO mode. This is absolutely fine to do for something like an LED where the timing doesn't need nanosecond accuracy. It has the advantage that you can use any pin not just the one with the correct alternate function on it. – Tom V Mar 16 '21 at 21:36