Home > OS >  Avoid Input Latency while reading input from keyboard loop
Avoid Input Latency while reading input from keyboard loop

Time:07-25

I'm just starting win STM32 and am trying to write some code which tries to accept input from user keypress, and vary the blink-rate of 2 LEDs or blink them alternatively, or at the same time. So, I have 3 Keys(2 keys each for inc/dec, and one key for mode), and 2 LEDs. The loop section looks something like this:

  /* USER CODE BEGIN WHILE */
  const uint32_t step = 50u;
  const uint32_t max_interval = 500u;

  uint32_t interval = max_interval;
  short mode = 0;
  while (1)
  {
    volatile GPIO_PinState wakeup = HAL_GPIO_ReadPin(WAKEUP_GPIO_Port, WAKEUP_Pin);
    mode = (wakeup == GPIO_PIN_RESET? 0: 1);

    if(mode == 1) {
        HAL_GPIO_WritePin(LED2_GPIO_Port, LED2_Pin, GPIO_PIN_RESET);
    }

    HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
    HAL_GPIO_TogglePin(LED2_GPIO_Port, LED3_Pin);

    volatile GPIO_PinState key0 = HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin);
    volatile GPIO_PinState key1 = HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin);
    if(key0 == GPIO_PIN_RESET)
        interval -= (interval==step? 0: step);

    if(key1 == GPIO_PIN_RESET)
        interval  = (interval==max_interval? 0: step);

    HAL_Delay(interval);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

Now, depending on the HAL_Delay(interval), the loop would get a chance to check for key-input, whose purpose is to control the blink rate. Is there some way, I can untie this latency for key-input? The microcontroller in question is STM32F407VET6, and I'm using CubeIDE. It would be nice to have a single-threaded solution.

CodePudding user response:

Some delay for key input is unavoidable, unless you have some hardware-debounced keys. Normally, when hitting a key, the transition is not a single edge, but some burst of level changes until the mechanics settle. One way to do debouncing would be to have a periodic interval timer (e.g. at 1khz rate) and you check each time the level of a key. If it is high, you count a counter up. If it is low, you count a counter down and then you have 2 thresholds (hysteresis) in the count values, when you consider it a button down or button up transition. Since all that works in the interrupt, you could then push the key event into a FIFO (queue) and in your "main thread", you can pull the events at convenient occasions.

If there is also a programmable timer on your hardware, you could use that to toggle the output pins for the LED and your main loop would then simply be along the lines:

void mainloop() {
  while (true) {
    KeyEvent_t key;
    nextKeyEvent(&key);
    switch (key) {
       case BUTTON1_DOWN: 
         reduceBlinkRate();
         break;
       case BUTTON2_DOWN:
         increaseBlinkRate();
         break;
       default:
         // skillful doing nothing (e.g. to save power)
         break;
    }
  }
}

  • Related