Electronic – Blinking LED with ATMega8 won’t blink

atmegaavravr-gccavrdudeled

As I'm a complete novice, I thought I'd start with something really simple: making a led blink. According to several websites, this is something everyone should be able to do… Hmmm… In my case, the LED doesn't do anything. It stays dark. Why?

This is the program I've written (on a Ubuntu 12.04 machine):

#define F_CPU 1000000UL

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

void sleep(int milliseconds)
{
while (milliseconds > 0)
{
    _delay_ms(1);
    milliseconds--;
}
}

int main()
{
// set lowest bit to output in DDRB register
DDRB |= 0x01;

while(1)
{
    // switch led on
    PORTB &= 0x01;
    sleep(500);

    // switch led off
    PORTB &= 0x00;
    sleep(500);
}

return 0;
}

Then I followed these steps:

  1. Compiled my program:

    avr-gcc -mmcu=atmega8 test-001-blinkingled.c -o test-001-blinkingled.o -Os

  2. Hex

    avr-objcopy -j .text -j .data -O ihex test-001-blinkingled.o test-001-blinkingled.hex

  3. Uploaded to the microcontroller (using an AVRISPmkII):

    sudo avrdude -p m8 -P usb -c avrispv2 -U flash:w:test-001-blinkingled.hex -F -v

with following result:

avrdude output

This is a picture of my very basic circuit:
(I use an old 9V adapter for power, so I used 2 resistors to regulate the voltage to 4.95V)

My breadboard circuit

What am I doing wrong? If you see other strange or stupid things, please educate me!

Best Answer

Four problems

  1. You are using a resistor voltage divider to power your MCU. Bad. Bad bad. You need a proper regulator. Or a USB (IE 5v) power supply. Heck, use 3 AA batteries instead of a 9v if you don't have a regulator. The ATMega line can take what, 2.5 to 5v normal range? You have nothing that really depends on a full 5v, no clock sensitive/dependent code.

  2. You only power one side of the ATMega. There are two power and two ground pins. They are NOT redundant. One set is Digital VCC and GND, the other is Analog VCC and GND. Ideally, you should use an inductor between the DVCC and AVCC pins, for noise sensitive analog circuits, but at the minimum, DVCC and AVCC should be connected, as should DGnd and AGnd.

  3. A decoupling cap for both (~0.1uf) is recommended as well, but you could just use one for DVCC/DGnd.

  4. You use a Bitwise And (&). Only bits that are already set, will be set. [0 & 1 = 0] [1 & 0 = 0] [0 & 0 = 0] [1 & 1 = 1]
    Your code will never toggle the led on. You need a Bitwise OR | (the vertical bar or pipe) to turn it on. A Bitwise And with an inverted bit will turn it off (PortB &= ~0x01). Alternatively, a Bitwise XOR ^ (caret symbol) can be used to toggle.

PORTB |= 0x01;
sleep(500);

PORTB &= ~0x01;
sleep(500);

PORTB ^= 0x01;
sleep(500);

AVR Freaks has a great tutorial on bitwise operations here, for general C but they also focus on AVR/Atmega/Attiny, including port/bit manipulation.