Search This Blog

Beginning Embedded Electronics - 2

Lecture 2 - How to Get Code Onto a Microcontroller

You can get all the parts for this lecture here. We also highly recommend that you get a multimeter with a 'continuity' setting. A good quality multimeter with this setting goes for ~$60 and as high as $300 for a really spectacular one. We like our $60 cheapo.

Sorry for the confusion. When these tutorials were written and photographed, we used the ATmega8. We now carry the newer ATmega168. You will find all ATmega168 information in the following pages, but the pictures will show an ATmega8.

I'm assuming you've got your 5V supply tested and working. Next, we need to insert the ATmega168 into the breadboard and connect up power and ground.

ATmega8 (works the same with ATmega168) straddling the middle row of the breadboard

You will need to slightly bend in the legs of the DIP (dual inline package) to get the ATmega168 to straddle the breadboard center. Be careful! Do not bend the pins too far inward. The pins of the ATmega168 should insert into the inner two most rows on the breadboard. I find it best to to insert one side and then slightly push the IC sideways until the other side of pins can insert into the opposite row on the breadboard. Confusing, I know.

Note: The 5V 'rail' is the horizontal row of holes next to the red line. You should have a wire connecting your 5V power regulator circuit to one hole on the 5V rail. This will energize all the holes next to the red line with 5V. This is true about the blue line as well. All the horizontal holes next to the blue line are connected together. One of these holes should be connected to the ground pin on your voltage regulator, and to the ground connection of your wall wart. You can connect the VCC pins on the ATmega168 to any holes along the 5V rail, and you connect the GND pins on the ATmega168 to any hole along the blue GND rail.

Oh, hey! If no one ever told you, there is a really simple way to figure out where pin 1 is on an IC. The manufacturer of anything polarized (tantalum caps, electrolytic caps, LEDs, ICs, etc) will always put some sort of marking on the device to indicate the how the device is supposed to be oriented. For ICs, there is a small dimple on one end of the IC. The blue arrow in the picture is pointing to this dimple. The orange arrow points at pin 1, and the blue labels show how the pin numbers increase.

Pin labeling on an IC

Counting from the dimple, pin 1 is on the left and increases down the left side of the IC. The pin numbers jump to the right side row of pins and count up. See image from the ATmega168 datasheet below.

The ATmega168 should be in the breadboard, pin 7 (VCC) and pin 20 (AVCC) should be connected to your 5V rail and pins 8 and 22 (GND) should be connected to GND on your bread board. If you turn your power circuit on, the ATmega168 is now running, but it has nothing to run!

Actually this is not wholly true - there is one more connection that needs to be made before the ATmega168 starts running code. The RESET pin on the ATmega168 needs to be connected to VCC. You can either wire the RESET pin directly to 5V or you can 'tie it high' by connecting the RESET pin to VCC through a resistor. This will allow you to add a momentary reset button. What's this? The reset line on the ATmega168 is exactly what it sounds like - it resets the micro just like the reset works on your computer. If you look at the ATmega168 datasheet you'll see the RESET label is written with a line above it. This is nomenclature that indicates the reset pin is active low. What is 'active low'? The RESET pin is an input. A low level on this pin will put the micro into reset - i.e. the pin is activated with a low input, aka 'active low'. So unless you want your ATmega168 to stay in reset, you'll need to pull this pin high.

Now you need a reset button. A momentary switch is a switch that is activated (or closed) while you're touching it and open when you release the button. These are often called 'tactile switches' because they 'click' when you depress them giving the person pressing the button some 'tactile' feedback.

This is what the schematic part looks like. Notice pins 1 and 2 are connected together. 3 and 4 are connected together. And when you press 'de button, it temporarily connects 1/2+3/4 together.

Notice this button has five legs. If your button has five legs, just ignore the middle leg - it's not connected to anything and can be clipped off.

To test this button, whip out the trusty multimeter and set it to the continuity setting. This is the setting on nicer, mid-grade multimeters that is crucial to troubleshooting and experimenting. Touch the probes together - you should hear a tone indicating that there is continuity or a (nearly) zero resistance path between the probes. Insert the button into the breadboard and probe the two pins on one side of the button. If you picked pins 1/2 or 3/4 you should hear a tone. These pins are permanently connected inside switch. If you picked pins 1/3 or 2/4, you won't hear a noise - but hit the button. By hitting the button you will make an electrical connection between all four pins - and you should hear the tone! This means you have electrical continuity.

The schematic shows pins 1 and 2 of the reset switch connected together (connected to ground) and pins 3/4 connected together (connected to !RESET) . In practice, you just need the switch to work. Play with your multimeter and find two pins that don't make noise when the button is not touched, and do make noise when the button is depressed. Use these two pins.

The schematic shown above is what we're going for. The 10K resistor 'pulls' the reset pin high during normal activity. By pulling the reset pin high, the ATmega168 runs normally. When you push the reset switch (S2), the reset pin sees a continuous connection to ground. Since the resistance through the depressed switch is nearly zero, it wins (compared to the resistance of the 10K resistor!) and the reset pin is pulled low, RESET is activated and the ATmega168 goes into reset. Release the button and the reset pin is pulled high again and the ATmega168 comes out of reset. Nifty!

ATmega168 pinout

See the dimple from the ATmega168 datasheet? Looking at the top of the IC (legs down), with the dimple to the top, pin numbers increase starting from 1 in the top left corner. This is how every IC pin is number. However, the orientation marking varies a bit between manufacturers and between packaging types. Look for a non-congruent marking like a dimple, small dot, white arrow, a notched corner - anything that makes that area of the chip different from the other parts of the chip probably indicates pin 1. When in doubt, check the datasheet.

Reset wired next to a ATmega8 (same applies for the ATmega168)

Learn how to use the the continuity setting on your multimeter. It will be vital to troubleshooting down the road!

Each microcontroller manufacturer has a different method to get code in the flash memory of the micro. In the past few years there has been emphasis placed on ISP or "in system programming". ISP allows you to program the IC without having to disconnect the microcontroller from the application. This is not trivial! History was much more painful. Atmel has designed a relatively straight forward method that requires the control of a few pins (6 total). Because of this simple interface, the hardware programmer that is required to connect your computer to this SPI interface is very straight forward (cheap!) as well.

The red stripe indicates the location of Pin 1

Remember how we identified pin1 on the IC from the dimple? Well connectors also need polarization so that we don't reverse the orientation of the connector and fry things. Unfortunately the way connectors are numbered is opposite that of ICs. In the picture of the ISP connector, you see the red stripe indicating pin 1. An IC counts sequentially down one side. Connectors on the other hand, increase pin numbers, back and forth, as you work your way down the connector.

The programming chain looks something like this:

  1. There is a free C compiler called AVR-GCC. User writes code in C and then compiles that code into HEX files

  2. AVR-GCC can be installed on the Windows platform with an easy WinAVR install program

  3. The user gets this HEX code onto an AVR via the ISP pins

  4. Both a serial port programmer and a parallel port programmere have been designed to connect the computer port to the AVR ISP pins

  5. The computer runs a command line program to transfer the HEX file from the computer, to the serial or parallel port, and out to the AVR ISP pins

  6. The micro runs the machine code (*.HEX files) once powered or reset

What's a C compiler? This is a program that inputs a program written in the C language and outputs a HEX file. We prefer to program in C because it is easier for us than assembly and more flexible than BASIC.

What's a HEX file? This is a file that contains various hexidecimal characters. These hex 'codes' represent machine instructions that the ATmega168 understand. This file is what gets sent down to the programmer, and the programmer loads these machine instructions onto the ATmega168.

Before we can get too crazy, download and install WinAVR on the computer that you will be doing your code development on. If this link goes out of date, a google search should take you straight to it. The windows install should be fairly straight forward - follow all the defaults. WinAVR contains a version of the GCC compiler and various other tools including avrdude and Programmer's Notepad. avrdude is a simple command line program that takes a HEX file and sends it to the serial or parallel port for programming onto an Atmel microcontroller.

Working backwards up this list, I'll provide you with an example 'Hello World' HEX file that will prove that everything is working correctly on your micro. With any micro controller board, the first trick is always to get an LED to blink. This is the 'Hello World' of embedded systems. Guess what blink_1MHz.hex does?

With the blink hex file in hand, you now need to get it onto the micro. You will need to connect the AVR-PG1 (or the AVR-PG2) to the ATmega168. The easiest way to do this is with 9 wires running from your breadboard to the 10-pin connector on the ISP connector on the AVR-PG1/PG2.

Jamming wires into the ISP connector is not a good long-term solution but for the sake of getting the LED to blink, it'll do. I've cut short wires and stripped both ends. One stripped end is inserted into the end of the black programming connector, the other end is inserted into the breadboard.

The AVR-PG2 parallel programmer wired into the ATmega168. I've also wired up two 0.1uF caps. These decoupling caps are placed near the VCC and GND pins on the ATmega168 to help reduce noise into the IC. You may think you have a straight DC 5V but not really - these 0.1uF caps help reduce ripple on the 5V line. Yes, the ATmega168 will probably run without them but they're good to have installed.

AVR ISP Note: You really do have to wire all 4 GND pins. You cannot wire just one of the GND pins on the ISP connector.

Additionally we need an LED to control. This can be tied to any GPIO pin. PC0 looks like a good spot.

The resistor/LED order does not matter - just remember (from Tutorial 1) that you must have the resistor! The GPIO pin doesn't actually matter. blink_1MHz.hex will toggle all the pins on all ports so you can hook the resistor to any pin. As you add more peripheral hardware you will want to dedicate some pins for alternate use (such as TX and RX pins for serial communication).

You're getting closer! Time to program the chip!

Once WinAVR is installed, you should have a few new icons on your desktop. Programmers Notepad is a nice code editor and highlighter.

What's a code editor/highlighter? When programming, you will need a text editor on your computer so that you can create (type) code. Once you've created this 'code' on your computer (inside the code editor) you will pass this code to the compiler (you will click a button that runs the compiler with the C file you've typed) and the compiler will create a HEX file (assuming there are no problems or typos in your code). The highlighter? When creating code, it's often nice to have various parts of your program color coded so that you can tell a common things like for( ) and #define. This highlighting helps a lot when programming.

Use whichever text tool you like. Notepad will work, but is pretty rudimentary. I also likeJFE from my PIC days. Both have a 'tools' option which is great but JFE is better in my opinion because it lists the C functions that you can double click on and navigate to. If there is a way to do a similar trick in Programmer's Notepad 2, please let me know! Because Programmers Notepad v2 (aka PN2) comes with the WinAVR installation, we'll use it!

AVR-GCC is extremely powerful, very complex, and difficult to use initially. I am used to passing a *.c file to a PIC compiler (CC5x) and getting a HEX file back out. No fuss, no mess. Believe you me, the pain of getting AVR-GCC up and running is worth it. AVR-GCC is a truly nice compiler, and it's free. I've included a stock Makefile and blink_1MHz.c file inblink_1MHz.zip to get you started. I am by no means a Linux or make type of person. All you need to know is that when you type 'make' at the command prompt, the compiler is going to look for a file called 'Makefile' (no file extension!) and use that file to direct how to compile your C file.

These are the only two files you should need to get blink to compile. Open up blink_1MHz.c in programmer's notepad and click on Tools->Make All. This is the same as typing 'make all' from the command prompt from what ever directory you saved these two files. For example

C:\Code\Blink>make all

should compile your code as well. It's just a bit easier to do this through the Programmer's Notepad interface rather than toggling back and forth to the Command Prompt window. Once you have successfully compiled the C file into a HEX file, you now need to get that hex file onto the AVR. It's finally time to power up your system! The cheap AVR programmers require the target (that's your breadboard) to provide power to the programmer (that's the AVR-PG1 or PG2). Power up your bread board - you should see the power LED come on. From here on out, I will assume you're using the AVR-PG2 parallel port programmer.

There is only two spots in the makefile that you should be concerned about at this time. These two spots are located under the  programming options section. This makefile is huge, but scroll down to the Programming Options (avrdude) section. Now put a '#' in front of lines you want to comment out.

If you're using the AVR-PG1 (serial port programmer) you edit like this:

#AVRDUDE_PROGRAMMER = stk200
AVRDUDE_PROGRAMMER = ponyser

# com1 = serial port. Use lpt1 to connect to parallel port.
#AVRDUDE_PORT = lpt1
AVRDUDE_PORT = COM1

If you're using the AVR-PG2 (parallel port programmer) you edit like this:

AVRDUDE_PROGRAMMER = stk200
#AVRDUDE_PROGRAMMER = ponyser

# com1 = serial port. Use lpt1 to connect to parallel port.
AVRDUDE_PORT = lpt1
#AVRDUDE_PORT = COM1

Of course the port numbers depend on your specific computer but once you get things working, you'll be set for life. Assuming you've edited and saved your makefile, go back to PN2. With your breadboard powered, click Tools->Program. This will send the command 'make program' to the command prompt. If everything is setup correctly, you should have successfully loaded blink_1MHz.hex onto your target ATmega168 and your LED should be blinking.

If you get an error :

can't open device "giveio"

Then read this page. Basically you need to copy the giveio.sys file from C:\WinAVR/bin to the C:\Windows directory, then type install_giveio.bat at the command prompt.

Typical Problems:

If you still are not able to program the AVR - this is where 99% of first time users end up. Dig in and troubleshoot.

Are the ISP connections correct? It's easy to get the ISP connector backwards. Take a look at the photos above.

Is there a loose wire? Pull out the multimeter and check that you've got 5V being delivered to the VCC and GND pins on the ATmega168. Do the wires going into the ISP connector have a good solid connection?

Do you have your ATmega168 connected to both power and ground?

Is your 5V supply outputting 5V?

Do you have the right COM port or LPT port selected in your makefile?

There is a multitude of things to check. It's hard! I know. But once you get things correctly set up, and that LED blinks - it will feel fantastic!

Ok - I'm going to assume that you got the code correctly loaded onto the AVR and that the LED is blinking. Congratulations! You are now well on your way to a whole world of pain! Once you get one thing working, it's hard to stop! GPS, datalogging, RF, PCB layout - it's all just a couple hops away.

You can get all the parts for this lecture here.

Here are some additional resources for AVR programming:

1 comment:

SpAz said...

Neat, I got a kit without ISP, but once I get better with C and AVR I will make a parallel port in system programmer.

My microcontroller projects are on
www.Nerdful.com
.