Thursday 19 May 2016

Microcontrollers part IV: The First Taste of Programming

As far as I know, there are two programming languages to program AVR: assembly and C. Assembly is a very low-level language that gets you as close to the machine level as possible. It allows to use the computing resources as efficiently as it can get but takes an ass-load more work to write and debug.

Even very simple operations like summing up three numbers from the memory can take like five lines of code to perform in assembly whereas in C one line does the job. Also C is somewhat tedious in modern standards but certainly less than assembly, making it my choice for microcontroller programming.

Finally, it's time to get cooking! Let's start with something simple: a blinking LED. What follows is a compilation from the AVR Libc Reference Manual, the ATtiny85 datasheet and my previous knowledge on the AVR programming (which is not very deep).

Let's use the pin PB0 to control the LED (see the ATtiny85 pinout here). Usually one should use a resistor to limit the amount of current passing through the LED. However, since I don't have any right now the I/O pin can output max. 40 mA of current, I can connect it directly between the PB0 and GND pins. (Note that this shortens the lifespan of both the LED and chip, though.)

Next we need the program. As usual, I open my text editor and start off by writing down definitions and includes:

 #define F_CPU 1000000UL  
 #include "avr/io.h"  
 #include "util/delay.h"  

The first line defines the clock frequency which I chose to be 1 MHz. The header file "avr/io.h" contains the definitions for I/O operations and "util/delay.h" contains the function declaration for _delay_ms() that I'll use to slow down the blinking. The rest of the program is written in the main function which is very short:

 void main(){ 
 
   DDRB = 0b0001; 
 
   while (1){  
     PORTB = 0b0001;  
     _delay_ms(250);  

     PORTB = 0b0000;  
     _delay_ms(250);  
   }  
 }  

This is the actual program that the chip starts to executed immediately after the power is connected. The first line sets the direction of the I/O pins through DDRB (Data Direction Register B). This is done by a binary number 0b0001. The prefix 0b stands for the binary number and the bits after that correspond to the pins PB3, PB2, PB1 and PB0. Since we want PB0 to be an output we set that to 1. All the other bits can be whatever, in this case 0:s or inputs.

After setting data directions, the program enters into an eternal loop that blinks the LED. The first line in the loop sets the LED on through PORTB. Here the pin-bit correspondence is the same as in the former case but the action depends how the pins are configured. If the pin set as an output, then 1 bit sets the output to HIGH and 0 to LOW. On the other hand, if the pin is configured to an input, then setting the bit controls whether the pull-up resistor is on or not. I'll talk more about this later.

After setting PORTB, the program waits for 250 milliseconds. After that it sets PORTB again but now putting the last bit to 0 i.e. PB0 to LOW state turning off the LED. The program again waits for 250 ms and then moves in the beginning of the while loop. The loop is repeated until the power source is detached from the microcontroller.

The finished program needs to be compiled and written to the chip. I saved my file as main.c and typed the following lines into the terminal:

avr-gcc -mmcu=attiny85 -Os -c main.c  
avr-gcc -mmcu=attiny85 -o main.elf main.o  
avr-objcopy -j .text -j .data -O ihex main.elf main.hex  

The first line compiles main.c, the second one links it to the libraries, and the last one produces an Intel hex file that can be uploaded to the microcontroller. Once again, if the model of the chip is different, the first two lines have to be changed accordingly.

The last step is to write the program to the chip. Plug the following into the terminal:

 sudo avrdude -p attiny85 -C ~/avrdude_gpio.conf -c pi_1 -e -U flash:w:main.hex  

If the connections and the alignment of the celestial bodies are as they should, the microcontroller should now be programmed! And here's what the result looks like:


Works like a charm! Even though I forgot to connect the operating voltage to the RESET pin.. Apparently the circuit works without it for the demo purpose but it is very unstable. Now just touching the pin with a finger causes the chip to reset which surely is unwanted behavior. Always remember to wire the RESET pin as well!

--

This concludes the Microcontrollers series that I intended as a tutorial to DIY microcontroller electronics. From the basics to setting up tools, we've now have acquired the equipment and knowledge to pursue for more complicated applications, being a small but important step closer to a working retro-style gaming system. The quest continues!
Original: https://en.wikipedia.org/wiki/File:It's_dangerous_to_go_alone!_Take_this..png

No comments:

Post a Comment