Tutorial Dasar Mikrokontroler

Mikrokontroler, yah inilah dunia baru saya yang penuh dengan tantangan. Mungkin sebagian dari kita masih bingung, apa sih itu mikrokontroler…?, ehhmmm mikrokontroler adalah sebuah sistem mikroprosesor dimana didalamnya terdapat CPU, ROM, RAM, I/O, Clock dan peralatan lainnya yang dikemas dalam satu chip atau bisa juga dikatakan komputer versi mini… CMIW. Nah contoh sehari-hari dari implementasi mikrokontroler ini bisa kita lihat pada traffic light jalanan lalu lintas (lampu merah).  Nggak percaya…? coba klo demo mahasiswa ikutan aja hancurin tuh traffic light n lihat isinya….hahhaha…

Nah… ini ada tutorial dasar mikrokontroler yang saya temukan dari blog mahasiswa india, tutorialnya bagus banget buat belajar dasar – dasar mikrokontroler berbasis avr. Bukannya gw malas atau plagiat yang cuma seenak jidat copas artikel orang, tapi belum ada waktu tuk benahin nih blog and artikelnya. silahkan dibaca…hehehe

Atmel has come up with a whole range of superb AVR microcontrollers which are the dream of every hobbyist. However, the real icing on the cake is that these µControllers can be programmed with just a parallel port connector and nothing else!!!. However, Atmel µC’s have their downsides too. They have to be programmed in either Assembly or in C. There is one program – Bascom AVR – which reportedly allows programming in BASIC. But, unfortunately it doesn’t seem to work (?) with the el-cheapo parallel port programmers :( . So, the only option left is C, unless you are willing to dabble with Assembly.

I’ll attempt to give a brief introduction to basic I/O operations in C for AVR microcontrollers.

First of all, you need a programmer to program. As i told you, its all very simple, you just need a parallel port cable. Follow this excellent tutorial by The Real Elliot at Instructables.com

So, first make a simple programmer, test out the blinking LED program and then come back.

PS: Your programmer doesn’t have to include all the header pins, a board etc, that Real Elliot has shown in his tutorial. A basic parallel port connector with a few wires and resistors soldered directly on it is what i have been using from the past couple of months.  It works just as well.

Before starting, there are a few things i would wish to tell. First of all, at first sight , (especially to those unacquainted to C), all this “_BV(PD4)” stuff may seem a little too cryptic. At one point, you probably will be tempted to ditch GCC and learn Assembly.  However, i assure you that Assembly is much more frightening than AVR C.  AVR C is not at all hard to learn, it just looks a bit alarming because of those weird symbols like << >> ~ which keep floating around. Once, you understand what all that is about, it’ll all be a piece of cake.

What you should know before reading this tutorial:

1) I expect that you are somewhat well acquainted with atleast any 1 high level programming language. (BASIC, Java, C/C++ etc)

2) I expect that you are reasonably comfortable with the C syntax. You do not need to know all the stuff that comes in the 10th and 11th chapters of C++ books. Just the basics – Program syntax, header files, functions, if then else, loops – should be enough.

3) I expect you to be comfortable with binary numbers, logic gates and Boolean algebra.

If the answer to any of the above is no , then brush up and then come back.

I also recommend that everyone goes through this excellent pdf to brush up you C skills in case  they are a bit rusty.

The Port Control Registers

ATMEL AVR Port control Registers overview

For easier access , the I/O pins on an AVR uC are grouped into a number of ports. Each port contains a number of pins ranging from 3 to a maximum of 8. To control these Ports , 3 registers have been provided. Each register controls a specific feature of the Port. Let us examine each Register one by one.

And , one more thing. Unfortunately , both the register PORTx and the Portx physical pins are referred to by the same name. To avoid confusion , i will be referring to the register as PORTx and the physical pins as Portx.

Defining a pin as either Input or Output – The DDRx Registers

If you take a look at the tiny2313 datasheet, it says something on the 1st page – “18 I/O lines”. This means that out of the 20 pins of tiny2313, 18 can be used as either input or output pins.

But then, immediately the doubt arises ”How do I tell the micro controller whether I want to use a pin as input or as output?”

For this purpose, there exists a register known as the DDRx register for every port. The “x” stands for the port alphabet. Every bit in the register controls a single pin of the port.

ATMEL AVR C DDRx Register

In case of the DDRx register, each bit controls the I/O of the respective port pin. I.e., the 5th bit controls the 5th pin of the PORT et cetera.

To make a pin work as Input, just write a LOW to its respective bit in the appropriate DDRx register.

To make a pin work as Output, just write a HIGH to its respective bit in the appropriate DDRx register.

Now suppose, i wanted to configure the 3rd and 7th pin of portb as output and the rest as input :

DDRB = 0b10001000;

Notice that the 7th and the 3rd bits are made high. And the rest are all LOWs.  The above command, when executed, will configure PORTB as we selected.

Similarly, you do the same thing for other ports as well.

Suppose you wanted to make all the pins of portd as output:

PORTD = 0b11111111;

But, if you are a keen observer , you might have noticed one thing. PORTD has only 7 pins. However, we have written an 8 bit value to the DDRD register. So, what happens to the last bit? The answer is: nothing. Nothing happens. The eight bit is simply ignored by the microcontroller.

Making a pin go HIGH or LOW – The PORTx register

There is one more register that controls the HIGH/LOW status of a pin. That register is called the PORTx register. Every bit in the register controls the state of the respective bit in that port. i.e. the 5th bit controls the 5th pin of the port etc.

It has 2 functions:

Case 1 : To make a pin go high or low ( if it is an output pin).

ATMEL AVR C PORTx  Register - For output pins

DDRB = 0b10001111;          /* Configuring I/O pins of  portb   */
PORTB = 0b10001010     /*   Write this byte to PORTB           */

Now, the 7th bit, 3rd bit and the 1st bit will be set.  The 0th and 2nd bit will be reset. The other bits will be in a High-Z state as they are configured as input pins.

Case 2 : To activate / Deactivate pull up resistors.

ATMEL AVR C PORTx register - For input Pins

The input pins of tiny2313 are generally in the Hi-Z state. This makes them prone to catching noise and picking up false signals. Hence, it is advisable to put a pull-up resistor to reduce noise. The resistor will normally hold the input pin at logic HIGH. Any external source can pull the voltage down to LOW when required.

Fortunately, Atmel has already included internal pull-up resistors. You can enable them by writing a HIGH to the appropriate bit of the PORTx register.

DDRB = 0b00000000;           /* Configuring I/O pins of portb  */
PORTB = 0b01110101;         /*enable internal pull-up resistors on output pins 1 , 3 , 5 , 6 , 7 */

Reading the status of an Input Pin – The PINx register

ATMEL AVR C PINx register

To put it bluntly, the PINx register contains the status of all the pins in that port. If the pin is an input pin, then its corresponding bit will mimic the logic level given to it. If it is an output pin, its bit will contain the data that has been previously output on that pin.

DDRD = 0b00000000;        /* Set all pins as input */
uint8_t status;                                /* Define a 8 bit integer variable */
status = PIND;                   /* Store the current value of PIND in status */

The above code will cause whatever input has been given to the 8 pins to be written to the variable status.

PS : Dont worry yourself if you cant understand the uint_8 stuff. All you need to understand is that we have just created a 8 bit variable with the name “status”.   “uint8_t” in AVR C is kinda like the equivalent  of “int” in ANSI C.

The Practical Stuff

Now that you know about the 3 registers , you are all set to actually start programming some real stuff. Why dont we program a running light sequence?

In our running light sequence , there will be 8 LEDs which will light up in sequence. It will be something very similar to a ring counter made using a CD4017.

Since ,we are using 8 LEDs , we must use a port that has 8 pins. That port in the Attiny2313 is the Portb.

AVR Tiny2313 Datasheet Portb Highlighted

So , first we must configure all the pins of Portb as output. For that we need to set all the bits in the DDRB register high.

DDRB = 0b11111111;

Now that we have configured the LEDs as output , we are now ready to start lighting the LEDs one by one. We will set each bit in PORTB register high one after the other , with a small delay in between

DDRB = ob11111111

PORTB = 0b10000000;
_delay_ms(50);
PORTB = 0b01000000;
_delay_ms(50);
PORTB = 0b00100000;
_delay_ms(50);
PORTB = 0b00010000;
_delay_ms(50);
PORTB = 0b00001000;
_delay_ms(50);
PORTB = 0b00000100;
_delay_ms(50);
PORTB = 0b00000010;
_delay_ms(50);
PORTB = 0b00000001;_
delay_ms (50);

With the above code , the LEDs will just run once and then stop. We need to it keep on running in a cycle like in a CD4017. To do that , let us add a infinite loop. We also have to declare the main function and include the all essential header files.

#define F_CPU 1000000UL                                    /* Clock Frequency = 1Mhz */

#include <inttypes.h>
#include <avr/io.h>
#include <util/delay.h>

int main(){                         // The main function

DDRB = 0b11111111;                    // Set all the pins of PortB as output

while (1) {                        // Set up an infinite loop

PORTB = 0b10000000;                    // Turn on LED1
_delay_ms(50);                        // Wait
PORTB = 0b01000000;                    // Turn on LED2
_delay_ms(50);                        // Wait
PORTB = 0b00100000;                    // The same sequence repeats…
_delay_ms(50);
PORTB = 0b00010000;
_delay_ms(50);
PORTB = 0b00001000;
_delay_ms(50);
PORTB = 0b00000100;
_delay_ms(50);
PORTB = 0b00000010;
_delay_ms(50);
PORTB = 0b00000001;
_delay_ms(50);
}

}

The statment while  (1) is forever true , so the LEDs keep cycling forever.

There’s just one teeny weeny thing left : the Makefile. You can use the same one that Real Elliot provides in his Ghetto programming tutorial here. For your convenience i have uploaded both here :

Ready to use Makefile – The full credit goes to Real Elliot.

Running_LEDs.c

Dont forget to remove the .txt extension from the makefile after you download it.

If you compile it and load it into your Attiny2313 , you will see the LEDs on PortB running in a chain like this :

Animated GIF of AVR uC Attiny2313 Driving a LED Chain

Note : This code is a terrible example of how to make an LED chain. The same thing can be accomplished more efficiently by a loop in less than 5 lines of code.

Selective bit modification in Registers

However there is a huge disadvantage in the modifying registers in this way! Suppose you want to set the 7th bit of PORTB and reset the 3rd bit without affecting the rest, how would you do it?

It seems like its impossible, because bits in the AVR registers cannot be accessed individually. Despite this fact, with a little bit of Boolean algebra , it is possible to modify just the bits we need without touching the rest. I’m still writing the post on this. So, I’ll post the tut on selective bit modification later.

Thats all for now,

:)

Nah…. Semoga ada pencerahan setelah membaca artikel diatas. Lain kali klo ada waktu saya akan bikin tutorial versi gewe sendiri, maklum saya masih dalam masa Tugas Akhir kk…heheh

Sumber Asli ArtikelNya

1 Comment

Leave a comment