Started following some tutorial on att85 usi. Downloaded example code from make avr book.

This commit is contained in:
Dan
2022-09-20 01:08:01 -04:00
parent d0cbc0000e
commit 361a828c46
295 changed files with 68746 additions and 0 deletions

View File

@@ -0,0 +1,196 @@
##########------------------------------------------------------##########
########## Project-specific Details ##########
########## Check these every time you start a new project ##########
##########------------------------------------------------------##########
MCU = atmega168p
F_CPU = 8000000UL
BAUD = 9600UL
## Also try BAUD = 19200 or 38400 if you're feeling lucky.
## A directory for common include files and the simple USART library.
## If you move either the current folder or the Library folder, you'll
## need to change this path to match.
LIBDIR = ../../AVR-Programming-Library
##########------------------------------------------------------##########
########## Programmer Defaults ##########
########## Set up once, then forget about it ##########
########## (Can override. See bottom of file.) ##########
##########------------------------------------------------------##########
PROGRAMMER_TYPE = usbtiny
# extra arguments to avrdude: baud rate, chip type, -F flag, etc.
PROGRAMMER_ARGS =
##########------------------------------------------------------##########
########## Program Locations ##########
########## Won't need to change if they're in your PATH ##########
##########------------------------------------------------------##########
CC = avr-gcc
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
AVRSIZE = avr-size
AVRDUDE = avrdude
##########------------------------------------------------------##########
########## Makefile Magic! ##########
########## Summary: ##########
########## We want a .hex file ##########
########## Compile source files into .elf ##########
########## Convert .elf file into .hex ##########
########## You shouldn't need to edit below. ##########
##########------------------------------------------------------##########
## The name of your project (without the .c)
# TARGET = blinkLED
## Or name it automatically after the enclosing directory
TARGET = $(lastword $(subst /, ,$(CURDIR)))
# Object files: will find all .c/.h files in current directory
# and in LIBDIR. If you have any other (sub-)directories with code,
# you can add them in to SOURCES below in the wildcard statement.
SOURCES=$(wildcard *.c $(LIBDIR)/*.c)
OBJECTS=$(SOURCES:.c=.o)
HEADERS=$(SOURCES:.c=.h)
## Compilation options, type man avr-gcc if you're curious.
CPPFLAGS = -DF_CPU=$(F_CPU) -DBAUD=$(BAUD) -I. -I$(LIBDIR)
CFLAGS = -Os -g -std=gnu99 -Wall
## Use short (8-bit) data types
CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
## Splits up object files per function
CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS = -Wl,-Map,$(TARGET).map
## Optional, but often ends up with smaller code
LDFLAGS += -Wl,--gc-sections
## Relax shrinks code even more, but makes disassembly messy
## LDFLAGS += -Wl,--relax
## LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm ## for floating-point printf
## LDFLAGS += -Wl,-u,vfprintf -lprintf_min ## for smaller printf
TARGET_ARCH = -mmcu=$(MCU)
## Explicit pattern rules:
## To make .o files from .c files
%.o: %.c $(HEADERS) Makefile
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<;
$(TARGET).elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LDLIBS) -o $@
%.hex: %.elf
$(OBJCOPY) -j .text -j .data -O ihex $< $@
%.eeprom: %.elf
$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=0 -O ihex $< $@
%.lst: %.elf
$(OBJDUMP) -S $< > $@
## These targets don't have files named after them
.PHONY: all disassemble disasm eeprom size clean squeaky_clean flash fuses
all: $(TARGET).hex
debug:
@echo
@echo "Source files:" $(SOURCES)
@echo "MCU, F_CPU, BAUD:" $(MCU), $(F_CPU), $(BAUD)
@echo
# Optionally create listing file from .elf
# This creates approximate assembly-language equivalent of your code.
# Useful for debugging time-sensitive bits,
# or making sure the compiler does what you want.
disassemble: $(TARGET).lst
disasm: disassemble
# Optionally show how big the resulting program is
size: $(TARGET).elf
$(AVRSIZE) -C --mcu=$(MCU) $(TARGET).elf
clean:
rm -f $(TARGET).elf $(TARGET).hex $(TARGET).obj \
$(TARGET).o $(TARGET).d $(TARGET).eep $(TARGET).lst \
$(TARGET).lss $(TARGET).sym $(TARGET).map $(TARGET)~ \
$(TARGET).eeprom
squeaky_clean:
rm -f *.elf *.hex *.obj *.o *.d *.eep *.lst *.lss *.sym *.map *~ *.eeprom
##########------------------------------------------------------##########
########## Programmer-specific details ##########
########## Flashing code to AVR using avrdude ##########
##########------------------------------------------------------##########
flash: $(TARGET).hex
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U flash:w:$<
## An alias
program: flash
flash_eeprom: $(TARGET).eeprom
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -U eeprom:w:$<
avrdude_terminal:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nt
## If you've got multiple programmers that you use,
## you can define them here so that it's easy to switch.
## To invoke, use something like `make flash_arduinoISP`
flash_usbtiny: PROGRAMMER_TYPE = usbtiny
flash_usbtiny: PROGRAMMER_ARGS = # USBTiny works with no further arguments
flash_usbtiny: flash
flash_usbasp: PROGRAMMER_TYPE = usbasp
flash_usbasp: PROGRAMMER_ARGS = # USBasp works with no further arguments
flash_usbasp: flash
flash_arduinoISP: PROGRAMMER_TYPE = avrisp
flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P /dev/ttyACM0
## (for windows) flash_arduinoISP: PROGRAMMER_ARGS = -b 19200 -P com5
flash_arduinoISP: flash
flash_109: PROGRAMMER_TYPE = avr109
flash_109: PROGRAMMER_ARGS = -b 9600 -P /dev/ttyUSB0
flash_109: flash
##########------------------------------------------------------##########
########## Fuse settings and suitable defaults ##########
##########------------------------------------------------------##########
## Mega 48, 88, 168, 328 default values
LFUSE = 0x62
HFUSE = 0xdf
EFUSE = 0x00
## Generic
FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) \
$(PROGRAMMER_ARGS) $(FUSE_STRING)
show_fuses:
$(AVRDUDE) -c $(PROGRAMMER_TYPE) -p $(MCU) $(PROGRAMMER_ARGS) -nv
## Called with no extra definitions, sets to defaults
set_default_fuses: FUSE_STRING = -U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m -U efuse:w:$(EFUSE):m
set_default_fuses: fuses
## Set the fuse byte for full-speed mode
## Note: can also be set in firmware for modern chips
set_fast_fuse: LFUSE = 0xE2
set_fast_fuse: FUSE_STRING = -U lfuse:w:$(LFUSE):m
set_fast_fuse: fuses
## Set the EESAVE fuse byte to preserve EEPROM across flashes
set_eeprom_save_fuse: HFUSE = 0xD7
set_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
set_eeprom_save_fuse: fuses
## Clear the EESAVE fuse byte
clear_eeprom_save_fuse: FUSE_STRING = -U hfuse:w:$(HFUSE):m
clear_eeprom_save_fuse: fuses

View File

@@ -0,0 +1,137 @@
/*
Quick and dirty functions that make serial communications work.
Note that receiveByte() blocks -- it sits and waits _forever_ for
a byte to come in. If you're doing anything that's more interesting,
you'll want to implement this with interrupts.
initUSART requires BAUDRATE to be defined in order to calculate
the bit-rate multiplier. 9600 is a reasonable default.
May not work with some of the older chips:
Tiny2313, Mega8, Mega16, Mega32 have different pin macros
If you're using these chips, see (e.g.) iom8.h for how it's done.
These old chips don't specify UDR0 vs UDR1.
Correspondingly, the macros will just be defined as UDR.
*/
#include <avr/io.h>
#include "USART.h"
#include <util/setbaud.h>
void initUSART(void) { /* requires BAUD */
UBRR0H = UBRRH_VALUE; /* defined in setbaud.h */
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif
/* Enable USART transmitter/receiver */
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); /* 8 data bits, 1 stop bit */
}
void transmitByte(uint8_t data) {
/* Wait for empty transmit buffer */
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = data; /* send data */
}
uint8_t receiveByte(void) {
loop_until_bit_is_set(UCSR0A, RXC0); /* Wait for incoming data */
return UDR0; /* return register value */
}
/* Here are a bunch of useful printing commands */
void printString(const char myString[]) {
uint8_t i = 0;
while (myString[i]) {
transmitByte(myString[i]);
i++;
}
}
void readString(char myString[], uint8_t maxLength) {
char response;
uint8_t i;
i = 0;
while (i < (maxLength - 1)) { /* prevent over-runs */
response = receiveByte();
transmitByte(response); /* echo */
if (response == '\r') { /* enter marks the end */
break;
}
else {
myString[i] = response; /* add in a letter */
i++;
}
}
myString[i] = 0; /* terminal NULL character */
}
void printByte(uint8_t byte) {
/* Converts a byte to a string of decimal text, sends it */
transmitByte('0' + (byte / 100)); /* Hundreds */
transmitByte('0' + ((byte / 10) % 10)); /* Tens */
transmitByte('0' + (byte % 10)); /* Ones */
}
void printWord(uint16_t word) {
transmitByte('0' + (word / 10000)); /* Ten-thousands */
transmitByte('0' + ((word / 1000) % 10)); /* Thousands */
transmitByte('0' + ((word / 100) % 10)); /* Hundreds */
transmitByte('0' + ((word / 10) % 10)); /* Tens */
transmitByte('0' + (word % 10)); /* Ones */
}
void printBinaryByte(uint8_t byte) {
/* Prints out a byte as a series of 1's and 0's */
uint8_t bit;
for (bit = 7; bit < 255; bit--) {
if (bit_is_set(byte, bit))
transmitByte('1');
else
transmitByte('0');
}
}
char nibbleToHexCharacter(uint8_t nibble) {
/* Converts 4 bits into hexadecimal */
if (nibble < 10) {
return ('0' + nibble);
}
else {
return ('A' + nibble - 10);
}
}
void printHexByte(uint8_t byte) {
/* Prints a byte as its hexadecimal equivalent */
uint8_t nibble;
nibble = (byte & 0b11110000) >> 4;
transmitByte(nibbleToHexCharacter(nibble));
nibble = byte & 0b00001111;
transmitByte(nibbleToHexCharacter(nibble));
}
uint8_t getNumber(void) {
// Gets a numerical 0-255 from the serial port.
// Converts from string to number.
char hundreds = '0';
char tens = '0';
char ones = '0';
char thisChar = '0';
do { /* shift over */
hundreds = tens;
tens = ones;
ones = thisChar;
thisChar = receiveByte(); /* get a new character */
transmitByte(thisChar); /* echo */
} while (thisChar != '\r'); /* until type return */
return (100 * (hundreds - '0') + 10 * (tens - '0') + ones - '0');
}

View File

@@ -0,0 +1,44 @@
/* Functions to initialize, send, receive over USART
initUSART requires BAUD to be defined in order to calculate
the bit-rate multiplier.
*/
#ifndef BAUD /* if not defined in Makefile... */
#define BAUD 9600 /* set a safe default baud rate */
#endif
/* These are defined for convenience */
#define USART_HAS_DATA bit_is_set(UCSR0A, RXC0)
#define USART_READY bit_is_set(UCSR0A, UDRE0)
/* Takes the defined BAUD and F_CPU,
calculates the bit-clock multiplier,
and configures the hardware USART */
void initUSART(void);
/* Blocking transmit and receive functions.
When you call receiveByte() your program will hang until
data comes through. We'll improve on this later. */
void transmitByte(uint8_t data);
uint8_t receiveByte(void);
void printString(const char myString[]);
/* Utility function to transmit an entire string from RAM */
void readString(char myString[], uint8_t maxLength);
/* Define a string variable, pass it to this function
The string will contain whatever you typed over serial */
void printByte(uint8_t byte);
/* Prints a byte out as its 3-digit ascii equivalent */
void printWord(uint16_t word);
/* Prints a word (16-bits) out as its 5-digit ascii equivalent */
void printBinaryByte(uint8_t byte);
/* Prints a byte out in 1s and 0s */
char nibbleToHex(uint8_t nibble);
void printHexByte(uint8_t byte);
/* Prints a byte out in hexadecimal */
uint8_t getNumber(void);
/* takes in up to three ascii digits,
converts them to a byte when press enter */

View File

@@ -0,0 +1,61 @@
#! /usr/bin/env python
## Given a list of names and pin defines, runs through a routine that
## sets up a standard set of macros which can then be cut/paste or
## otherwise included.
import sys
try:
outputFilename = sys.argv[1]
except:
print
print 'No filename passed, saving to "pinDefinitions.h" in this directory.'
outputFilename = "pinDefinitions.h"
print
print
print "First we need to define macro names and the coresponding AVR pins."
print "None of the names are case-sensitive -- all are converted to uppercase."
print "When you're done, hit [enter] for the macro name."
print " "
nicknames = []
pinouts = []
while(True):
nickname = raw_input("\nPin Macro Name: ").strip().upper()
if (nickname == ""):
break
nicknames.append(nickname)
pinout = raw_input("AVR Pinout: ").strip().upper()
pinouts.append(pinout)
output = "// ---------------\n// Pin Defines \n// ---------------\n\n"
for (nickname, pinout) in zip(nicknames, pinouts):
output += "#define %s %s\n" % (nickname, pinout)
output += "#define %s_PORT PORT%s\n" % (nickname, pinout[1])
output += "#define %s_PIN PIN%s\n" % (nickname, pinout[1])
output += "#define %s_DDR DDR%s\n" % (nickname, pinout[1])
output += "#define %s_SET_OUTPUT %s_DDR |= _BV(%s)\n" %\
(nickname, nickname, nickname)
output += "#define %s_SET_INPUT %s_DDR &= ~_BV(%s)\n" %\
(nickname, nickname, nickname)
output += "#define %s_SET_HIGH %s_PORT |= _BV(%s)\n" % \
(nickname, nickname, nickname)
output += "#define %s_SET_LOW %s_PORT &= ~_BV(%s)\n" % \
(nickname, nickname, nickname)
output += "#define %s_TOGGLE %s_PORT ^= _BV(%s)\n" % \
(nickname, nickname, nickname)
output += "#define %s_IS_HIGH (%s_PIN & _BV(%s))\n" % \
(nickname, nickname, nickname)
output += "#define %s_IS_LOW !(%s_PIN & _BV(%s))\n" % \
(nickname, nickname, nickname)
output += "\n"
try:
outfile = open(outputFilename, "w")
outfile.write(output)
outfile.close()
except NameError:
print output

View File

@@ -0,0 +1,26 @@
/* Standard Macros */
/* You can totally get by without these, but why? */
/* Make sure we've already got io / sfr / pindefs loaded */
#ifndef _AVR_IO_H_
#include <avr/io.h>
#endif
/* Reminder: the following useful bit-twiddling macros are
always included in avr/sfr_defs.h, which is called from
avr/io.h
bit_is_set(sfr, bit)
bit_is_clear(sfr, bit)
loop_until_bit_is_set(sfr, bit)
loop_until_bit_is_clear(sfr, bit)
*/
/* Define up the full complement of bit-twiddling macros */
#define BV(bit) (1 << bit)
#define set_bit(sfr, bit) (_SFR_BYTE(sfr) |= BV(bit)) // old sbi()
#define clear_bit(sfr, bit) (_SFR_BYTE(sfr) &= ~BV(bit)) // old cbi()
#define toggle_bit(sfr, bit) (_SFR_BYTE(sfr) ^= BV(bit))

View File

@@ -0,0 +1,22 @@
#include "main.h"
// -------- Global Variables --------- //
// -------- Functions --------- //
int main(void) {
// -------- Inits --------- //
// clock_prescale_set(clock_div_1); /* CPU Clock: 8 MHz */
initUSART();
printString("OK");
// ------ Event loop ------ //
while (1) {
} /* End event loop */
return (0); /* This line is never reached */
}

View File

@@ -0,0 +1,19 @@
// Standard AVR includes
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>
// Standard includes
#include <stdlib.h>
// These are optional, but nice to have around.
// Feel free to comment them out if you don't use them.
#include "USART.h"
#include "macros.h"

View File

@@ -0,0 +1,41 @@
#! /usr/bin/env python
## Simple Python routine for creating a new AVR project
## Feel free to extend this to meet your needs
## In particular, main.h includes nearly every AVR library you'll ever need
## which is no problem, b/c the linker will just ignore the unused ones.
## But if you're not using them, it might cause confusion later.
## Trim them down to fit?
## Or, if you're feeling DIY, you can just copy the Makefile, main.c and main.h
## into a new directory yourself. The other files are optional, but handy.
import os
import shutil
import sys
## Get command-line input
class UsageError(Exception):
pass
try:
newProjectName = sys.argv[1]
except IndexError:
raise(UsageError("Please specify a project name on the command-line.\n"))
## Create new project directory...
## ... in parent directory
## relativeDirectory = os.path.join(os.path.pardir, newProjectName)
## ... or in this directory, and you get to move it yourself.
relativeDirectory = newProjectName
os.mkdir(relativeDirectory)
## Files copied directly over...
def copyToNewDirectory(whichFile, newDirectory):
shutil.copy(whichFile, newDirectory)
## ... these ones.
for filename in ["Makefile", "main.c", "main.h", "USART.h", "USART.c", "macros.h"]:
copyToNewDirectory(filename, relativeDirectory)
print "Copied Makefile, main.c, and main.h into %s." % relativeDirectory
print "Time to start coding."