Microprocessor

FROGGA - My First Microcontroller

Welcome to my - and propably your - first microcontroller programming. On this page I put toghether a little tutorial about how to get started with programming microcontrollers. I was a total newbie and I still don't have much knowledge about electronics. But that's what you can benefit from! All I explain to you is like talking to a 3 year old. That's the way I wish I had been presented all this.
The end of that tutorial will be a GameBoy-like device, playing a Frogger-Clone.


a video of it

Hardware

Well, you can't program what you don't have, so you can get one of the already pre-assembled parts (I bought an AVR butterfly first) or you can start assembling you own. I had the feeling of being too much limited by the butterfly, so I built my own after a short "Hello World" on the butterfly.

The Board

Well, here's the assembly instruction for the board I built: First, I needed 5V DC current. You can't get that at the groceries, so I took a cheap 6V adapter, got a "7805 Positive Volt Regulator" and built this:

              C1
             100μF
+6V(in)------+-||-+
             |    |
           in|    |
       7805 []----+--GND
          out|    | 
             |    |
+5V(out)-----+-||-+
               C1
             100μF

The 7805 makes your >5V into a solid 5V power supply, smoothing out possible noise from the AC adapter. The center pin is connected to GND. BTW: GND is "ground", that's (-) and always gets a black cable. VCC is (+) and always gets a red cable.

Part-List:
  • Must Have:
  • a small pair of pliers
  • a small screwdriver (used for keeping small cables down when soldering)
  • a small vice or some clip to hold parts when soldering
  • a multimeter (for measuring resistances)
  • Soldering gun
  • Solder, 0.5mm
  • 5m Cable in various colors (at least 10 colors), 0.14mm
  • 1x barod with pinholes + conductor paths on the back (yes, that's the back side)
  • ATmega32, 8MHz
  • Sockel
  • 10x Resistors 10kΩ, 100Ω
  • 10x Ceramic-Capacitors 47pF
  • 10x " 100nF
  • 1x Quarz (Slim) 8 MHz
  • 10x Capacitor 27pF
  • 10x LED's for 5V + resistances - ask at the shop
  • 1x a 5-way button
  • 1x Parallel Port Connector (kill an old printer cable)
  • a bunch of LEDs in fancy colors
  • Optional:
  • an LCD (I used one from Pollin with 128x64 pixels)
  • a piezo "speaker", 5V
  • 2-row pin connector stripes. Get 4 bars of them. Male and female.

Then put the chip on an empty circuit board. Make sure the board has at least the amount of pinholes for your processor. My board was 19 pinholes wide and the chip was 40 pins. That's not funny.
                                          :ISP:
        R1        ------------------------RESET
        10kR     /                   -----SCK
    +5V-[]-+-----+-Reset::PC5       / ----MISO
           |       ---::::PC4       |/ ---MOSI
         C1-       ---::::PC3       ||/   GND---GND
       47pF-   *2  ---::::PC2 *1    |||
           |   |   ---::::PC1 |     |||
     GND--/    V   ---::::PC0 V     |||
     +5V-----------VCC:::AGND---GND |||
     GND-----------GND:::AREF       |||
            -------XTAL1:AVCC---+5V |||
      +-+--/   ----XTAL2::SCK------/ ||      
   C2 - |     /    ---:::MISO-------/ |      
  27pF- |     |    ---:::MOSI---------/       
      | |     |    ---::::---                
GND---+ ^     |    ---::::---
      | Quarz |        ^     
    C2= Y8MHz |     ATmegaXX 
  27pF| |     |              
      +-+-----/              

    *1: 100nF between AVCC + AGND, close to the controller
    *2: 100nF between VCC  +  GND, close to the controller
Did I mention that I'm a ASCII-addicted? That is the reaon why I write "R" instead of Ω, and "u" instead of μ. Keep that in mind and have mercy on me.
Anyway. The processor shown here is just a symbolic one for _any_ AVR processors. I used an ATmega32L that runs at 8MHz and has 2KB RAM - that's a lot for microprocessors. You have to get the specs for your processor from AVR's website and look up/count the pins for the names I used up there.
If you're done, take out your multimeter. Connect one pin to the very beginning of GND on your board, and the other one to the pin you connected GND to. Is the resistance almost zero? Then continue with all the other connections you have made.
Beleive me. It's easier to do it now that later, when you have it all conencted.

Software

You need some software to get started. First you might need WinAVR. It's the GCC compiler for AVR devices. Then I got the AVR Studio (Version 4 here) and the latest service pack. Last a program called "PonyProg", because AVR Studio cannot access the "high end" ISP cable I soldered.

Basic Programming

Well, I assume you know about { } and [ ] braces used in C / C++, so if you don't get a book or read any other tutorial first. I read "teach yourself C in 21 days" which was rather good in my opinion.
The processor has pins and you can check if they're high (+5V at the pin) or low (GND is at the pin). You can also program the chip to go high or low.

Setting the pin-state (Output):


That's rather easy: The Pins PDx are called "PORTD". PBx=PORTB and so on. First you set the pin to be an output port. That's by writing:
DDRx |= (1 << p);

Where x is the port "name" and p is the port index. If you want PB5 to be your output port, you write:
DDRB |= (1 << 5);

DDR means "data direction register" and a 0 bit indicates input, a 1 bit indicates output. A mnemonic is "Data Dump Register", indicating 1 for dumping (output) and 0 for non-duimping (input). You get acustomned to that very soon.
For accessing the whole port as output write:
DDRB = 0xff;

Now, if you want to set the pin's value, just write:
PORTx |= (1 << p);

and if you want to clear the bit (put it "low"), write:
PORTx &= ~(1 << p);


Reading Pin State (Input)


First, set the DDR to input for a pin:
DDRB &= ~(1 << 5);

That's just clearing the bit. Then activate the pull-up resistance for that pin. You just write bit 1 for that PORT as if you were setting it "high".
PORTB |= (1 << 5);

A "pullup resistance" is a resistance inside the chip, that keeps the pin "high" if you don't do anything. You simply have to connect the port to GND in order to "pull down" that resistance. This way you can access parts like buttons and switches very easily. See below. Then you can get the state of the pin with:
char IsBitHigh = PINx & (1 << p);

Right! Writing to a pin with "PORTx", reading from a pin with "PINx".

First Contact


If you soldered the thing above together, you can start writing you own program.
Well, I hated starting with a flashing LED - I wanted to go big in the first place. I was a fool. Take a short time to build this small tutorial LED project. I give you hints how to make that all in just a few minutes. It's the only way to see if your processor is working.
Launch the AVR Studio and build (hardware) the LED sample. Copy/paste the code from below into a new project. Hit the "compile" button and see the output window. It should not mention anything about errors.
The AVR studio created you a default/project_name.hex file. That's the program.
Now, connect you ISP cable to LPT1 and the circuit board, switch the power on, open PonyProg and configure it for your first upload. Open Menu: Setup/Interface Setup.
Select: Parallel, "Avr, ISP I/O", LPT1 and press "Probe" button. It should say: Hokay!
Then select menu: Device/AVR micro/ATmega32 (or whatever you have). Finally flash (=upload) the file using menu items:
File / Open (FLASH) Program File, select the .hex file
Command / Write Program (FLASH)
If everything goes smooth, your LED should start fading in/out now.

Extending the board


Next thing I did was soldering 5x2 pins on the board to make plugable connections to the port. I used this pin-arrangement:
   +---+
  1|o o|0
  3|o o|2
  5|o o|4
  7|o o|6
VCC|o o|GND
   +---+

Adding Devices

OK, now a processor without devices is rather boring, right? So here's my list of useful devices and how to program them.

LED - Light


For making a LED glow, put it between VCC and GND with a resistance of 100R attached. The LED will only work in one direction. like this:
 __-----__
/         
|         |
|  ____   |
|  |_ #   |
|     #|  |
|__|_|_|__|  R4
    |  |      100R
    |  +------[]----GND
VCC
        

Now connect a LED to ... say PORTC, PIN0 and connect through a 100R resistance to GND. I've not soldered this together, I just used a clip+cable thingy and conencted one clip to the pin C0 and the other end to the LED. Then I soldered the resistance to the LED (directly) and connected that end with a clip+cable thingy to the GND on my board.
If you connect the clip of C0 to VCC directly, it must shine when you turn on the power supply. Then try this code:
// Blinky.c
#include <avr/io.h>
#include <util/delay.h>


int main(int argc, char* argv[])
{
short i;
	// set PORTC, PIN0 for output
	DDRC = 0x01;
	for(;;)
	{
		for(i = 1; i <= 128; i*=2)
		{
			PORTC = i;
			_delay_loop_2(30000);
		}
		for(i = 128; i > 1; i -= i/2)
		{
			PORTC = i;
			_delay_loop_2(30000);
		}
	}
}
		

Button


Well, a button is simply a trigger you press and it returns you pressed/unpressed.
      R2
              ___  1kR
        PIN--/  ---[]---GND
        
That's easy, huh? Simply connect the pin through the trigger with GND and put a 1kR resistance in between. I bought a 5-button switch, which is basically a small 4-way directional pad that you can push down as a 5th button.
5-Button Switch
That's what it looks like. In order to find out which pins to connect to what I used my multimeter, conencted to one pin and tried all the others - moving the dpad in all directions for each pin. I found one, so one of these 2 pins must be GND, the other one is for the direction. I keept one pin, tried another for 2nd cable on multimeter and if it was OK, I got the GND, if not, the other one was GND.
I found out my button has this connection (top view):
  +----+
 E|oo o|GND
<-|oo o|->
  +----+
   |
   V		
		

For checking buttons I use this functions:
// Button.c
#include <avr/io.h>
// Key port - I have mine on PORTC
#define KEY_PIN PINC
#define KEY_DDR DDRC
#define KEY_PORT PORTC

// The pins for each direction
#define KEY_NULL	-1
#define KEY_UP		0
#define KEY_LEFT	1
#define KEY_DOWN	2
#define KEY_RIGHT	3
#define KEY_ENTER	4

volatile char KEY = KEY_NULL;
volatile char KEY_VALID=0;
void HandleKeys(void)
{
	if(KEY_VALID) return;

	for (char i=0;i<5;i++)
	{
		if(i!= KEY && !(KEY_PIN & (1 << ;i)) )
		{
			KEY_VALID = 1;
			KEY = i;
		}
	}
	// Key has been released
	if(!KEY_VALID && KEY!=KEY_NULL && (KEY_PIN & (1 << KEY)) )
		KEY=KEY_NULL;
}

// Is Key up/down now?
char GetKeyState(char key)
{
	return !(KEY_PIN & (1 << key) );
}

// whick key has changed to keydown
char GetKey(void)
{
char k;
    if (KEY_VALID)
    {
        k = KEY;
        KEY_VALID = 0;
    }
    else
        k = KEY_NULL;
    return k;
}
int main(int argc, char** argv)
{
	// switch to input mode
	KEY_DDR &= ~(KEY_LEFT|KEY_RIGHT|KEY_UP|KEY_DOWN|KEY_ENTER);
	// enable pullup resistances
	KEY_PORT|=  (KEY_LEFT|KEY_RIGHT|KEY_UP|KEY_DOWN|KEY_ENTER);

	for(;;)
	{
		HandleKeys();
		switch(GetKey())
		{
			...
		}
	}
}
		

Photo-Resistance



       R2      LDR       
       1kR     1kR
+5V  --[]------[]--- GND
             |
             V
            ADC
The ATmega32 (and many others) have a port called "ADC". That's an analog-digital converter. With it you can get a 16 bit number from you resitance. Might be you have to set some register first - I'll have to check.

LCD - A Display


Well, you can program whatever display you want. I chose one from Pollin electronics That's called: HP12542R-DYO and has a SED1565 (compatible) controller on board. It has a 128x64 pixel display, it is really cheap (about 8,-EUR) and an LED for backlight that works with +5V. Great!
The Display is split into 128 blocks with each 8 pixels height. If you can't hold the display data in RAM and then draw the whole graphics at once, you will not likely be able to acces every single pixel, but only a set of 8 pixels height. That is the reason, why I chose a Frogger remake - the cars move smooth horizontally, but stay in line vertically.

The Frogga Game

Hardware

Now, if you want to build the Frogga game, here's how to do that.
         Display:           PB0o--oPA0
             /RES-----------PB1o--oPA1
             CS-------------PB2o--oPA2
             A0-------------PB3o--oPA3
             R/W------------PB4o--oPA4
             E--------------PB5o--oPA5
                            PB6o--oPA6
+5V----+---(10kR)-.         PB7o--oPA7
    .--)--|100nF|-------- RESETo--oAREF
    |  '---------+----------VCCo--oGND------------+-GND
GND-+----|100nF|-' +--------GNDo--oAVCC-+-|100nf|-'
    '+-+-----------+ +-+--XTAL1o--oPC7  '-----------+5V
     | '--|27nF|-----+ | +XTAL2o--oPC6
     | ,-[Quarz-8MHz]--+ |  PD0o--oPC5             +-----+
     | '----------+------+  PD1o--oPC4-------------|enter|
     '----|27nF|--'         PD2o--oPC3-------------|right|
                            PD3o--oPC2-------------|down |
                            PD4o--oPC1-------------|left |
                            PD5o--oPC0-------------|up   |
                            PD6o--oPD7             |gnd  |--(1kR)--GND
                                                   +-----+

Pins PD0 to PD7 connect to D0 to D7 of the display
On the Display:
A------VCC
K----.-GND
n.c.-+
GND--'
Vcc----VCC
GND----GND
D7-----PD7
..     ..
D0-----PD0
E------PB5
R/W----PB4
Vcc----VCC
A0-----PB3
/CS1---GND
/RES---PB1
GND----GND
GND----GND

You can download the project files here:
Download Frogga
For any furhter reference contact me via www.glbasic.com