Laboratory |
Laboratory 10: FSM in C language. Interrupts to detect signal events (CLK) [P10] Plan X: FSM using state enumeration, small counters. Plan Y: large counters. |
[12/12] |
This is the group post lab assignment PLA10_11 to be submitted at Atenea before the due date. Study and execute in your computer this LAB10 and the next LAB11 lab tutorials before attempting to solve this post lab assignment. |
3.5.4. Examples
3.5.4.3. Counter_BCD_1digit: 1-digit BCD counter with count enable (CE) and terminal count (TC10)
How to generate a CLK-like synchronisation signal when executing software? How to synchronise operations like state transitions in a FSM each time an active CLK edge is detected as it was done in Chapter 2? We will answer these important questions using an external CLK signal or overflow flags from embedded peripheral such TMR0, to generate interrupts to the main program.
Two main ideas: Adapting a FSM in software and detecting signal transitions (rising and falling edges) by means of interrupt to the main program triggered by hardware flags from peripheral subsystems (external pins, timers, A/D, USART, etc.). Each time that there is an interrupt event, we will set a software variable named _flag in the interrupt service routine ISR() function.
1. Specifications | Planning | Dev. & test | Prototype | report |
To demonstrate how a sequential circuit can be implemented using a microcontroller for instance in a target chip PIC18F4520 and the latest Microchip MPLAB X IDE and XC8 tools, let us implement some features of a typical 1-digit BCD counter type 74HCT160 or 74HCT190. Full rec.
Fig. 1. Internal structure of the traditional chip 74HCT190 to be implemented using a μC. Note: chip's parallel load (LD) functionality is not going to be considered in this introductory example on plan X, because it represents changing the plan from X to Y. Thus in this example we like to invent a chip like the 74HCT190 with its inputs LD_L (PL_L) = '1', and Din(3..0) = "0000" all the time. |
The chip and the main ideas can be readapted as represented in Fig. 2 using our naming conventions as in ounter_BCD_1digit example on plan X.
Fig. 2. Symbol of the chip functionality (Visio). Specifications (symbol, function table, timing diagram) are very similar to the ones studied in Chapter 2. Design step #1 --> only UP counting to make it even simpler. Design step #2 -- > counting UP and DOWN. Add input UD_L and modify the project conveniently. |
|
Draw an example of timing diagram as in Fig. 3. Thus, a question arises immediately: how to make the microcontroller sensitive to CLK signal edges? Is it the same that reading inputs (polling) or not? What is the difference between this external CLK that runs the counter application and the quartz oscillator OSC at 4 MHz that runs the microcomputer?
Fig. 3. Example of timing diagram for the initial design phase #1. |
The key concept of interrupt. The interrupt logic and their associated configuration bits are similar for most microcontrollers: PIC18F4520, PIC16F877A, ATmega328P, etc. PIC18F4520 interrupts can be prioritised using additional configuration bits.
Note: Plan X for counter has its limitations when the application has many states or many state transitions. For instance, if a feature such as parallel load (LD and Din) is introduced later on as a new design step #3, the project must be considered from plan Y perspective where current_state is encoded in binary sequential (radix-2), thus, redesigning completely the counter as it was shown in Lab7 is required. We will study how plan Y is adapted to uC below in the second tutorial of this laboratory Counter_mod1572.
Specifications | 2. Planning | Dev. & test | Prototype | report |
The project design flow when using microcontroller technology is depicted in Fig. 4.
Fig. 4. Design flow for developing and testing a single design step at a time. |
Step #1: Design a basic up counter with TC10 and CE. For instance as was done in P7 Counter_BCD_1digit.
Draw the state diagram as in Fig. 5. Note that in this chapter we use memory variables to solve the diagram. External signals are read (polled) or detected by means of interrupts (edge sensitive), and output variables in parenthesis are written to the corresponding microcontroller pins.
Fig. 5. State diagram driven by interrupts on external edge detection. |
Be aware of the differences between a level sensitive signal (read/poll) and an edge sensitive signal (interrupt) because they are interfaced using specific mechanisms. We will attach switches to signals to be polled/read, and pushbuttons to signals which edges has to be detected.
|
Step #2: Enhance the previous circuit adding the UD_L feature. Only when step #1 is fully develop and debugged using step by step execution and watching variables of interest.
|
(Optional) Step #3: Add the parallel load (LD), which means changing completely from plan X to plan Y. Additionally, some actions has to be considered when an invalid data is inputted by the user (D = 1010, 1011, ... 1111), for instance, reset the system. Therefore, it is better to solve this step #3 once the next tutorial below on plan Y is studied.
Circuit and port connections are represented in Fig. 6. Note: If the system has to be prototyped later on in a training board such PICDEM2 PLUS or EXPLORER 8, use some of the unconnected port pins available on the board to attach inputs and outputs.
Fig. 6. Hardware used in this application. The idea is to
connect the CLK signal to an external interrupt pin (INT0).
|
The general idea is represented in Fig. 7. The concepts of CC1 and CC2 combinational circuits inherited from Chapter 2 are the same, however this time, we will implement these logics using software routines and input and output RAM variables.
Fig. 7. Software organisation used in this application.
Because var_current_state is saved in a memory position
and updated every main loop cycle, there is no need of
next_state variable as it was the case in Chapter 2.
And below even a clearer flowchart representation of
the software organization What signals to read?,
what signals
to be connected to external interrupts? |
This special C code organisation is for taken full advantage of having develop Chapter I and Chapter II in the CSD ladder. Almost all the content learnt since now can be fully applied here again, even if we switch to microprocessors technologies. Furthermore, it can be applied the same if you change technologies again for Arduino or Raspberry Pi or any other similar platform. Notice the huge advantage of organising as separate and independent pieces of software the hardware-dependent functions acting as interfacing drivers.
In Fig. 8 there is an example of software-hardware diagram. Another advantage of this organisation is that software functions output_logic() and state_logic() are completely compatible among platforms and programming languages. Only hardware-dependent functions (drivers) have to be rewritten when changing microcontrollers or programming environments.
Fig. 8. Hardware-software diagram. Hardware interface functions are drawn in blue and software functions based on RAM memory in black. The picture also shows the circuit and the associated configuration bits for allowing the external interrupt INT0 to detect CLK's falling edges or rising edges (it configurable). |
All the main RAM variables to handle the FSM are represented in Fig. 9. Pay attention that var_Q is 11-bit wide, thus a convenient type is int (16-bit wide). All the other variables are kept char type for being able to watch them easily in our simulation and debugging tool.
Fig. 9. RAM variables list. |
Draw the main ideas of init_system(). Configure input and output pins. Consider as well interrupt configuration bits to allow INT0.
Fig. 10. TRIS configuration bits. |
Notice how organising the software in this very specific set of functions, each one with a very well defined objective, it is easy to work in group with several team members working concurrently in different functions of the same project.
Draw the flowchart of read_inputs(). Basic function to poll input voltages as in P9.
Draw the flowchart of write_outputs(). Basic function write pins voltages as in P9.
Infer how to organise the interrupt service routine ISR() to handle CLK's falling edge detections.
Fig. 11. Interrupt service routine for setting var_CLK_flag. |
And now, it is necessary to discuss how to transfer all the state transitions into a truth table.
Draw state_logic() truth table
Fig. 12. Truth table for state_logic() function. When the input var_CLK_flag is used for all transitions there is no need to add it to the truth table (As we did with the CLK signal in Chapter II projects). |
Translate it into a behavioural flowchart. As shown in Fig. 13, all transitions are affected by the CLK edge detection interrupt as expected in counters. The function read_inputs() captures the pins of interest and generates their corresponding RAM variables.
Fig. 13. Translating state_logic() truth table into a behavioural flowchart so that C statements can be easily imagined. |
Finally, what is left to finish this project planning is the same idea but for the outputs, how to translate all the outputs in parenthesis into a truth able and the equivalent flowchart?
Draw output_logic() truth table.
Fig. 14. Truth table for output_logic() function. |
Translate it into a behavioural flowchart.
Fig. 15. Translating output_logic() truth table
into a behavioural flowchart so that C statements can be
easily imagined. The hardware function
write_outputs() converts RAM varialbes into electrical
signals in the selected pins. |
Additional questions:
- How long does it take to execute the code and thus which is the reading/polling speed?
- How many RAM bytes are used in this application?
- Which configuration bits has to be programmed to setup interruptions from INT0?
- How to program the INT0 active edge (rising or falling)?
- How many external interrupt sources INT has the microcontroller that you can choose from?
Project location:
C:\CSD\P10\Counter_BCD_1digit\(files)
|
Important remarks: Do NOT write C code without having discussed in sheet of paper your planning and flowcharts. Therefore, four or five sheets of paper are expected to clarify and organise every aspect of hardware and software. Reuse as much as possible materials from previous projects, however, do NOT use digsys pictures in your reports, but analyse and redraw them in your own way. It is the only way to grasp full details and be able to ask meaningful questions to comprehend projects.
Specifications | Planning | 3. Dev. & 4. test | Prototype | report |
This is an example of circuit schematic Counter_BCD_1digit.pdsprj . This capture is easily generated copying and adapting a similar example.
Fig. 16. Hardware connections to solve phase #1 of this project.
A switch allows you to select the CLK source: single pulses or an external oscillator. |
The C source file Counter_BCD_1digit.c for step #1 where only count enable and up counting are developed.
Run the IDE and start a new project in the corresponding folder. Name it as usual: Counter_BCD_1digit_prj.
Compile, generate the COF and the HEX output configuration files.
Check the number of resources used: the size of the program, the number of memory bytes (RAM).
Run Proteus and test the circuit using step by step, break points and the watch window tools. Remember that the key strategy is to write a few lines of code at a time, compile, run and test. And only when it works, add some more code after having transferred truth tables and algorithms into flowcharts.
Questions:
- How long does it take to run the mail loop?
- How long does it take to execute an interrupt? and therefore, what is the maximum CLK frequency you should apply in order to make it run correctly?
- How can you compare these magnitudes with values attained in chapter II designing hardware counters in VHDL for target FPGA or CPLD?
Fig. 17. Example capture from Proteus logic analyser instrument and the analysis to determine whether the circuit works correctly (CE = 1). NOTE: Do not print the instrument screen capture with black background for your reports, but change the colours configuration instead to save printer ink. |
This is the compiled Counter_BCD_1digit.zip project.
Specifications | Planning | Dev. & Test | 5. Prototype | Report |
Example 1: Board Picdem2+. Target microcontroller: PIC18F4520. Tools: MPLAB X + XC8 + Proteus
We can use the prototyping area for soldering push-buttons, switches and LED.
Fig. 18. Prototype built on a PICDEM2 board. |
Example 2: Simple mC target board. Target microcontroller: PIC18F46K22. Tools: MPLAB X + XC8 + Proteus + MPLAB SNAP debugger/programmer
We can try the same experiment using another target board and developing resources. Fig. 19 shows the adaptations for connecting a similar microcontroller. The hardware circuit Counter_BCD_1digit.pdsprj and the source file Counter_BCD_1digit.c so that we can pay attention on how to inicialise configuration bits and ports for this specific target microcontroller PIC18F46K22.
Fig. 19. Circuit connecting the PIC18F46K22. |
We can program and debug the circuit as we did already did in Proteus. Fig. 20 shows the setup using the MPLAB SNAP.
Fig. 20. Laboratoy setup to verify our design. |
A good idea is to make a minimum target PCB with all port pins available through sockets like Arduino. In this way it can be used repeatedly with different shields or protoboards to verify application circuits. Fig, 21 shows the debugging environment in MPLAB X to run step by step watching variable values and using breakpoints.
Fig. 21. Using the debugger embedded in MPLABX IDE. |
Example 3: Board Explorer 8. Target microcontroller: PIC18F4520. Tools: MPLAB X + XC8 + Proteus
The same project but changing the pins to adapt to port connections as shown in Fig. 22 and Fig. 23.
Fig. 22. Microcontroller pins for Explorer 8 board. Button S1 will generate external CLK interrupts. Button S2 will be CE_L control input. Schematic for COSC and MCRL_L are also represented pasted from the board's user manual. |
|
|
The schematic connections are different thus hardware functions read_inputs() and write_outptuts() have to be modified accordingly. This is the advantage of programming the application using our style, only minor adaptations are necessary when changing prototyping platforms. This is the adapted project counter_BCD_1digit.pdsprj and counter_BCD_1digit.c. Project location:
C:\CSD\P10\Counter_BCD_1digit\EXP8_PIC18F4520\(files)
The design can be also emulated in hardware using for instance ICD 3 tool monitoring variables, breakpoints, watch windows, etc.
Fig. 23. Prototype built on Explorer 8 board. |
Instrument such Analog Discovery 2 or VB8012 may be used to drive CLK signal using the waveform generator and measuring outputs connecting the logic analyser.
Example 4 optional, beyond the CSD learning objectives. Board Explorer 8. Target microcontroller: PIC18F46K22. Tools: MPLAB X + XC8 + MCC + Proteus..
In this case, multiple files are specified by the MPLAB Code configurator.
The LCD populating Explorer 8 is wired and operating, but not used until the next design phase #2: counter_BCD_1digit_LCD.
Project location:
C:\CSD\P10\Counter_BCD_1digit\EXP8_PIC18F46K22\(files)
Fig. 24. Proteus captured schematic of some Explorer 8 circuits. As usual, if component models exist, we will try firstly to develop and run the prototype application in Proteus. |
This is the adapted project counter_BCD_1digit.pdsprj and counter_BCD_1digit.zip.
NOTE: To work with this new programing environment, do not start a "new project" but instead "open project" from the unzipped example given saved previously to the destination location.
Fig. 25. Open project in MPLAB X. This project, once running can be copied as the stating point for the next design phase #2. |
Specifications | Planning | Dev. & Test | Prototype | 6. Report |
Follow this rubric for writing reports.
Laboratory |
Laboratory 10: adapting FSM to C language. Interrupts to detect signal events (CLK) [P10] Plan Y: large counters: Counter_mod1572 Plan X: small counters |
|
3.5.4.4. Counter_mod1572 (large binary counter, plan Y)
Implement a FSM using C language (plan Y, large number of states)
How large number of states are saved? If there are too many states or too many state transitions, the FSM cannot be enumerated or it is impractical to do it, thus, let us organise the architecture as in chapter 2 plan Y, where var_current_state is defined as std_logic_vector signal. The equivalent this time is a variable type char, int, etc. (depending on the number of bits required). A char variable can hold up to 256 states. A int variable can hold up to 65536 states. A double int variable of 32 bits can hold 4.294.967.296 states (this is for instance counting seconds for 135 years!). Therefore, try to imagine how a real-time calendar chip such as DS1307 may be organised considering concepts from chaining counters.
1. Specifications | Planning | Dev. & test | Prototype | report |
To demonstrate how a sequential circuit can be implemented using a microcontroller (PIC18F4520) and IDE tools (Microchip MPLABX, XC8), let us implement a large counter such as Counter_mod_1572 using plan Y. Fig. 1 represents the symbol and functional table using our naming conventions, which are the same ones studied in Counter_mod1572. Full rec.
Fig. 1. Symbol (Visio) of the chip functionality. As usual, we can click a button to input CLK edges or instead, connect an oscillator. To make it a bit different, let us to drive the counter with CLK's falling edges. |
In a first design phase the basic counter can be implemented as shown in Fig.1. Optionally, because you know now that this is only the beginning, in a second design phase, parallel inputs or reversibility can be added as new features for this binary counter. On the other hand, as an addition exercise, you can even imagine the circuit using plan C2 and counter_mod16 as components.
Your great advantage now: FSM foundations are already studied in P7, and thus, solving it using a different technology based n microcontrollers, is not going to change its conceptualisation in any way. Indeed, from the point of view of engineering, we will have the advantage of comparing circuit realisations for the same entity (power consumption, speed, component list, flexibility to implement modifications, etc.)
Draw an example of timing diagram as in Fig. 2. Deduce how many states the system may include.
Fig. 2. Example of timing diagram directly inherited from Counter_mod1572 and adapted to μC using interrupts to detect falling CLK edges. The polling function read_inputs() for capturing the CE_L level can be executed continuously in the main loop or only when there is an INT0 detection. Which option would be better? |
Specifications | 2. Planning | Dev. & test | Prototype | report |
Let us organise the plan as usual taking large counters from P7 plan Y as reference.
Draw the state diagram as in Fig. 3.
Fig. 3. Example of state diagram adaptation. Every state transition depends on the detection of the CLK active edge by means of the interrupt service routine. Signals are transformed into RAM variables. As in the previous project, all state transitions are effective only when var_CLK_flag is asserted, thus INT0 interrupts must be enabled all the time (INT0IE = 1, GIE = 1) from init_system(). When there is no interrupt detection (var_CLK_flag = 0), the system is doing nothing but looping the main program. |
The electronic circuit is represented in Fig. 4. Some pins are connected to inputs and others to outputs.
Fig. 4. Hardware used in this application. The idea is to connect the CLK signal to an external interrupt pin (INT0) that has the specific circuitry to detect an active edge (configured falling) and set the hardware interrupt flag (INT0IF). |
This unit explains the key concept of external interrupt for detecting edges.
The general idea is represented in Fig. 5. The concepts of CC1 and CC2 combinational circuits inherited from Chapter 2 are the same, however this time, we will implement these logics using software routines.
Fig. 5. Software organisation used in this application. Because current_state is saved in a memory position and updated every main loop cycle, there is no need of next_state variable as it was the case in Chapter 2. |
The idea of designing a chapter 2 synchronous circuit is not that clear now. On the one hand, the microcontroller (a general purpose processor) is a synchronous device where the external OSC generates the necessary signals to synchronise all the architecture operations; on the other hand, the application, this time an 11-bit binary sequential counter, requires the detection of an external interrupt to be updated (CLK), and, to attend an interrupt there is an overhead of some OSC periods (in the range of some μs). So, think and discuss about it. Furthermore, about polling (why not sampling?) CE_L values there is also a problem related to the general loop: the more assembly instructions to execute the larger the loop and slower is going to be the polling frequency to read inputs. Finally, a larger OSC frequency implies shorter instruction execution times, and thus, a larger polling frequency.
Fig. 6 below shows a clearer flowchart representation of the software organization. What signals to read? what signals to be connected to external interrupts? While running in the infinite loop, any time that an INT0IF is detected the system jumps to attend the interrupt routine for a few μs. In this way, state diagram transitions can be reassessed.
Fig. 6. General interrupt-driven FSM-style program organisation. |
In Fig. 7 there is an example of software-hardware diagram. Another advantage of this organisation is that software functions output_logic() and state_logic() are completely compatible among platforms and programming languages. Only hardware-dependent functions (drivers) have to be rewritten when changing microcontrollers or programming environments.
Fig. 7. Hardware-software diagram. Hardware interface functions are drawn in blue and software functions based on RAM memory in black. The picture also shows the circuit and the associated configuration bits for allowing the external interrupt INT0 to detect CLK's falling edges. |
All the main RAM variables to handle the FSM are represented in Fig. 8. Pay attention that var_Q (and this time also current_state) is 11-bit wide, thus a convenient type is int (16-bit wide). All the other variables are kept char type for being able to watch them easily in our simulation and debugging tools.
Fig. 8. RAM variables list. |
Draw the main ideas of init_system(). Configure input and output pins. Consider as well interrupt configuration bits to allow INT0.
Fig. 9. TRIS configuration bits. |
Draw the flowchart of read_inputs(). Basic function to poll input voltages as in P9.
Draw the flowchart of write_outputs(). Basic function write pins voltages as in P9.
Infer how to organise the interrupt service routine ISR() to handle CLK's falling edge detections.
Fig. 10. Interrupt service routine for setting var_CLK_flag. |
Draw state_logic() truth table. And now, it is necessary to discuss how to transfer all the state transitions into a truth table. This time a convenient behavioural interpretation using the "+" arithmetic operator makes it very easy.
Fig. 11. Truth table for state_logic() function and its equivalent behavioural flowchart using arithmetic operators that are included in C language by default. |
Draw output_logic() truth table. This plan Y has the advantage that sequential binary code outputs are simply a copy of the internal state. And the var_TC1572 is deduced with the same logic expressed in Fig. 1.
Fig. 12. Truth table output_logic() and its behavioural interpretation. |
Project location:
C:\CSD\P10\Counter_mod1572\(files)
|
Optional. Only when the project is complete and running, add the parallel load (LD) feature.
Specifications | Planning | 3. Dev. & 4. test | Prototype | report |
This Fig. 13 is an example on how to capture the schematic in Fig .4 in Proteus. A single pole double throw (SPDT) switch is used for selecting between to types of CLK signals.
Fig. 13. Capturing the schematic in Proteus. Using an external SPDT switch we can click a button to input a single CLK edge or instead, connect an oscillator component for continuous operation. |
Example circuit: Counter_mod1572.pdsprj. In Fig. 14 there is an example of I/O ports connections.
Fig. 14. Example of I/O. |
Run the IDE and start a new project in the corresponding folder for the target microcontroller PIC18F4520. The C source file Counter_mod1572.c.
Compile, generate COF and HEX output configuration files. Attach the COF file to Microchip PIC18F4520 Proteus microcontroller.
Check the number of resources used: the size of the program, the number of memory bytes (RAM).
Run Proteus and test the circuit using step by step, break points and the watch window tools. Remember that the key strategy is to write a few lines of code at a time, compile, run and test. And only whet it works, add some more code after having translated truth tables and algorithms into flow charts.
Fig. 15. System running and watching variables for debugging purposes. |
Measure the main loop execution speed.
Fig. 16. Example of watching variables in the last state Q = 1571 |
Specifications | Planning | Dev. & Test | 5. Prototype | Report |
Download your application configuration file (*.hex) to a training board an verify that it works as expected and in the same way it did in the simulator.
Fig. 17 shows the materials for preparing a prototyping session.
Fig. 17. Basic elements for prototyping a microcontroller application. For new MPLAB X IDE versions, classic old tools are not longer supperted, thus you can choose the programmer/debugger to be ICD5 or PICkit 5 or MPLAB SNAP. |
Specifications | Planning | Dev. & Test | Prototype | 6. Report |
Project report: sheets of paper, scanned figures, file listings, notes or any other resources. Follow this rubric for writing reports. The main idea here is to explain corectly that you have developed and tested the circuit step by step running concurrently the MPLABX IDE and Proteus watching variables and step mode.