Ideal Hardware Timer Setup Routine

cfunctionmicrocontrollertimer

Imagine you were trying to write a C routine for an 8bit microcontroller that converted a desired timespan (be it seconds, milliseconds, hertz, etc). to the corresponding hardware timer preload value (taking into account the clock source and frequency of the timer). The goal is to make the function as easy as possible to use, with as few arguments as possible. What would this function look like?

Would you pass in a uint32_t representing the desired hertz of the timer (0 = 0Hz, 1000 = 1kHz, etc.):

void set_timer(uint32_t hz);

Would you prefer using a uint16_t representing kHz instead (0 = 0Hz, 1 = 1KHz, 10 = 10Khz)?

void set_timer(uint16_t khz);

Or would a 32bit fixed point argument be more desirable (to be able to represent fraction of hertz)?

void set_timer(q15_16_t hz);

Or would this fixed point value represent seconds instead of Hz?

void set_timer(q15_16_t sec);

Or would you use a 16bit fixed point instead of a 32bit fixed point.

Or would you even dare want to use a floating point? Or what about a half-precision float?

What do you think?

Best Answer

First I would suggest using time instead of frequency, since the latter implies that the timer is of a continuous kind. The user is often interested in a certain "one-shot" delay, when waiting for some sort of hardware to become available.

Second, uint32_t is a big NO on 8-bit microcontrollers. As soon as you use 32-bit numbers, every 8-bitter on the market will create a flood of inefficient machine code, likely with internal subroutine calls. 16 bit numbers are bad enough. Though of course, there are cases where you need high resolution accuracy and then you might have to reluctantly use large integer types.

In this case, I very much doubt that your 8-bit MCU has a 32-bit timer peripheral. De facto standard for 8-bitters is to have 16-bit hardware timers. There is no point of specifying a resolution that doesn't correspond with the hardware.

Using floating point is even worse: if you ever find yourself needing floating point accuracy on a 8-bit MCU, you most likely picked the wrong MCU for your project to begin with. (The cost argument of 8-bit vs 32-bit has been obsolete forever.)

Based on the above argument, I would suggest something like:

void set_timer (uint16_t ms);

where ms is the time in miliseconds.

The ideal case is however to calculate the needed timing in the pre-processor, then show that into a constant, which is then directly read into the timer hardware registers.