Close

Millis Function

A project log for Electronic Load 3.3V-16V 1A

Electronic load that supports 3.3V-16V at 1A of current. Equipped with keypad, LCD, rotary encoder, STM32 Microcontroller and more!

schwarzrmsuschwarzrmsu 01/13/2020 at 02:380 Comments

In order to avoid large pockets of delay, I will need to generate a function that will allow me to execute specific actions only after a certain amount of time has expired.  In arduino, this can be accomplished using the millis() function.  Since I am using the STM32 micro-controller and the STM32 IDE, I do not have the luxury of using this library function.  Therefore I have created my own millis function.  Probably not as good, but seems to be working pretty well. 

The first step was to enable a new timer that counts up at a rate of 100kHz (In other words it counts to 100 every 1ms):

static void MX_TIM7_Init(void)
{
  htim7.Instance = TIM7;
  htim7.Init.Prescaler = 479; //479
  htim7.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim7.Init.Period = 65535;
  htim7.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
  {
    Error_Handler();
  }
}

This function configures a timer to count up to 100 every 1ms.  The reason I have slowed down this timer is to prevent the 16 bit unsigned integer from over flowing too quickly.  This timer can overflow after following duration:

Once all of my code is complete, I can start to bench mark the amount of time it takes to execute the entire stack.  With that information I can fine tune my timer frequency, but for now I will conservatively set the frequency to 100kHz.

Now that I have a timer that counts to 100 every 1ms, I have created a function that counts how many times this happens:

uint32_t millis(void)
{
    uint16_t CURRENT_TIMER7_COUNT = __HAL_TIM_GET_COUNTER(&htim7);

    uint16_t currentMillis = 0;
    if(CURRENT_TIMER7_COUNT>=100)
    {
        currentMillis = CURRENT_TIMER7_COUNT/100;
        systemMillis = systemMillis + currentMillis;
        __HAL_TIM_SET_COUNTER (&htim7, 0);
    }
    return systemMillis;
}

This function checks the current count at the time this function is called.  If the count is larger than 100 it increases a variable called systemMillis by 1.  systemMillis is the current number of milliseconds the application has been running.  If the counter is increased it resets the counter to prevent it from overflowing.  systemMillis is a 32 bit unsigned integer which will take a long time to over flow.  The systemMillis variable will overflow after this specified amount of time:

This is an acceptable amount of time to run this particular application with requiring a reset.  Once this timer expires I plan on resetting all the Millis related variables which might cause a slight timing mishap, but should not be noticeable to the user if the user has left application running longer than 49.71 days.

I then tested this function within main while(1) by blinking an LED on and off and probing the LED DO port:

mainMillis = millis();

if (mainMillis - turnOnRedLedMillis >= 1000)
{
    HAL_GPIO_TogglePin(DEBUG_RGB_LED_R_DO_PORT, DEBUG_RGB_LED_R_DO_PIN);
    turnOnRedLedMillis = mainMillis;
}

 1s:

100ms:

10ms:

5ms:

1ms:

These results are adequate for my needs.  This new function will help me execute portions of the code only when they really need to be execute.  I think this will be most useful for low priority portions of the code being executed less then portions that are higher priority.

There are many uses for this function and you will be sure to see it future updates regarding SW.

Hope you found this interesting, and if you have any ideas that would work better please let me know.  Thank you for reading.

Discussions