Jump to content


Featured Entries

  • N9WXU

    Initializing Strings in C

    By N9WXU

    Embedded applications are hard for a large number of reasons, but one of the main issues is memory.  Today I want to talk about how our C variables get initialized and a few assumptions we make as we use C to write embedded software. Let us take a few simple declarations such as we might make every day. char *string1 = "string1"; const char *string2 = "string2"; char const *string3 = "string3"; char * const string4 = "string4"; char const * const string5 = "string5";   In C99 th
  • N9WXU

    Tokenizing Keywords - Part 1

    By N9WXU

    This is the first of a 5 part article where I will explore some different ways to tokenize keywords.  This is a simple and common task that seems to crop up when you least expect it.  We have all probably done some variation of the brute force approach in this first posting, but the posts that follow should prove interesting.  Here is the sequence: Part 1 : STRCMP Brute Force and the framework Part 2 : IF-ELSE for speed Part 3 : Automating the IF-ELSE for maintenance Part 4 :
  • Orunmila

    How long is a nanosecond?

    By Orunmila

    Exactly how long is a nanosecond? This Lore blog is all about standing on the shoulders of giants. Back in February 1944 IBM shipped the Harvard Mark 1 to Harvard University. It looked like this: The Mark I was a remarkable machine at the time, it could perform addition in 1 cycle (which took roughly 0.3 seconds) and multiplication in 20 cycles or 6 seconds. Calculating sin(x)  would run up to 60 seconds (1 minute). The team that ran this Electromechanical computer had o
  • Orunmila

    Epigrams on Programming

    By Orunmila

    Epigrams on Programming Alan J. Perlis Yale University This text has been published in SIGPLAN Notices Vol. 17, No. 9, September 1982, pages 7 - 13.  The phenomena surrounding computers are diverse and yield a surprisingly rich base for launching metaphors at individual and group activities. Conversely, classical human endeavors provide an inexhaustible source of metaphor for those of us who are in labor within computation. Such relationships between society and device are no
  • Orunmila

    The Ballmer Peak

    By Orunmila

    If you are going to be writing any code you can probably use all the help you can get, and in that line you better be aware of the "Ballmer Peak". Legend has it that drinking alcohol impairs your ability to write code, BUT there is a curious peak somewhere in the vicinity of a 0.14 BAC where programmers attain almost super-human programming skill. The XKCD below tries to explain the finer nuances. But seriously many studies have shown that there is some truth to this in the sense that

Our community blogs

  1. Here I am on a clear cool evening, by the fire outside with my laptop.  Tonight I will talk about a new peripheral, the timer/counter.  Periodically I will be interrupted to put another log on my fire, but it should not slow me down too much.

    Timers and counters are almost the same peripheral with only the difference of what is causing the counter to count.  If the counter is incrementing from a clock source, it becomes a timer because each count registers the passage of a precise unit of time.  If the counter is incrementing from an unknown signal (perhaps not even a regular signal), it is simply a counter.  Clearly, the difference between these is a matter of the use-case and not a matter of design.  Through there are some technical details related to clocking any peripheral from an external "unknown" clock that is not synchronized with the clocks inside the microcontroller.  We will happy ignore those details because the designers have done a good job of sorting them out.

    Let us take a peek at a very simple timer on the PIC16F18446.  Turn to page 348 of your PIC16F18446 data sheet and take a look at figure 25-1.  (shown below)


    This is the basic anatomy of a pretty vanilla timer.  Of course most timers have many more features so this article is simply an introduction.  On the left side of this image there are a number of clock sources entering a symbol that represents a multiplexer.  A multiplexer is simply a device that can select one input and pass it to its output.  The T0CS<2:0> signal below the multiplexer is shorthand for a 3-bit signal named T0CS.  The slash 3 also indicates that that is a 3-bit signal.  Each of the possible 3-bit codes is inside the multiplexer next to one of the inputs.  This indicates the input you will select if you apply that code on the signal T0CS.  Pretty simple.  The inputs are from top to bottom (ignoring the reserved ones) SOSC (Secondary Oscillator), LFINTOSC (Low Frequency Internal Oscillator), HFINTOSC (High Frequency Internal Oscillator) Fosc/4 (The CPU Instruction Clock) an input pin (T0CKI) inverted or not-inverted.

    Let us cover each section of this peripheral in a little more detail.  Of course you should go to the data sheet to read all the information.


    The secondary oscillator is a second crystal oscillator on 2 I/O pins.  A crystal oscillator is a type of clock that uses a piece of quartz crystal to produce a very accurate frequency.  The secondary oscillator is designed to operate at 32.768kHz which by some coincidence is 2^15 counts per second.  This makes keeping accurate track of seconds very easy and very low power.  You could configure the hardware to wake up the CPU every second and spend most of your time in a low power sleep mode.


    There are two internal oscillator in the PIC16F18446.  The LFINTOSC is approximately 31kHz and is intended for low power low speed operation but not very accurate timing.  The HFINTOSC is adjustable from 1-32MHz and is better than 5% accurate so it is often sufficient for most applications.  Because these two oscillators are directly available to the timer, the CPU can be operating at a completely different frequency allowing high resolution timing of some events, while running the CPU at a completely different frequency.


    This option is the simplest option to select because most of the math you are doing for other peripherals is already at this frequency.  If you are porting software for a previous PIC16 MCU, the timer may already be assumed to be at this frequency.  Due to historical reasons, a PIC16 is often clocked at 4MHz.  This makes the instruction clock 1MHz and each timer tick is 1us.  Having a 1us tick makes many timing calculations trivial.  If you were clocking at 32MHz, each tick would be 31ns which is much smaller but does not divide as nicely into base 10 values.


    This option allows your system to measure time based upon an external clock.  You might connect the timing wheel of an engine to this input pin and compute the RPM with a separate timer.  


    After the input multiplexer, there is an input pre-scaler.  The goal of the pre-scaler is to reduce the input clock frequency to a slower frequency that may be more suitable for the application.  The most prescallers are implemented as a chain of 'T' flip-flops.  A T flip-flop simply changes its output (high to low or low to high) on each rising edge of an input signal.  That makes a T Flip-Flop a divide by 2 circuit for a clock.  If you have a chain of these and you use a multiplexer to decide which T flip flop to listen to, you get a very simple divider that can divide by some power of 2.  i.e. 2, 4, 8, 16... with each frequency 1/2 of the previous one.  


    The synchronizer ensures that input pulses that are NOT sourced by an oscillator related to FOSC are synchronized to FOSC.  This synchronization ensures reliable pulses for counting or for any peripherals that are attached to the counter.  However, synchronization requires the FOSC/4 clock source to be operating and that condition is not true in when the CPU is saving power in sleep.  If you are building an alarm clock that must run on a tiny battery, you will want the timer to operate while the CPU is sleeping and to produce a wakeup interrupt at appropriate intervals.  To do this, you disable synchronization.  Once the CPU has been awakened, it is a good idea to activate synchronization or to avoid interacting with the counter while it is running.

    TMR0 Body

    The TMR0 body used to be a simple counter, but in more recent years it has gained 2 options.  Either, the timer can be a 16-bit counter, or it can be an 8-bit counter with an 8-bit compare.  The 8-bit compare allows the timer to be reset to zero on any 8-bit value.  The 16-bit counter allows it to count for a longer period of time before an overflow.  The output from the TMR0 body depends upon the module.  In the 8-bit compare mode, the output will be set each time there is a compare match.  In the 16-bit mode, the output will be set each time the counter rolls from 0xFFFF to 0x0000.


    The output from the core can be directed to other peripherals such as the CLC's, it can also be sent through a postscaler for further division and then create an interrupt or toggle an output on an I/O pin.  The postscaler is different than the prescaler because it is not limited to powers of two.  It is a counting divider and it can divide by any value between 1 and 16.  We shall use that feature in the example.

    Using the Timer

    Timers can be used for a great number of things but one common thing is to produce a precise timing interval that does not depend upon your code.  For instance,  2 lessons ago, we generated a PWM signal.  The one way to do this was to set and clear the GPIO pin every so many instruction cycles.  Unfortunately, as we added code to execute the PWM would get slower and slower.  Additionally, it could get less reliable because the program could take different paths through the code.  Using the PWM peripheral was the perfect solution, but another solution would be to use a timer.  For instance, you could configure the timer to set the output after an interval.  After that interval had elapsed, you could set a different interval to clear the output.  By switching back and forth between the set interval and the clear interval, you would get a PWM output.  Still more work than the PWM peripheral, but MUCH better than the pure software approach.

    For this exercise we will use the timer to force our main loop to execute at a fixed time interval.  We will instrument this loop and show that even as we add work to the loop, it still executes at the same time interval.  This type of structure is called an exec loop and it is often used in embedded programming because it ensures that all the timing operations can be simple software counting in multiples of the loop period.

    And here is the program.

    void main(void)
        TRISAbits.TRISA2 = 0;       // Configure the TRISA2 as an output (the LED)
        T0CON1bits.ASYNC = 0;       // Make sure the timer is synchronized
        T0CON1bits.CKPS = 5;        // Configure the prescaler to divide by 32
        T0CON1bits.CS = 2;          // use the FOSC/4 clock for the input
                                    // the TMR0 clock should now be 250kHz
        TMR0H = 250;                // Set the counter to reset to 0 when it reaches 250 (1ms)
        TMR0L = 0;                  // Clear the counter
        T0CON0bits.T0OUTPS = 9;     // Configure the postscaler to divide by 10
        T0CON0bits.T0EN = 1;        // turn the timer on
                                    // the timer output should be every 10ms
            LATAbits.LATA2 = 0;     // Turn on the LED... this allows us to measure CPU time
            __delay_ms(5);          // do some work... could be anything.
            LATAbits.LATA2 = 1;     // Turn off the LED... Any extra time will be while the LED is off.
            while(! PIR0bits.TMR0IF ); // burn off the unused CPU time.  This time remaining could be used as a CPU load indicator.
            PIR0bits.TMR0IF = 0;    // clear the overflow flag so we can detect the next interval.

    I chose to use a delay macro to represent doing useful work.  In a "real" application, this area would be filled with all the various functions that need to be executed every 10 milliseconds.  If you needed something run every 20 milliseconds you would execute that function every other time.  In this way, many different rates can be easily accommodated so long as the total execution time does not exceed 10 milliseconds because that will stretch a executive cycle into the next interval and break the regular timing.

    Special Considerations

    One interesting effect in timers is they are often the first example of "concurrency issues" that many programmers encounter.  Concurrency issues arise when two different systems access the same resource at the same time.  Quite often you get unexpected results which can be seen as "random" behavior.  In the code above I configured the timer in 8-bit mode and took advantage of the hardware compare feature so I never needed to look at the timer counter again.  But let us imagine a slightly different scenario.  Imagine that we needed to measure the lap time of a race car.  When the car started the race we would start the timer.  As the car crossed the start line, we would read the timer BUT WE WOULD NOT STOP IT.  When the car finished the last lap, we could stop the timer and see the total time.  IN this way we would have a record for every lap in the race.  Simply by subtracting the time of completion for each lap, we would have each lap interval which would be valuable information for the race driver.  Each time we read the timer without stopping it, we have an opportunity for a concurrency issue.  For an 8-bit timer we can read the entire value with one instruction and there are no issues.  However, the race is likely to last longer than we can count on 8-bits so we need a bigger timer.  With a 16-bit timer we must perform 2 reads to get the entire value and now we encounter our problem.


    In the picture above I have shown two scenarios where TMR0 in 16-bit mode is counting 1 count per instruction cycle.  This is done to demonstrate the problem.  Slowing down the counting rate does not really solve the problem but it can affect the frequency of the issue.  In this example the blue cell indicates the first read while the red cell indicates the second read to get all 16-bits.  When the counter was 251, the reads are successful, however when the counter is 255, the actual value we will read will be 511 which is about 2x the actual value.  If we reverse the read order we have the same problem.  One solution is to read the high, then the low and finally, read the high a second time.  With these three data points and some math, it is possible to reconstruct the exact value at the time of the first read.  Another solution is in hardware.


    In the data sheet we see that there is some additional circuitry surrounding TMR0H.  With this circuitry, the TMR0 will automatically read TMR0H from the counter into a holding register when TMR0L is read. So if you read TMR0L first and then TMR0H you will NEVER have the issue.  Now consider the following line of C.

    timerValue = TMR0

    It is not clear from just this line of code which byte of TMR0 is read first.  If it is the low byte this line is finished and perfect.  However, if it is the high byte, then we still have a problem.  One way to be perfectly clear in the code is the following:

    timerValue = TMR0L;
    timerValue |= TMR0H << 8;

    This code is guaranteed to read the registers in the correct order and should be no less efficient.  The left shift by 8 will probably not happen explicitly because the compiler is smart enough to simply read the value of TMR0H and store it in the high byte of timerValue.

    These concurrency issues can appear in many areas of computer programming.  If your program is using interrupts then it is possible to see variables partially updated when an interrupt occurs causing the same concurrency issues.  Some bigger computers use real-time operating systems to provide multi-tasking.  Sharing variables between the tasks is another opportunity for concurrency issues.  There are many solutions, for now just be aware that these exist and they will affect your future code.

    Timer 0 is probably the easiest timer on a PICmicrocontroller.  It has always been very basic and its simplicity makes it the best timer to play with as you learn how they work.  Once you feel you have mastered timer 0, spend some time with timer 1 and see what additional features it has.

    Once again, the project is in the attached files.

    Good Luck.


  2. Orunmila
    Latest Entry

    By Orunmila,

    Melvin Conway quipped the phrase back in 1967 that "organizations which design systems ... are constrained to produce designs which are copies of the communication structures of these organizations."

    Over the decades this old adage has proven to be quite accurate and this has become known as "Conway's Law". Researchers from MIT and Harvard have since shown that there is strong evidence for this correllation, they called it the "The Mirroring Hypothesis". 

    When you read "The mythical man month" by Fred Brooks we see that we already knew back in the seventies that there is no silver bullet when it comes to Software Engineering, and that the reason for this is essentially the complexity of software and how we deal with it. It turns out that adding more people to a software project increases the number of people we need to communicate with and the number of people who need to understand it. When we just make one big team where everyone has to communicate with everyone the code tends to reflect this structure. As we can see the more people we add into a team the more the structure quickly starts to resemble something we all know all too well!


    When we follow the age old technique of divide and concquer, making small Agile teams that each work on a part of the code which is their single responsibility, it turns out that we end up getting encapsulation and modularity with dependencies managed between the modules.

    No wonder the world is embracing agile everywhere nowadays!

    You can of course do your own research on this, here are some org carts of some well known companies out there you can use to check the hypothesis for yourself!



  • Create New...