I've just started trying to use AVR's directly rather than use a dev board like an Arduino Uno. The problem I'm seeing is when I try to drive a bunch of LEDs on the output pins many of them are reading very low voltages much less then the expected 5V.
I am running the code off of a 14MHz crystal. I've set the fuses on the AVR to: lfuse: 0xFF hfuse: 0x89 The crystal connects to pins XTAL1 & XTAL2. Each lead of the crystal also connects to GND through a 22pF ceramic capacitor.
I've connected a .1uF electrolytic cap across VCC and GND and another across AVCC and GND with the cathode (-) connected to the GND terminal. There's also a 10uF electrolytic cap across my source terminals.
The connections to the ATMEGA32A are as follows: PB0-7: OPEN RESET: 10K resistor to VCC VCC : 5V GND : GND XTAL1: Crystal XTAL2: Crystal PD0-7: 510 ohm resistor to LED to GND PC0-7: 510 ohm resistor to LED to GND AVCC : 5V GND : GND AREF : 5V (Tried this OPEN as well. No changed) PA0-7: OPEN
PORTD seems to work just fine. I'm getting the full 4.6V drop from the AVR to ground on each of those pins. PORTC, however, is not working properly. As I go from C0 and up the voltage drop from each of those pins decrease as I move up PORTC. PC0 gives nearly the full 4.6V. It gradually decreases as I get to C7 which measures 2.2V.
Is there any particular reason for this to happen? Am I missing some type of connection the AVR needs? My very simple code and makefile are below.
main
#include <avr/io.h>
void setup();
void setup()
{
DDRD=0XFF;
PORTD = 0xff;
DDRC |= 0XfF;
PORTC = 0xff;
}
int main()
{
setup();
while(1)
{
}
return 0;
}
makefile
MCU = atmega32
# Target file name (without extension).
TARGET = main
AVRDUDE_PROGRAMMER = avrisp
AVRDUDE_PORT = COM3
OPT = s
FORMAT = ihex
SRC = $(TARGET).c
#SRC += TimerOne.cpp
EXTRAINCDIRS =
CLOCK = 14745600
CPU = F_CPU=$(CLOCK)
# Optional compiler flags.
# -g: generate debugging information (for GDB, or for COFF conversion)
# -O*: optimization level
# -f...: tuning, see gcc manual and avr-libc documentation
# -Wall...: warning level
# -Wa,...: tell GCC to pass this to the assembler.
# -ahlms: create assembler listing
CFLAGS = -g -O$(OPT) \
-funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall \
$(patsubst %,-I%,$(EXTRAINCDIRS))
# -lm = math library
LDFLAGS = -lm
AVRDUDE = avrdude
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) -b 19200
AVRDUDE_FLAGS += -v
# ---------------------------------------------------------------------------
# Define directories, if needed.
DIRAVR = c:/winavr
DIRAVRBIN = $(DIRAVR)/bin
DIRAVRUTILS = $(DIRAVR)/utils/bin
DIRINC = .
DIRLIB = $(DIRAVR)/avr/lib
# Define programs and commands.
CC = avr-g++ -D$(CPU) -D$(MCU)
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
REMOVE = rm -f
COPY = cp
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
ELFSIZE = $(SIZE) -AC --mcu=$(MCU) $(TARGET).elf
# Define all object files.
OBJ = $(patsubst src%,obj$(VERSION)%,$(patsubst %.c,%.o,$(SRC)))
# Define all listing files.
LST = $(ASRC:.S=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target: make program!
all: main.hex
main.hex: main.elf
$(OBJCOPY) -O $(FORMAT) -R .eeprom main.elf main.hex
main.elf: main.o
$(CC) $(ALL_CFLAGS) main.o --output main.elf $(LDFLAGS)
main.o:
@echo
@echo $(MSG_COMPILING) $<
$(CC) -c $(ALL_CFLAGS) main.c -o $@
# Program the device.
program: $(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) -U flash:w:$(TARGET).hex
# Flash the device
flash:
$(AVRDUDE) $(AVRDUDE_FLAGS) -U lfuse:w:0xFF:m -U hfuse:w:0x89:m
# Target: clean project.
clean: begin clean_list finished end
clean_list :
@echo
@echo $(MSG_CLEANING)
$(REMOVE) $(TARGET).hex
$(REMOVE) $(TARGET).eep
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).cof
$(REMOVE) $(TARGET).elf
$(REMOVE) $(TARGET).map
$(REMOVE) $(TARGET).obj
$(REMOVE) $(TARGET).a90
$(REMOVE) $(TARGET).sym
$(REMOVE) $(TARGET).lnk
$(REMOVE) $(TARGET).lss
$(REMOVE) $(TARGET).o
# Listing of phony targets.
.PHONY : all begin finish end sizebefore sizeafter gccversion coff extcoff \
clean clean_list program
It appears that I only need to ask the question before I finally find the answer on my own after days of searching. As is often the case the answer was in the datasheet. The problem was the fuse bits. By default the JTAG interface is enabled which is part of PORTC. That was why PORTC was not working right. I updated the HFUSE bits from 0x89 to 0xC9. That disabled the JTAG interface and PORTC acted like normal IO ports.