In previous post, I show a simple programming example of INT0. As it's already stated, the Atmega16 has up to 3 external interrupt sources. In this example, I use all its external interrupt sources, the INT0, the INT1, and the INT2.
I select the low logic level of these interrupt source to trigger the ISR. Whenever any interrupt occurs, its corresponding output LEDs will toggle its logic state. The output LEDs are PB5, PB6, and PB7.
Display multiplexing is very common for most microcontroller programming and interfacing. In usual, a controller could drive up to 8 digits before we can see its display flickering. In this programming example, I use only two digits of 7-Segment display. Because it's easy to build the circuit with a little of source codes.
Program simulation in Proteus
Controller keeps track of counting an external pulse generated by SW1 switch pressing. The maximum press counting is 60 before it rolls down to 0. The display will become flicker whenever the input switch has a longer press duration, but it's not longer than 250ms.
Atmega16 has up to 21 interrupt sources. Here I will discuss only the external interrupt of this controller. External interrupt consist of three source sources:
INT0 - External interrupt request 0
INT1 - External interrupt request 1, and
INT2 - External interrupt request 2.
First I will show how to use INT0 source. It has four sense that determine whether the interrupt is triggering. It is the Interrupt Sense Control register bits of the MCU Control Register (MCUCR).
MCU Control Register (MCUCR)
Interrupt Sense Control register bits
The General Interrupt Control Register (GICR) turn on and off these external interrupt source, including the INT0 source.
General Interrupt Control Register – GICR
They also have their corresponding interrupt flag in the General Interrupt Flag Control (GIFR).
General Interrupt Flag Control (GIFR)
There are three bit corresponding to INTF1, INTF0, and INTF2. These bits will be cleared after the Interrupt Service Routine (ISR) executed. Optionally the programmer can clear any flag by setting it. However it is uncommon from most of microcontrollers.
In C programming the interrupt is very easy to program that I will show it in this programming example.
In this example I use only the INT0 source. The interrupt sense is the falling edge of INT0, as I will select it in program. Each time the INT0 occurs, and output LED connects to PD7 will toggle.
Schematic Diagram
The source code is very simple. It contains a little lines of code.
As mentioned in previous post, configuring Timer/Counter0 module of ATMega16 to drive in counter mode the programmer doesn’t need to write a program routine to count external input pulse. The counter is automatically increase its content with the present of input pulse change.
Since counter mode is fast, the system can show its content on a multiplexing display without flickering. In this example of using Timer/Counter0 module, the system accept a number of input pulse from external device using its peripheral hardware inside. Its result will be displayed on a three-digit multiplexing display.
Hardware and Software Preparation
This programming example is solely experimented on a personal computer. Embedded controller’s program is written using embedded C in Atmel Studio 7 while its hardware experiment will be tested in Proteus simulator.
Hardware Preparation
Proteus is a good choice for electronics circuit design and simulation. Software simulation produces a nearby result to physical hardware test.
Schematic diagram preparation for system simulation
The user can choose another lower frequency of its crystal oscillator, but the delay function parameter must be properly set in software.
An optional square wave generator GEN1 supplies a variable high frequency. It’s enabled/disabled by a latched switch SW2.
Software Preparation
Software setting of counter mode of Timer/Counter0 peripheral is done within a few lines of code. Another routine is written to handle multiplexing display. This three-digits display made of some little more lines of code.
C
/*
* counter0MuxDisplay.c
*
* Created: 12/15/2020 9:49:40 PM
* Author : admin
*/
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
/*Each digit active for 5ms*/
#define digitOn 5
voiddriveDisplay(void){
/*7-Segments data for common cathode type display*/
I created a label for delay function parameter. It’s “digitOn”, and it’s set to 5 (ms). it’s useful for code modification in later hardware test.
Proteus Simulation
Without spending time in physical hardware prototyping, the programmer can draw this example circuit in simulator. It also save a lot of time and budget of components purchasing.
Proteus simulation of this working example
The result shown on this picture is 195 in decimal. the maximum counting of the 8-bit TCNT0 register is 0xFF or 255 in decimal. After it reached 255 it will roll back to 0 at next counting.
Creating A 16-bit Counter
We can get a 16-bit counting register from this 8-bit TCNT0 register by adding one more 8-bit register. An additional C unsigned 16-bit integer stores the total counting result up to 65536 counts.
Circuit Diagram Preparation
This optional programming example has some variation on its output display. It’s a five-digit multiplexing display that show a counting variable up to 65536 counts before it rolls back to 0.
Proteus VSM circuit diagram for hardware prototyping and simulation
I added a counter timer virtual instrument to verify the counting result whenever the counter is supplied from a high speed square wave generator GEN1.
AVR GCC Code Preparation
I added an unsigned 8-bit character and another unsigned 16-bit integer to get a 16-bit counting variable in AVR GCC.
Since interrupt flag created by Timer/Counter0 Overflow (TOV0) is set whenever TCNT0 overflows and rolls back to 0, we test and clear this flag to update the 16-bit counting variable.
Unlike previous example of an 8-bit counter, this 16-bit counter needs a five-digit display. The need to add more lines of code to the program that drive this multi-digit multiplexing display. We will more embedded C codes in this example.
C
/*
* counter0MuxDisplay_2.c
*
* Created: 12/16/2020 12:44:43 PM
* Author : admin
*/
#include <avr/io.h>
#define F_CPU 16000000UL
#include <util/delay.h>
/*Each digit active for 5ms*/
#define digitOn 5
/*Auxiliary Counting Variables */
unsignedchartcnt0_1=0;
unsignedinttotalCounter=0;
voiddriveDisplay(void){
/*7-Segments data for common cathode type display*/
We will see its simulation result at the next section.
Simulation Result
This circuit diagram composes of a lot of components placement and breadboard wiring. Using a simulator could produce a comparable result to the one’s in physical hardware.
Simulation result in Proteus VSM of this working example
Square wave generator GEN1 creates a frequency of 5kHz for this counter. Timer counter counts a nearby result with respect to the microcontroller counter. This microcontroller counting system reset its content whenever it reaches the maximum value of 65536 counts.