Getting started with the PIC16F18446 and State Machines

This tutorial explains to use of state machines with the PIC16F18446 Curiosity Nano board. It provides 2k of RAM and 16k program memory. More than enought for this small tutorial.

Pre-requisites if you want to follow all steps yourself: - Java installation - MPLab X IDE - SinelaboreRT demo - Graphviz (for editing the state machine)

For this tutorial we will use just the push botton and the LED on the board. So you can follow it without any additional hardware required. The LED shall blink all the time. The frequency can be changed from slow to fast by pressing the button. Simple enough but sufficient to show all the key concepts we are going to use.

The PINs are allocated as shown in the next figure using the MPLAP X IDE pin manager. The 4MHz system clock and the 10ms Timer0 timer tick were also configured with the Resource Manager. I've not used this configurator before. But have to say that it is a very convinient way to setup the hardware. I would wish to have the same for the MSP430 μCs I also often use.

Step 1 - Deciding the system archtecture

For small sensor nodes it is usually sufficient use a main loop design. The main loop cycles endlessly and waits for events. Events are benefitially stored in an event queue. The queue is filled from timer events, other state machines (cooperating machines) or interrupt handlers. If events are available the state machine(s) are called from the main loop to process them.

In our little example events are sent from the keyboad interrupt and from a software timer module which is called regulary from the cyclic hardware timer. The following figure shows the system archtecture.

The below code snippets show the irq handlers and the main loop processing the evens.

// cyclic timer interrupt void TMR0_IRQHandler(void){ tick(); // if a timer has fired this function stores a timer event in the message queue } // keyboard interrupt void SW0_IRQHandler(void){ fifoPut(&fifo,evKey); } void main(void){ ... while (1) { do { // check if there are one or more events in the queue. // if yes, process all events in the state machine retVal = fifoGet(&fifo, &bufVal); if (retVal != QUEUE_EMPTY) { sm(&instData, bufVal); } } while (retVal != QUEUE_EMPTY); __delay_ms(10U); } }

Step 2 - Realizing the state machine

So far we have not seen how the state machine looks like. To realize this simple job just two evens are reqired. - evKey: Indicates that the user pressed the switch - evTimeout: Indicating that it is time to toggle the LED

For this simpel state machine the editor which is built into the code generator is sufficient. For more complex machines is is recommended to use an advanced UML modelling tool of your choice. The next figure shows the complete state machine:

Initally the state machine enters the state Slow. The initial transition triggers the start of the timer with timeout time 10U (10U represents 10 times the base clock of the hardware interrupt (i.e. 100ms)). Then the machine waits for further events. Every time event evTimeout occures there is a self transition and as action the LED is toggeled.

In case evKey occures a state transitions from state Slow to state Fast and vice versa is triggered and the timeout time is updated.

Example action code for the transition going from state Slow to state Fast.

timerStop(timer_id); timerStart(timer_id, 10U);

Step 3 - Integrating the state machine in MPLAB X

The generated state machine code can be easily added to the PIC project. It is recommended to create a new folder e.g. called state_machine_generated_files. The state machine looks like as follows. To convienently edit the state machine model and generate code from it two batch files were created. The code generator needs a configuration file to set basic parameters. Take a look into the configuration file and read the manual if the meaning of the parameters is not clear.