GPIO Programming
GPIO Programming
Introduction
As with other microcontrollers, the first programming activity is GPIO (General Purpose Input/Output) control.
In this activity, we will be introduced with utilizing GPIO’s of ATmega644. Gizduino+ 644 will be used.
WINAVR
The latest WinAVR (as of this writing) is 2010-01-20. It is a GCC based compiler for AVR microcontrollers. It comes
with its own IDE, the Programmer’ Notepad which can be useful but users can also make use of any text editor. Unlike other
IDE’s, using WinAVR requires us to make our own makefile. Makefile is simply a script that will guide us to compile and link
out programs. WinAVR installation do come with a makefile wizard, the Mfile editor.
#include <avr/io.h>
unsigned char i, j;
void delay(void){
for (i=0;i<255;i++) {
for (j=0;j<255;j++);
}
}
int main(void){
DDRB |= (1<<LED);
PORTB &= ~(1<<LED);
while(1){
PORTB |= (1<<LED);
delay();
PORTB &= ~(1<<LED);
delay();
}
return 0;
}
The code above is simple blinky program. LED will be connected to pin PB5 of PORTB.
1 | G e tti n g S t a r t e d w i t h E m b e d d e d C : A V R p r o g r a m m i n g
About the code
#include <avr/io.h>
This line includes IO.Hwhich describes all definition required to simplify the coding. IO.H can be found in
“C:\WinAVR-20100110\avr\include\avr”, assuming default installation of WinAVR. Inside IO.H, the actual header
file will be pointed out depending on the device being used. In our case, it’s the ATMEGA644. ATMEGA644 should
be defined in the makefile (more on this later).
DDRB |= (1<<LED);
This line defines the direction of a particular PIN/PORT. DDRB is PORTB Data Direction Register. Setting (1) any pin
indicates an output. And Clearing (0) it makes it an input.
The way the line written is referred to as AVR style notation. Actually, this line executes several commands. LED is
defined as the 5th pin (PB5). Therefore (1<<LED) means we shift a ‘1’ LED times. After execution, the 8-bit value
should be 0b00010000.
So, the DDRB |= (1<<LED) is like DDRB = DDRB OR 0b00010000. This tells us that when we OR a particular bit/s
with ‘1’, it becomes ‘1’.
while(1){
PORTB |= (1<<LED);
delay();
2 | G e tti n g S t a r t e d w i t h E m b e d d e d C : A V R p r o g r a m m i n g
PORTB &= ~(1<<LED);
delay();
}
This foreverloop should toggle the state of the LED. Setting a pin makes it HIGH and clearing makes it LOW
Using WinAVR
Copy-paste the code above to a text editor and save it in folder with any filename with ‘c’ extension (figure 1).
For this activity, let us call it as main.c.
Launch mfile (from Start menu). A default makefile script will be shown, save it to your working folder (the
folder where you saved the main.c).
3 | G e tti n g S t a r t e d w i t h E m b e d d e d C : A V R p r o g r a m m i n g
Figure 2. Makefile generation on mfile.
Go the working folder and open makefile with any text editor. And edit the following lines as:
MCU = atmega644p
F_CPU = 16000000
AVRDUDE_PROGRAMMER = Arduino
AVRDUDE_PORT = usb
Then save it.
We use 16MHz because it is the oscillator installed in the gizDuino+ 644.
4 | G e tti n g S t a r t e d w i t h E m b e d d e d C : A V R p r o g r a m m i n g
Open your command prompt and go to the working register and type the command “make all”.
The “make all” command compiles, links and generates output files, such as HEX, ELF and COF. We will be
needing HEX file.
Figure 4. Working folder showing the files generated after "make all".
Connect the gizduino+ 644p on your USB port and wait for enumeration of the PL2303 USB to serial driver.
The driver can be downloaded from: http://www.prolific.com.tw/US/ShowProduct.aspx?p_id=225&pcid=41
Connect an LED on PB7 (with a limit resistor). PB7 is PIN 13 in gizduino+. (Refer to the schematic included on
this activity)
In the command prompt on the same folder, type “make program”. The HEX file will now be downloaded .
An LED on PB7 should blink very fast but is noticeable.
Note: When recompiling or using “make all”, be sure to clean it first by “make clean”. You can also make use of
an oscilloscope instead of LED to verify your code.
There is an incorporated delay function that comes with WinAVR. Utilizing it is simply by including it as a header.
The code below demonstrate the usage of the delay function and the inclusion of the header file.
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB |= (1<<LED);
PORTB &= ~(1<<LED);
while(1)
{
PORTB |= (1<<LED);
_delay_ms(500);
PORTB &= ~(1<<LED);
_delay_ms(500);
}
return 0;
}
5 | G e tti n g S t a r t e d w i t h E m b e d d e d C : A V R p r o g r a m m i n g
Inputs with AVR
There are 3 Registers involving an I/O register. For PORTB, these are DDRB, PORTB and PINB. DDRD is as we know is the Data
Direction Register, PORTB is the Data Register itself and PINB is the Input register for PORTB. When we want to write to
PORTB, we write to PORTB and when we want to read PORTB, we read PINB.
The code below will show us how read a pin. PINB bit zero is to detect an active-low signal. When an active-low is detected
it shall toggle the LED connected to bit 0.
#include <avr/io.h>
#include <util/delay.h>
int main(void)
{
DDRB &= ~(1<<SWITCH); // PB0 as input
DDRD |= (1<<LED); // bit 0 is output
PORTD = (1<<LED); // initialize LED to HIGH
while(1)
{
if(!(PINB) & (1<<SWITCH)) //detects if SWITCH is LOW
{
_delay_ms(200); // a debounce delay
PORTD ^= (1<<LED); // toggle LED
}
}
return 0;
}
6 | G e tti n g S t a r t e d w i t h E m b e d d e d C : A V R p r o g r a m m i n g
Design Problem: Keypad decoder
Using AVR C programming, you are to decode a keypad and simulate it in Proteus. You may follow the schematic
below or assign your I/O to other pins. The program will show the number pressed on the seven segment. The
value shall not change until another key is pressed.
References:
ATmega644 Datasheet
AVR C Runtime Library
7 | G e tti n g S t a r t e d w i t h E m b e d d e d C : A V R p r o g r a m m i n g