diff --git a/src/USB2SerialMux.c b/src/USB2SerialMux.c index b585f04..341d99b 100644 --- a/src/USB2SerialMux.c +++ b/src/USB2SerialMux.c @@ -104,7 +104,10 @@ void SetupHardware(void) PMIC.CTRL = PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_HILVLEN_bm; #endif - /* Hardware Initialization */ + /* UART Hardware Initialization */ + uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); + + /* USB Hardware Initialization */ USB_Init(); } diff --git a/src/USB2SerialMux.h b/src/USB2SerialMux.h index bc4aa1d..39094bd 100644 --- a/src/USB2SerialMux.h +++ b/src/USB2SerialMux.h @@ -41,6 +41,7 @@ #include #include #include + #include #include "Descriptors.h" @@ -48,8 +49,14 @@ #include #include + #include "uart/uart.h" + uint8_t error_mask = 0x00; + /* UART definitions: */ + + #define UART_BAUD_RATE 115200 + /* Macros: */ #define SET_ERR_MASK(m) error_mask = m diff --git a/src/makefile b/src/makefile index 4decff1..4dbf09e 100644 --- a/src/makefile +++ b/src/makefile @@ -18,9 +18,9 @@ F_CPU = 16000000UL F_USB = $(F_CPU) OPTIMIZATION = s TARGET = USB2SerialMux -SRC = $(TARGET).c Descriptors.c $(LUFA_SRC_USB) +SRC = $(TARGET).c Descriptors.c $(LUFA_SRC_USB) uart/uart.c LUFA_PATH = ../LUFA -CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ +CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ -Iuart/ LD_FLAGS = # Default target diff --git a/src/uart/Makefile.uart b/src/uart/Makefile.uart new file mode 100644 index 0000000..6b2e71c --- /dev/null +++ b/src/uart/Makefile.uart @@ -0,0 +1,338 @@ +# ---------------------------------------------------------------------------- +# Makefile to compile and link the UART library and test program +# Author: Peter Fleury +# File: $Id: Makefile.uart,v 1.7 2015/09/05 19:04:44 peter Exp $ +# +# Adjust MCU and F_CPU below to your AVR target +# +# Adjust the size of the receive and transmit ringbuffer in bytes using the +# defines -DUART_RX_BUFFER_SIZE= and -DUART_TX_BUFFER_SIZE= +# in the CDEFS section below +#---------------------------------------------------------------------------- +# usage: +# +# make = build software +# make clean = Clean out built project files +# make program = Download the hex file to the device, using avrdude. +# Please customize the avrdude settings below first! +# +# make filename.s = Just compile filename.c into the assembler code only. +# make filename.i = Create a preprocessed source file +# +# To rebuild project do "make clean" then "make" +#---------------------------------------------------------------------------- + + +# MCU name +MCU = atmega8 + + +# Processor frequency. +# This will define a symbol, F_CPU, in all source code files equal to the +# processor frequency. You can then use this symbol in your source code to +# calculate timings. Do NOT tack on a 'UL' at the end, this will be done +# automatically to create a 32-bit value in your source code. +F_CPU = 7372800 + + + +# Target file name (without extension). +TARGET = test_uart + + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c uart.c + + +# List Assembler source files here. +# Make them always end in a capital .S. Files ending in a lowercase .s +# will not be considered source files but generated files (assembler +# output from the compiler), and will be deleted upon "make clean"! +# Even though the DOS/Win* filesystem matches both .s and .S the same, +# it will preserve the spelling of the filenames, and gcc itself does +# care about how the name is spelled on its command-line. +#ASRC = + + +# List any extra directories to look for include files here. +# Each directory must be seperated by a space. +# Use forward slashes for directory separators. +# For a directory that has spaces, enclose it in quotes. +EXTRAINCDIRS = + + +#specify alternate location of sources files +# (unlike VPATH= which is a search path for all prerequisites, not just source files) +#vpath %.c // +#vpath %.S // + + +# Optimization level, can be [0, 1, 2, 3, s]. +# 0 = turn off optimization. s = optimize for size. +# (Note: 3 is not always the best optimization level. See avr-libc FAQ.) +OPT = s + + +# Place -D or -U options here +# uncomment and adapt these line if you want different UART library buffer size +#CDEFS += -DUART_RX_BUFFER_SIZE=128 +#CDEFS += -DUART_TX_BUFFER_SIZE=128 + + + +# Place -I options here +CINCS = + + +#---------------- Compiler Options ---------------- +# -gdwarf-2: generate debugging information +# -O*: optimization level +# -f...: tuning, see GCC manual and avr-libc documentation +# -Wall...: warning level +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns...: create assembler listing +CFLAGS = -DF_CPU=$(F_CPU)UL +CFLAGS += $(CDEFS) $(CINCS) +CFLAGS += -I. $(patsubst %,-I%,$(EXTRAINCDIRS)) +CFLAGS += -std=gnu99 +CFLAGS += -gdwarf-2 +CFLAGS += -O$(OPT) +CFLAGS += -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums +CFLAGS += -Wall -Wstrict-prototypes +CFLAGS += -Wa,-adhlns=$(<:.c=.lst) +CFLAGS += -save-temps + + +#---------------- Assembler Options ---------------- +# -Wa,...: tell GCC to pass this to the assembler. +# -adhlns=$(<:.S=.lst) create listing +# -gdwarf-2: generate debugging information +ASFLAGS = -DF_CPU=$(F_CPU)UL -x assembler-with-cpp -Wa,-gdwarf2 + +#---------------- Library Options ---------------- +# Minimalistic printf version +PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min + +# Floating point printf version (requires MATH_LIB = -lm below) +PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt + +# If this is left blank, then it will use the Standard printf version. +PRINTF_LIB = +#PRINTF_LIB = $(PRINTF_LIB_MIN) +#PRINTF_LIB = $(PRINTF_LIB_FLOAT) + + +# Minimalistic scanf version +SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min + +# Floating point + %[ scanf version (requires MATH_LIB = -lm below) +SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt + +# If this is left blank, then it will use the Standard scanf version. +SCANF_LIB = +#SCANF_LIB = $(SCANF_LIB_MIN) +#SCANF_LIB = $(SCANF_LIB_FLOAT) + + +MATH_LIB = -lm + + + +#---------------- External Memory Options ---------------- + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# used for variables (.data/.bss) and heap (malloc()). +#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff + +# 64 KB of external RAM, starting after internal RAM (ATmega128!), +# only used for heap (malloc()). +#EXTMEMOPTS = -Wl,--defsym=__heap_start=0x801100,--defsym=__heap_end=0x80ffff + +EXTMEMOPTS = + + + +#---------------- Linker Options ---------------- +# -Wl,...: tell GCC to pass this to linker. +# -Map: create map file +# --cref: add cross reference to map file +LDFLAGS = -Wl,-Map=$(TARGET).map,--cref +LDFLAGS += $(EXTMEMOPTS) +LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB) + + + +#---------------- Programming Options (avrdude) ---------------- + +# Programming hardware: Type: avrdude -c ? to get a full listing. +AVRDUDE_PROGRAMMER = usbasp + +# usb, com1 = serial port, lpt1 = parallel port +AVRDUDE_PORT = USB + +AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex +#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep + +# Uncomment the following if you do /not/ wish a verification to be performed after programming the device. +#AVRDUDE_NO_VERIFY = -V + +# Disable save mode for fuses +AVRDUDE_NO_SAFEMODE = -u + +# Uncomment the following if you want avrdude's erase cycle counter. +# Note that this counter needs to be initialized first using -Yn, +#AVRDUDE_ERASE_COUNTER = -y + +# Increase verbosity level. +#AVRDUDE_VERBOSE = -v -v + +# Adjust programming speed of USBasp +# no -B switch 375khz (default) +# -B 2000 500 hz +# -B 1000 1khz +# -B 500 2khz +# -B 250 4khz +# -B 125 8 khz +# -B 62 16khz +# -B 31 32khz * the cutoff for bit banged isp +# -B 10 93.75 khz +# -B 5 187.5 khz +# -B 2 375 khz +# -B 1 750 khz +# -B .5 1.5mhz +#AVRDUDE_SPEED = -B .5 + +AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) +AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY) +AVRDUDE_FLAGS += $(AVRDUDE_NO_SAFEMODE) +AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER) +AVRDUDE_FLAGS += $(AVRDUDE_SPEED) +AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE) + + + +#============================================================================ +# Output format. (can be srec, ihex, binary) +FORMAT = ihex + +# Define programs and commands. +#SHELL = win-bash +CC = avr-gcc +OBJCOPY = avr-objcopy +OBJDUMP = avr-objdump +SIZE = avr-size +NM = avr-nm +AVRDUDE = avrdude +REMOVE = rm -rf +COPY = cp +WINSHELL = cmd + + +# Define Messages +MSG_FLASH = Creating load file for Flash: +MSG_EEPROM = Creating load file for EEPROM: +MSG_EXTENDED_LISTING = Creating Extended Listing: +MSG_SYMBOL_TABLE = Creating Symbol Table: +MSG_LINKING = Linking: +MSG_COMPILING = Compiling: +MSG_ASSEMBLING = Assembling: +MSG_CLEANING = Cleaning project: + + + +# Define all object files. +OBJ = $(SRC:.c=.o) $(ASRC:.S=.o) + +# Define all listing files. +LST = $(SRC:.c=.lst) $(ASRC:.S=.lst) + + +# Compiler flags to generate dependency files. +GENDEPFLAGS = -MD -MP -MF .dep/$(@F).d + + +# Combine all necessary flags and optional flags. +# Add target processor to flags. +ALL_CFLAGS = -mmcu=$(MCU) $(CFLAGS) $(GENDEPFLAGS) +ALL_ASFLAGS = -mmcu=$(MCU) -I. $(ASFLAGS) + + +# Default target. +all: gccversion $(TARGET).elf $(TARGET).hex $(TARGET).eep $(TARGET).lss $(TARGET).sym size + + +# Display compiler version information. +gccversion : + @echo $(OBJ1) + @$(CC) --version + + +# Create final output files (.hex, .eep) from ELF output file. +%.hex: %.elf + @echo $(MSG_FLASH) $@ + $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@ + +%.eep: %.elf + @echo $(MSG_EEPROM) $@ + -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O $(FORMAT) $< $@ + +# Create extended listing file from ELF output file. +%.lss: %.elf + @echo $(MSG_EXTENDED_LISTING) $@ + $(OBJDUMP) -h -S $< > $@ + +# Create a symbol table from ELF output file. +%.sym: %.elf + @echo $(MSG_SYMBOL_TABLE) $@ + $(NM) -n $< > $@ + +# Link: create ELF output file from object files. +.SECONDARY : $(TARGET).elf +.PRECIOUS : $(OBJ) +%.elf: $(OBJ) + @echo $(MSG_LINKING) $@ + $(CC) -mmcu=$(MCU) $(LDFLAGS) $^ --output $(@F) + +# Compile: create object files from C source files. +%.o : %.c + @echo $(MSG_COMPILING) $< + $(CC) -c $(ALL_CFLAGS) $< -o $(@F) + +# Compile: create assembler files from C source files. +%.s : %.c + $(CC) -S $(ALL_CFLAGS) $< -o $(@F) + +# Assemble: create object files from assembler source files. +%.o : %.S + @echo $(MSG_ASSEMBLING) $< + $(CC) -c $(ALL_ASFLAGS) $< -o $(@F) + +# Create preprocessed source for use in sending a bug report. +%.i : %.c + $(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $(@F) + + +# Display size of file. +size: ${TARGET}.elf + @avr-size -C --mcu=${MCU} ${TARGET}.elf + + +# Program the device. +program: $(TARGET).hex $(TARGET).eep + $(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM) + + +# Delete all generated files. +clean: + @echo $(MSG_CLEANING) + $(REMOVE) $(TARGET).hex $(TARGET).eep $(TARGET).cof $(TARGET).elf $(TARGET).map $(TARGET).sym $(TARGET).lss $(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(SRC:.c=.i) .dep/ + + +# Include the dependency files. +#-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*) +-include $(shell mkdir .dep 2>NUL) $(wildcard .dep/*) + + +# Listing of phony targets. +.PHONY : all size gccversion clean program + diff --git a/src/uart/doxygen.css b/src/uart/doxygen.css new file mode 100644 index 0000000..a000833 --- /dev/null +++ b/src/uart/doxygen.css @@ -0,0 +1,1449 @@ +/* The standard CSS for doxygen 1.8.9.1 */ + +body, table, div, p, dl { + font: 400 14px/22px Roboto,sans-serif; +} + +/* @group Heading Levels */ + +h1.groupheader { + font-size: 150%; +} + +.title { + font: 400 14px/28px Roboto,sans-serif; + font-size: 150%; + font-weight: bold; + margin: 10px 2px; +} + +h2.groupheader { + border-bottom: 1px solid #879ECB; + color: #354C7B; + font-size: 150%; + font-weight: normal; + margin-top: 1.75em; + padding-top: 8px; + padding-bottom: 4px; + width: 100%; +} + +h3.groupheader { + font-size: 100%; +} + +h1, h2, h3, h4, h5, h6 { + -webkit-transition: text-shadow 0.5s linear; + -moz-transition: text-shadow 0.5s linear; + -ms-transition: text-shadow 0.5s linear; + -o-transition: text-shadow 0.5s linear; + transition: text-shadow 0.5s linear; + margin-right: 15px; +} + +h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow { + text-shadow: 0 0 15px cyan; +} + +dt { + font-weight: bold; +} + +div.multicol { + -moz-column-gap: 1em; + -webkit-column-gap: 1em; + -moz-column-count: 3; + -webkit-column-count: 3; +} + +p.startli, p.startdd { + margin-top: 2px; +} + +p.starttd { + margin-top: 0px; +} + +p.endli { + margin-bottom: 0px; +} + +p.enddd { + margin-bottom: 4px; +} + +p.endtd { + margin-bottom: 2px; +} + +/* @end */ + +caption { + font-weight: bold; +} + +span.legend { + font-size: 70%; + text-align: center; +} + +h3.version { + font-size: 90%; + text-align: center; +} + +div.qindex, div.navtab{ + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; +} + +div.qindex, div.navpath { + width: 100%; + line-height: 140%; +} + +div.navtab { + margin-right: 15px; +} + +/* @group Link Styling */ + +a { + color: #3D578C; + font-weight: normal; + text-decoration: none; +} + +.contents a:visited { + color: #4665A2; +} + +a:hover { + text-decoration: underline; +} + +a.qindex { + font-weight: bold; +} + +a.qindexHL { + font-weight: bold; + background-color: #9CAFD4; + color: #ffffff; + border: 1px double #869DCA; +} + +.contents a.qindexHL:visited { + color: #ffffff; +} + +a.el { + font-weight: bold; +} + +a.elRef { +} + +a.code, a.code:visited, a.line, a.line:visited { + color: #4665A2; +} + +a.codeRef, a.codeRef:visited, a.lineRef, a.lineRef:visited { + color: #4665A2; +} + +/* @end */ + +dl.el { + margin-left: -1cm; +} + +pre.fragment { + border: 1px solid #C4CFE5; + background-color: #FBFCFD; + padding: 4px 6px; + margin: 4px 8px 4px 2px; + overflow: auto; + word-wrap: break-word; + font-size: 9pt; + line-height: 125%; + font-family: monospace, fixed; + font-size: 105%; +} + +div.fragment { + padding: 4px 6px; + margin: 4px 8px 4px 2px; + background-color: #FBFCFD; + border: 1px solid #C4CFE5; +} + +div.line { + font-family: monospace, fixed; + font-size: 13px; + min-height: 13px; + line-height: 1.0; + text-wrap: unrestricted; + white-space: -moz-pre-wrap; /* Moz */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + white-space: pre-wrap; /* CSS3 */ + word-wrap: break-word; /* IE 5.5+ */ + text-indent: -53px; + padding-left: 53px; + padding-bottom: 0px; + margin: 0px; + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +div.line.glow { + background-color: cyan; + box-shadow: 0 0 10px cyan; +} + + +span.lineno { + padding-right: 4px; + text-align: right; + border-right: 2px solid #0F0; + background-color: #E8E8E8; + white-space: pre; +} +span.lineno a { + background-color: #D8D8D8; +} + +span.lineno a:hover { + background-color: #C8C8C8; +} + +div.ah, span.ah { + background-color: black; + font-weight: bold; + color: #ffffff; + margin-bottom: 3px; + margin-top: 3px; + padding: 0.2em; + border: solid thin #333; + border-radius: 0.5em; + -webkit-border-radius: .5em; + -moz-border-radius: .5em; + box-shadow: 2px 2px 3px #999; + -webkit-box-shadow: 2px 2px 3px #999; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + background-image: -webkit-gradient(linear, left top, left bottom, from(#eee), to(#000),color-stop(0.3, #444)); + background-image: -moz-linear-gradient(center top, #eee 0%, #444 40%, #000); +} + +div.classindex ul { + list-style: none; + padding-left: 0; +} + +div.classindex span.ai { + display: inline-block; +} + +div.groupHeader { + margin-left: 16px; + margin-top: 12px; + font-weight: bold; +} + +div.groupText { + margin-left: 16px; + font-style: italic; +} + +body { + background-color: white; + color: black; + margin: 0; +} + +div.contents { + margin-top: 10px; + margin-left: 12px; + margin-right: 8px; +} + +td.indexkey { + background-color: #EBEFF6; + font-weight: bold; + border: 1px solid #C4CFE5; + margin: 2px 0px 2px 0; + padding: 2px 10px; + white-space: nowrap; + vertical-align: top; +} + +td.indexvalue { + background-color: #EBEFF6; + border: 1px solid #C4CFE5; + padding: 2px 10px; + margin: 2px 0px; +} + +tr.memlist { + background-color: #EEF1F7; +} + +p.formulaDsp { + text-align: center; +} + +img.formulaDsp { + +} + +img.formulaInl { + vertical-align: middle; +} + +div.center { + text-align: center; + margin-top: 0px; + margin-bottom: 0px; + padding: 0px; +} + +div.center img { + border: 0px; +} + +address.footer { + text-align: right; + padding-right: 12px; +} + +img.footer { + border: 0px; + vertical-align: middle; +} + +/* @group Code Colorization */ + +span.keyword { + color: #008000 +} + +span.keywordtype { + color: #604020 +} + +span.keywordflow { + color: #e08000 +} + +span.comment { + color: #800000 +} + +span.preprocessor { + color: #806020 +} + +span.stringliteral { + color: #002080 +} + +span.charliteral { + color: #008080 +} + +span.vhdldigit { + color: #ff00ff +} + +span.vhdlchar { + color: #000000 +} + +span.vhdlkeyword { + color: #700070 +} + +span.vhdllogic { + color: #ff0000 +} + +blockquote { + background-color: #F7F8FB; + border-left: 2px solid #9CAFD4; + margin: 0 24px 0 4px; + padding: 0 12px 0 16px; +} + +/* @end */ + +/* +.search { + color: #003399; + font-weight: bold; +} + +form.search { + margin-bottom: 0px; + margin-top: 0px; +} + +input.search { + font-size: 75%; + color: #000080; + font-weight: normal; + background-color: #e8eef2; +} +*/ + +td.tiny { + font-size: 75%; +} + +.dirtab { + padding: 4px; + border-collapse: collapse; + border: 1px solid #A3B4D7; +} + +th.dirtab { + background: #EBEFF6; + font-weight: bold; +} + +hr { + height: 0px; + border: none; + border-top: 1px solid #4A6AAA; +} + +hr.footer { + height: 1px; +} + +/* @group Member Descriptions */ + +table.memberdecls { + border-spacing: 0px; + padding: 0px; +} + +.memberdecls td, .fieldtable tr { + -webkit-transition-property: background-color, box-shadow; + -webkit-transition-duration: 0.5s; + -moz-transition-property: background-color, box-shadow; + -moz-transition-duration: 0.5s; + -ms-transition-property: background-color, box-shadow; + -ms-transition-duration: 0.5s; + -o-transition-property: background-color, box-shadow; + -o-transition-duration: 0.5s; + transition-property: background-color, box-shadow; + transition-duration: 0.5s; +} + +.memberdecls td.glow, .fieldtable tr.glow { + background-color: cyan; + box-shadow: 0 0 15px cyan; +} + +.mdescLeft, .mdescRight, +.memItemLeft, .memItemRight, +.memTemplItemLeft, .memTemplItemRight, .memTemplParams { + background-color: #F9FAFC; + border: none; + margin: 4px; + padding: 1px 0 0 8px; +} + +.mdescLeft, .mdescRight { + padding: 0px 8px 4px 8px; + color: #555; +} + +.memSeparator { + border-bottom: 1px solid #DEE4F0; + line-height: 1px; + margin: 0px; + padding: 0px; +} + +.memItemLeft, .memTemplItemLeft { + white-space: nowrap; +} + +.memItemRight { + width: 100%; +} + +.memTemplParams { + color: #4665A2; + white-space: nowrap; + font-size: 80%; +} + +/* @end */ + +/* @group Member Details */ + +/* Styles for detailed member documentation */ + +.memtemplate { + font-size: 80%; + color: #4665A2; + font-weight: normal; + margin-left: 9px; +} + +.memnav { + background-color: #EBEFF6; + border: 1px solid #A3B4D7; + text-align: center; + margin: 2px; + margin-right: 15px; + padding: 2px; +} + +.mempage { + width: 100%; +} + +.memitem { + padding: 0; + margin-bottom: 10px; + margin-right: 5px; + -webkit-transition: box-shadow 0.5s linear; + -moz-transition: box-shadow 0.5s linear; + -ms-transition: box-shadow 0.5s linear; + -o-transition: box-shadow 0.5s linear; + transition: box-shadow 0.5s linear; + display: table !important; + width: 100%; +} + +.memitem.glow { + box-shadow: 0 0 15px cyan; +} + +.memname { + font-weight: bold; + margin-left: 6px; +} + +.memname td { + vertical-align: bottom; +} + +.memproto, dl.reflist dt { + border-top: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 0px 6px 0px; + color: #253555; + font-weight: bold; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + /* opera specific markup */ + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + border-top-right-radius: 4px; + border-top-left-radius: 4px; + /* firefox specific markup */ + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + -moz-border-radius-topright: 4px; + -moz-border-radius-topleft: 4px; + /* webkit specific markup */ + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + -webkit-border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + +} + +.memdoc, dl.reflist dd { + border-bottom: 1px solid #A8B8D9; + border-left: 1px solid #A8B8D9; + border-right: 1px solid #A8B8D9; + padding: 6px 10px 2px 10px; + background-color: #FBFCFD; + border-top-width: 0; + background-image:url('nav_g.png'); + background-repeat:repeat-x; + background-color: #FFFFFF; + /* opera specific markup */ + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); + /* firefox specific markup */ + -moz-border-radius-bottomleft: 4px; + -moz-border-radius-bottomright: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 5px 5px 5px; + /* webkit specific markup */ + -webkit-border-bottom-left-radius: 4px; + -webkit-border-bottom-right-radius: 4px; + -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.15); +} + +dl.reflist dt { + padding: 5px; +} + +dl.reflist dd { + margin: 0px 0px 10px 0px; + padding: 5px; +} + +.paramkey { + text-align: right; +} + +.paramtype { + white-space: nowrap; +} + +.paramname { + color: #602020; + white-space: nowrap; +} +.paramname em { + font-style: normal; +} +.paramname code { + line-height: 14px; +} + +.params, .retval, .exception, .tparams { + margin-left: 0px; + padding-left: 0px; +} + +.params .paramname, .retval .paramname { + font-weight: bold; + vertical-align: top; +} + +.params .paramtype { + font-style: italic; + vertical-align: top; +} + +.params .paramdir { + font-family: "courier new",courier,monospace; + vertical-align: top; +} + +table.mlabels { + border-spacing: 0px; +} + +td.mlabels-left { + width: 100%; + padding: 0px; +} + +td.mlabels-right { + vertical-align: bottom; + padding: 0px; + white-space: nowrap; +} + +span.mlabels { + margin-left: 8px; +} + +span.mlabel { + background-color: #728DC1; + border-top:1px solid #5373B4; + border-left:1px solid #5373B4; + border-right:1px solid #C4CFE5; + border-bottom:1px solid #C4CFE5; + text-shadow: none; + color: white; + margin-right: 4px; + padding: 2px 3px; + border-radius: 3px; + font-size: 7pt; + white-space: nowrap; + vertical-align: middle; +} + + + +/* @end */ + +/* these are for tree view inside a (index) page */ + +div.directory { + margin: 10px 0px; + border-top: 1px solid #9CAFD4; + border-bottom: 1px solid #9CAFD4; + width: 100%; +} + +.directory table { + border-collapse:collapse; +} + +.directory td { + margin: 0px; + padding: 0px; + vertical-align: top; +} + +.directory td.entry { + white-space: nowrap; + padding-right: 6px; + padding-top: 3px; +} + +.directory td.entry a { + outline:none; +} + +.directory td.entry a img { + border: none; +} + +.directory td.desc { + width: 100%; + padding-left: 6px; + padding-right: 6px; + padding-top: 3px; + border-left: 1px solid rgba(0,0,0,0.05); +} + +.directory tr.even { + padding-left: 6px; + background-color: #F7F8FB; +} + +.directory img { + vertical-align: -30%; +} + +.directory .levels { + white-space: nowrap; + width: 100%; + text-align: right; + font-size: 9pt; +} + +.directory .levels span { + cursor: pointer; + padding-left: 2px; + padding-right: 2px; + color: #3D578C; +} + +.arrow { + color: #9CAFD4; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + cursor: pointer; + font-size: 80%; + display: inline-block; + width: 16px; + height: 22px; +} + +.icon { + font-family: Arial, Helvetica; + font-weight: bold; + font-size: 12px; + height: 14px; + width: 16px; + display: inline-block; + background-color: #728DC1; + color: white; + text-align: center; + border-radius: 4px; + margin-left: 2px; + margin-right: 2px; +} + +.icona { + width: 24px; + height: 22px; + display: inline-block; +} + +.iconfopen { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderopen.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.iconfclosed { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('folderclosed.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +.icondoc { + width: 24px; + height: 18px; + margin-bottom: 4px; + background-image:url('doc.png'); + background-position: 0px -4px; + background-repeat: repeat-y; + vertical-align:top; + display: inline-block; +} + +table.directory { + font: 400 14px Roboto,sans-serif; +} + +/* @end */ + +div.dynheader { + margin-top: 8px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +address { + font-style: normal; + color: #2A3D61; +} + +table.doxtable { + border-collapse:collapse; + margin-top: 4px; + margin-bottom: 4px; +} + +table.doxtable td, table.doxtable th { + border: 1px solid #2D4068; + padding: 3px 7px 2px; +} + +table.doxtable th { + background-color: #374F7F; + color: #FFFFFF; + font-size: 110%; + padding-bottom: 4px; + padding-top: 5px; +} + +table.fieldtable { + /*width: 100%;*/ + margin-bottom: 10px; + border: 1px solid #A8B8D9; + border-spacing: 0px; + -moz-border-radius: 4px; + -webkit-border-radius: 4px; + border-radius: 4px; + -moz-box-shadow: rgba(0, 0, 0, 0.15) 2px 2px 2px; + -webkit-box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); + box-shadow: 2px 2px 2px rgba(0, 0, 0, 0.15); +} + +.fieldtable td, .fieldtable th { + padding: 3px 7px 2px; +} + +.fieldtable td.fieldtype, .fieldtable td.fieldname { + white-space: nowrap; + border-right: 1px solid #A8B8D9; + border-bottom: 1px solid #A8B8D9; + vertical-align: top; +} + +.fieldtable td.fieldname { + padding-top: 3px; +} + +.fieldtable td.fielddoc { + border-bottom: 1px solid #A8B8D9; + /*width: 100%;*/ +} + +.fieldtable td.fielddoc p:first-child { + margin-top: 0px; +} + +.fieldtable td.fielddoc p:last-child { + margin-bottom: 2px; +} + +.fieldtable tr:last-child td { + border-bottom: none; +} + +.fieldtable th { + background-image:url('nav_f.png'); + background-repeat:repeat-x; + background-color: #E2E8F2; + font-size: 90%; + color: #253555; + padding-bottom: 4px; + padding-top: 5px; + text-align:left; + -moz-border-radius-topleft: 4px; + -moz-border-radius-topright: 4px; + -webkit-border-top-left-radius: 4px; + -webkit-border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + border-bottom: 1px solid #A8B8D9; +} + + +.tabsearch { + top: 0px; + left: 10px; + height: 36px; + background-image: url('tab_b.png'); + z-index: 101; + overflow: hidden; + font-size: 13px; +} + +.navpath ul +{ + font-size: 11px; + background-image:url('tab_b.png'); + background-repeat:repeat-x; + background-position: 0 -5px; + height:30px; + line-height:30px; + color:#8AA0CC; + border:solid 1px #C2CDE4; + overflow:hidden; + margin:0px; + padding:0px; +} + +.navpath li +{ + list-style-type:none; + float:left; + padding-left:10px; + padding-right:15px; + background-image:url('bc_s.png'); + background-repeat:no-repeat; + background-position:right; + color:#364D7C; +} + +.navpath li.navelem a +{ + height:32px; + display:block; + text-decoration: none; + outline: none; + color: #283A5D; + font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; + text-shadow: 0px 1px 1px rgba(255, 255, 255, 0.9); + text-decoration: none; +} + +.navpath li.navelem a:hover +{ + color:#6884BD; +} + +.navpath li.footer +{ + list-style-type:none; + float:right; + padding-left:10px; + padding-right:15px; + background-image:none; + background-repeat:no-repeat; + background-position:right; + color:#364D7C; + font-size: 8pt; +} + + +div.summary +{ + float: right; + font-size: 8pt; + padding-right: 5px; + width: 50%; + text-align: right; +} + +div.summary a +{ + white-space: nowrap; +} + +div.ingroups +{ + font-size: 8pt; + width: 50%; + text-align: left; +} + +div.ingroups a +{ + white-space: nowrap; +} + +div.header +{ + background-image:url('nav_h.png'); + background-repeat:repeat-x; + background-color: #F9FAFC; + margin: 0px; + border-bottom: 1px solid #C4CFE5; +} + +div.headertitle +{ + padding: 5px 5px 5px 10px; +} + +dl +{ + padding: 0 0 0 10px; +} + +/* dl.note, dl.warning, dl.attention, dl.pre, dl.post, dl.invariant, dl.deprecated, dl.todo, dl.test, dl.bug */ +dl.section +{ + margin-left: 0px; + padding-left: 0px; +} + +dl.note +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #D0C000; +} + +dl.warning, dl.attention +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #FF0000; +} + +dl.pre, dl.post, dl.invariant +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00D000; +} + +dl.deprecated +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #505050; +} + +dl.todo +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #00C0E0; +} + +dl.test +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #3030E0; +} + +dl.bug +{ + margin-left:-7px; + padding-left: 3px; + border-left:4px solid; + border-color: #C08050; +} + +dl.section dd { + margin-bottom: 6px; +} + + +#projectlogo +{ + text-align: center; + vertical-align: bottom; + border-collapse: separate; +} + +#projectlogo img +{ + border: 0px none; +} + +#projectname +{ + font: 300% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 2px 0px; +} + +#projectbrief +{ + font: 120% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#projectnumber +{ + font: 50% Tahoma, Arial,sans-serif; + margin: 0px; + padding: 0px; +} + +#titlearea +{ + padding: 0px; + margin: 0px; + width: 100%; + border-bottom: 1px solid #5373B4; +} + +.image +{ + text-align: center; +} + +.dotgraph +{ + text-align: center; +} + +.mscgraph +{ + text-align: center; +} + +.diagraph +{ + text-align: center; +} + +.caption +{ + font-weight: bold; +} + +div.zoom +{ + border: 1px solid #90A5CE; +} + +dl.citelist { + margin-bottom:50px; +} + +dl.citelist dt { + color:#334975; + float:left; + font-weight:bold; + margin-right:10px; + padding:5px; +} + +dl.citelist dd { + margin:2px 0; + padding:5px 0; +} + +div.toc { + padding: 14px 25px; + background-color: #F4F6FA; + border: 1px solid #D8DFEE; + border-radius: 7px 7px 7px 7px; + float: right; + height: auto; + margin: 0 20px 10px 10px; + width: 200px; +} + +div.toc li { + background: url("bdwn.png") no-repeat scroll 0 5px transparent; + font: 10px/1.2 Verdana,DejaVu Sans,Geneva,sans-serif; + margin-top: 5px; + padding-left: 10px; + padding-top: 2px; +} + +div.toc h3 { + font: bold 12px/1.2 Arial,FreeSans,sans-serif; + color: #4665A2; + border-bottom: 0 none; + margin: 0; +} + +div.toc ul { + list-style: none outside none; + border: medium none; + padding: 0px; +} + +div.toc li.level1 { + margin-left: 0px; +} + +div.toc li.level2 { + margin-left: 15px; +} + +div.toc li.level3 { + margin-left: 30px; +} + +div.toc li.level4 { + margin-left: 45px; +} + +.inherit_header { + font-weight: bold; + color: gray; + cursor: pointer; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.inherit_header td { + padding: 6px 0px 2px 5px; +} + +.inherit { + display: none; +} + +tr.heading h2 { + margin-top: 12px; + margin-bottom: 4px; +} + +/* tooltip related style info */ + +.ttc { + position: absolute; + display: none; +} + +#powerTip { + cursor: default; + white-space: nowrap; + background-color: white; + border: 1px solid gray; + border-radius: 4px 4px 4px 4px; + box-shadow: 1px 1px 7px gray; + display: none; + font-size: smaller; + max-width: 80%; + opacity: 0.9; + padding: 1ex 1em 1em; + position: absolute; + z-index: 2147483647; +} + +#powerTip div.ttdoc { + color: grey; + font-style: italic; +} + +#powerTip div.ttname a { + font-weight: bold; +} + +#powerTip div.ttname { + font-weight: bold; +} + +#powerTip div.ttdeci { + color: #006318; +} + +#powerTip div { + margin: 0px; + padding: 0px; + font: 12px/16px Roboto,sans-serif; +} + +#powerTip:before, #powerTip:after { + content: ""; + position: absolute; + margin: 0px; +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.s:after, #powerTip.s:before, +#powerTip.w:after, #powerTip.w:before, +#powerTip.e:after, #powerTip.e:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.nw:after, #powerTip.nw:before, +#powerTip.sw:after, #powerTip.sw:before { + border: solid transparent; + content: " "; + height: 0; + width: 0; + position: absolute; +} + +#powerTip.n:after, #powerTip.s:after, +#powerTip.w:after, #powerTip.e:after, +#powerTip.nw:after, #powerTip.ne:after, +#powerTip.sw:after, #powerTip.se:after { + border-color: rgba(255, 255, 255, 0); +} + +#powerTip.n:before, #powerTip.s:before, +#powerTip.w:before, #powerTip.e:before, +#powerTip.nw:before, #powerTip.ne:before, +#powerTip.sw:before, #powerTip.se:before { + border-color: rgba(128, 128, 128, 0); +} + +#powerTip.n:after, #powerTip.n:before, +#powerTip.ne:after, #powerTip.ne:before, +#powerTip.nw:after, #powerTip.nw:before { + top: 100%; +} + +#powerTip.n:after, #powerTip.ne:after, #powerTip.nw:after { + border-top-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} +#powerTip.n:before { + border-top-color: #808080; + border-width: 11px; + margin: 0px -11px; +} +#powerTip.n:after, #powerTip.n:before { + left: 50%; +} + +#powerTip.nw:after, #powerTip.nw:before { + right: 14px; +} + +#powerTip.ne:after, #powerTip.ne:before { + left: 14px; +} + +#powerTip.s:after, #powerTip.s:before, +#powerTip.se:after, #powerTip.se:before, +#powerTip.sw:after, #powerTip.sw:before { + bottom: 100%; +} + +#powerTip.s:after, #powerTip.se:after, #powerTip.sw:after { + border-bottom-color: #ffffff; + border-width: 10px; + margin: 0px -10px; +} + +#powerTip.s:before, #powerTip.se:before, #powerTip.sw:before { + border-bottom-color: #808080; + border-width: 11px; + margin: 0px -11px; +} + +#powerTip.s:after, #powerTip.s:before { + left: 50%; +} + +#powerTip.sw:after, #powerTip.sw:before { + right: 14px; +} + +#powerTip.se:after, #powerTip.se:before { + left: 14px; +} + +#powerTip.e:after, #powerTip.e:before { + left: 100%; +} +#powerTip.e:after { + border-left-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.e:before { + border-left-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +#powerTip.w:after, #powerTip.w:before { + right: 100%; +} +#powerTip.w:after { + border-right-color: #ffffff; + border-width: 10px; + top: 50%; + margin-top: -10px; +} +#powerTip.w:before { + border-right-color: #808080; + border-width: 11px; + top: 50%; + margin-top: -11px; +} + +@media print +{ + #top { display: none; } + #side-nav { display: none; } + #nav-path { display: none; } + body { overflow:visible; } + h1, h2, h3, h4, h5, h6 { page-break-after: avoid; } + .summary { display: none; } + .memitem { page-break-inside: avoid; } + #doc-content + { + margin-left:0 !important; + height:auto !important; + width:auto !important; + overflow:inherit; + display:inline; + } +} + diff --git a/src/uart/manual_uart.html b/src/uart/manual_uart.html new file mode 100644 index 0000000..1835430 --- /dev/null +++ b/src/uart/manual_uart.html @@ -0,0 +1,472 @@ + + + + + + +AVR-GCC Libraries: UART Library <uart.h> + + + + + + +
+
+ + + + + + +
+
AVR-GCC Libraries +
+
+
+ + + +
+
+ +
+
UART Library <uart.h>
+
+
+

Detailed Description

+

Interrupt UART library using the built-in UART with transmit and receive circular buffers.

+
#include <uart.h>
+

This library can be used to transmit and receive data through the built in UART.

+

An interrupt is generated when the UART has finished transmitting or receiving a byte. The interrupt handling routines use circular buffers for buffering received and transmitted data.

+

The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define the size of the circular buffers in bytes. Note that these constants must be a power of 2. You may need to adapt these constants to your target and your application by adding CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_TX_BUFFER_SIZE=nn to your Makefile.

+
Note
Based on Atmel Application Note AVR306
+
Author
Peter Fleury pfleu.nosp@m.ry@g.nosp@m.mx.ch http://tinyurl.com/peterfleury
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Macros

#define UART_BAUD_SELECT(baudRate, xtalCpu)   (((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL)
 UART Baudrate Expression. More...
 
#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate, xtalCpu)   ( ((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000)
 UART Baudrate Expression for ATmega double speed mode. More...
 
#define UART_RX_BUFFER_SIZE   32
 Size of the circular receive buffer, must be power of 2. More...
 
#define UART_TX_BUFFER_SIZE   32
 Size of the circular transmit buffer, must be power of 2. More...
 
+#define UART_FRAME_ERROR   0x1000
 Framing Error by UART.
 
+#define UART_OVERRUN_ERROR   0x0800
 Overrun condition by UART.
 
+#define UART_PARITY_ERROR   0x0400
 Parity Error by UART.
 
+#define UART_BUFFER_OVERFLOW   0x0200
 receive ringbuffer overflow
 
+#define UART_NO_DATA   0x0100
 no receive data available
 
+#define uart_puts_P(__s)   uart_puts_p(PSTR(__s))
 Macro to automatically put a string constant into program memory.
 
+#define uart1_puts_P(__s)   uart1_puts_p(PSTR(__s))
 Macro to automatically put a string constant into program memory.
 
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+Functions

void uart_init (unsigned int baudrate)
 Initialize UART and set baudrate. More...
 
unsigned int uart_getc (void)
 Get received byte from ringbuffer. More...
 
void uart_putc (unsigned char data)
 Put byte to ringbuffer for transmitting via UART. More...
 
void uart_puts (const char *s)
 Put string to ringbuffer for transmitting via UART. More...
 
void uart_puts_p (const char *s)
 Put string from program memory to ringbuffer for transmitting via UART. More...
 
void uart1_init (unsigned int baudrate)
 Initialize USART1 (only available on selected ATmegas) More...
 
unsigned int uart1_getc (void)
 Get received byte of USART1 from ringbuffer. (only available on selected ATmega) More...
 
void uart1_putc (unsigned char data)
 Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) More...
 
void uart1_puts (const char *s)
 Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) More...
 
void uart1_puts_p (const char *s)
 Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) More...
 
+

Macro Definition Documentation

+ +
+
+ + + + + + + + + + + + + + + + + + +
#define UART_BAUD_SELECT( baudRate,
 xtalCpu 
)   (((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL)
+
+ +

UART Baudrate Expression.

+
Parameters
+ + + +
xtalCpusystem clock in Mhz, e.g. 4000000UL for 4Mhz
baudRatebaudrate in bps, e.g. 1200, 2400, 9600
+
+
+ +
+
+ +
+
+ + + + + + + + + + + + + + + + + + +
#define UART_BAUD_SELECT_DOUBLE_SPEED( baudRate,
 xtalCpu 
)   ( ((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000)
+
+ +

UART Baudrate Expression for ATmega double speed mode.

+
Parameters
+ + + +
xtalCpusystem clock in Mhz, e.g. 4000000UL for 4Mhz
baudRatebaudrate in bps, e.g. 1200, 2400, 9600
+
+
+ +
+
+ +
+
+ + + + +
#define UART_RX_BUFFER_SIZE   32
+
+ +

Size of the circular receive buffer, must be power of 2.

+

You may need to adapt this constant to your target and your application by adding CDEFS += -DUART_RX_BUFFER_SIZE=nn to your Makefile.

+ +
+
+ +
+
+ + + + +
#define UART_TX_BUFFER_SIZE   32
+
+ +

Size of the circular transmit buffer, must be power of 2.

+

You may need to adapt this constant to your target and your application by adding CDEFS += -DUART_TX_BUFFER_SIZE=nn to your Makefile.

+ +
+
+

Function Documentation

+ +
+
+ + + + + + + + +
void uart_init (unsigned int baudrate)
+
+ +

Initialize UART and set baudrate.

+
Parameters
+ + +
baudrateSpecify baudrate using macro UART_BAUD_SELECT()
+
+
+
Returns
none
+ +
+
+ +
+
+ + + + + + + + +
unsigned int uart_getc (void )
+
+ +

Get received byte from ringbuffer.

+

Returns in the lower byte the received character and in the higher byte the last receive error. UART_NO_DATA is returned when no data is available.

+
Returns
lower byte: received byte from ringbuffer
+
+higher byte: last receive status
    +
  • 0 successfully received data from UART
  • +
  • UART_NO_DATA
    +no receive data available
  • +
  • UART_BUFFER_OVERFLOW
    +Receive ringbuffer overflow. We are not reading the receive buffer fast enough, one or more received character have been dropped
  • +
  • UART_OVERRUN_ERROR
    +Overrun condition by UART. A character already present in the UART UDR register was not read by the interrupt handler before the next character arrived, one or more received characters have been dropped.
  • +
  • UART_FRAME_ERROR
    +Framing Error by UART
  • +
+
+ +
+
+ +
+
+ + + + + + + + +
void uart_putc (unsigned char data)
+
+ +

Put byte to ringbuffer for transmitting via UART.

+
Parameters
+ + +
databyte to be transmitted
+
+
+
Returns
none
+ +
+
+ +
+
+ + + + + + + + +
void uart_puts (const char * s)
+
+ +

Put string to ringbuffer for transmitting via UART.

+

The string is buffered by the uart library in a circular buffer and one character at a time is transmitted to the UART using interrupts. Blocks if it can not write the whole string into the circular buffer.

+
Parameters
+ + +
sstring to be transmitted
+
+
+
Returns
none
+ +
+
+ +
+
+ + + + + + + + +
void uart_puts_p (const char * s)
+
+ +

Put string from program memory to ringbuffer for transmitting via UART.

+

The string is buffered by the uart library in a circular buffer and one character at a time is transmitted to the UART using interrupts. Blocks if it can not write the whole string into the circular buffer.

+
Parameters
+ + +
sprogram memory string to be transmitted
+
+
+
Returns
none
+
See also
uart_puts_P
+ +
+
+ +
+
+ + + + + + + + +
void uart1_init (unsigned int baudrate)
+
+ +

Initialize USART1 (only available on selected ATmegas)

+
See also
uart_init
+ +
+
+ +
+
+ + + + + + + + +
unsigned int uart1_getc (void )
+
+ +

Get received byte of USART1 from ringbuffer. (only available on selected ATmega)

+
See also
uart_getc
+ +
+
+ +
+
+ + + + + + + + +
void uart1_putc (unsigned char data)
+
+ +

Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega)

+
See also
uart_putc
+ +
+
+ +
+
+ + + + + + + + +
void uart1_puts (const char * s)
+
+ +

Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega)

+
See also
uart_puts
+ +
+
+ +
+
+ + + + + + + + +
void uart1_puts_p (const char * s)
+
+ +

Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega)

+
See also
uart_puts_p
+ +
+
+
+ + + + diff --git a/src/uart/test_uart.c b/src/uart/test_uart.c new file mode 100644 index 0000000..399c03d --- /dev/null +++ b/src/uart/test_uart.c @@ -0,0 +1,129 @@ +/************************************************************************* +Title: Example program for the Interrupt controlled UART library +Author: Peter Fleury http://tinyurl.com/peterfleury +File: $Id: test_uart.c,v 1.7 2015/01/31 17:46:31 peter Exp $ +Software: AVR-GCC 4.x +Hardware: AVR with built-in UART/USART + +DESCRIPTION: + This example shows how to use the UART library uart.c + +*************************************************************************/ +#include +#include +#include +#include + +#include "uart.h" + + +/* define CPU frequency in Hz in Makefile */ +#ifndef F_CPU +#error "F_CPU undefined, please define CPU frequency in Hz in Makefile" +#endif + +/* Define UART buad rate here */ +#define UART_BAUD_RATE 9600 + + +int main(void) +{ + unsigned int c; + char buffer[7]; + int num=134; + + + /* + * Initialize UART library, pass baudrate and AVR cpu clock + * with the macro + * UART_BAUD_SELECT() (normal speed mode ) + * or + * UART_BAUD_SELECT_DOUBLE_SPEED() ( double speed mode) + */ + uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); + + /* + * now enable interrupt, since UART library is interrupt controlled + */ + sei(); + + /* + * Transmit string to UART + * The string is buffered by the uart library in a circular buffer + * and one character at a time is transmitted to the UART using interrupts. + * uart_puts() blocks if it can not write the whole string to the circular + * buffer + */ + uart_puts("String stored in SRAM\n"); + + /* + * Transmit string from program memory to UART + */ + uart_puts_P("String stored in FLASH\n"); + + + /* + * Use standard avr-libc functions to convert numbers into string + * before transmitting via UART + */ + itoa( num, buffer, 10); // convert interger into string (decimal format) + uart_puts(buffer); // and transmit string to UART + + + /* + * Transmit single character to UART + */ + uart_putc('\r'); + + for(;;) + { + /* + * Get received character from ringbuffer + * uart_getc() returns in the lower byte the received character and + * in the higher byte (bitmask) the last receive error + * UART_NO_DATA is returned when no data is available. + * + */ + c = uart_getc(); + if ( c & UART_NO_DATA ) + { + /* + * no data available from UART + */ + } + else + { + /* + * new data available from UART + * check for Frame or Overrun error + */ + if ( c & UART_FRAME_ERROR ) + { + /* Framing Error detected, i.e no stop bit detected */ + uart_puts_P("UART Frame Error: "); + } + if ( c & UART_OVERRUN_ERROR ) + { + /* + * Overrun, a character already present in the UART UDR register was + * not read by the interrupt handler before the next character arrived, + * one or more received characters have been dropped + */ + uart_puts_P("UART Overrun Error: "); + } + if ( c & UART_BUFFER_OVERFLOW ) + { + /* + * We are not reading the receive buffer fast enough, + * one or more received character have been dropped + */ + uart_puts_P("Buffer overflow error: "); + } + /* + * send received character back + */ + uart_putc( (unsigned char)c ); + } + } + +} diff --git a/src/uart/uart.c b/src/uart/uart.c new file mode 100644 index 0000000..547c736 --- /dev/null +++ b/src/uart/uart.c @@ -0,0 +1,777 @@ +/************************************************************************* +Title: Interrupt UART library with receive/transmit circular buffers +Author: Peter Fleury http://tinyurl.com/peterfleury +File: $Id: uart.c,v 1.15.2.4 2015/09/05 18:33:32 peter Exp $ +Software: AVR-GCC 4.x +Hardware: any AVR with built-in UART, +License: GNU General Public License + +DESCRIPTION: + An interrupt is generated when the UART has finished transmitting or + receiving a byte. The interrupt handling routines use circular buffers + for buffering received and transmitted data. + + The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define + the buffer size in bytes. Note that these variables must be a + power of 2. + +USAGE: + Refere to the header file uart.h for a description of the routines. + See also example test_uart.c. + +NOTES: + Based on Atmel Application Note AVR306 + +LICENSE: + Copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +*************************************************************************/ +#include +#include +#include +#include "uart.h" + + +/* + * constants and macros + */ + +/* size of RX/TX buffers */ +#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1) +#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1) + +#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK ) +#error RX buffer size is not a power of 2 +#endif +#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK ) +#error TX buffer size is not a power of 2 +#endif + + +#if defined(__AVR_AT90S2313__) || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S8515__) || \ + defined(__AVR_AT90S4434__) || defined(__AVR_AT90S8535__) || \ + defined(__AVR_ATmega103__) + /* old AVR classic or ATmega103 with one UART */ + #define UART0_RECEIVE_INTERRUPT UART_RX_vect + #define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect + #define UART0_STATUS USR + #define UART0_CONTROL UCR + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE + #define UART0_UBRRL UBRR + #define UART0_BIT_U2X U2X + #define UART0_BIT_RXCIE RXCIE + #define UART0_BIT_RXEN RXEN + #define UART0_BIT_TXEN TXEN +#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__) + /* old AVR classic with one UART */ + #define UART0_RECEIVE_INTERRUPT UART_RX_vect + #define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE + #define UART0_UBRRL UBRR + #define UART0_BIT_U2X U2X + #define UART0_BIT_RXCIE RXCIE + #define UART0_BIT_RXEN RXEN + #define UART0_BIT_TXEN TXEN +#elif defined(__AVR_AT90PWM216__) || defined(__AVR_AT90PWM316__) + /* AT90PWN216/316 with one USART */ + #define UART0_RECEIVE_INTERRUPT USART_RX_vect + #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_CONTROLC UCSRC + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE + #define UART0_UBRRL UBRRL + #define UART0_UBRRH UBRRH + #define UART0_BIT_U2X U2X + #define UART0_BIT_RXCIE RXCIE + #define UART0_BIT_RXEN RXEN + #define UART0_BIT_TXEN TXEN + #define UART0_BIT_UCSZ0 UCSZ0 + #define UART0_BIT_UCSZ1 UCSZ1 +#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega8A__) || \ + defined(__AVR_ATmega16__) || defined(__AVR_ATmega16A__) || \ + defined(__AVR_ATmega32__) || defined(__AVR_ATmega32A__) || \ + defined(__AVR_ATmega323__) + /* ATmega with one USART */ + #define UART0_RECEIVE_INTERRUPT USART_RXC_vect + #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_CONTROLC UCSRC + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE + #define UART0_UBRRL UBRRL + #define UART0_UBRRH UBRRH + #define UART0_BIT_U2X U2X + #define UART0_BIT_RXCIE RXCIE + #define UART0_BIT_RXEN RXEN + #define UART0_BIT_TXEN TXEN + #define UART0_BIT_UCSZ0 UCSZ0 + #define UART0_BIT_UCSZ1 UCSZ1 + #define UART0_BIT_URSEL URSEL +#elif defined (__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) + #define UART0_RECEIVE_INTERRUPT USART_RX_vect + #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_CONTROLC UCSRC + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE + #define UART0_UBRRL UBRRL + #define UART0_UBRRH UBRRH + #define UART0_BIT_U2X U2X + #define UART0_BIT_RXCIE RXCIE + #define UART0_BIT_RXEN RXEN + #define UART0_BIT_TXEN TXEN + #define UART0_BIT_UCSZ0 UCSZ0 + #define UART0_BIT_UCSZ1 UCSZ1 + #define UART0_BIT_URSEL URSEL +#elif defined(__AVR_ATmega163__) + /* ATmega163 with one UART */ + #define UART0_RECEIVE_INTERRUPT UART_RX_vect + #define UART0_TRANSMIT_INTERRUPT UART_UDRE_vect + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE + #define UART0_UBRRL UBRR + #define UART0_UBRRH UBRRHI + #define UART0_BIT_U2X U2X + #define UART0_BIT_RXCIE RXCIE + #define UART0_BIT_RXEN RXEN + #define UART0_BIT_TXEN TXEN +#elif defined(__AVR_ATmega162__) + /* ATmega with two USART */ + #define ATMEGA_USART1 + #define UART0_RECEIVE_INTERRUPT USART0_RXC_vect + #define UART1_RECEIVE_INTERRUPT USART1_RXC_vect + #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect + #define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_CONTROLC UCSR0C + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART0_UBRRL UBRR0L + #define UART0_UBRRH UBRR0H + #define UART0_BIT_URSEL URSEL0 + #define UART0_BIT_U2X U2X0 + #define UART0_BIT_RXCIE RXCIE0 + #define UART0_BIT_RXEN RXEN0 + #define UART0_BIT_TXEN TXEN0 + #define UART0_BIT_UCSZ0 UCSZ00 + #define UART0_BIT_UCSZ1 UCSZ01 + #define UART1_STATUS UCSR1A + #define UART1_CONTROL UCSR1B + #define UART1_CONTROLC UCSR1C + #define UART1_DATA UDR1 + #define UART1_UDRIE UDRIE1 + #define UART1_UBRRL UBRR1L + #define UART1_UBRRH UBRR1H + #define UART1_BIT_URSEL URSEL1 + #define UART1_BIT_U2X U2X1 + #define UART1_BIT_RXCIE RXCIE1 + #define UART1_BIT_RXEN RXEN1 + #define UART1_BIT_TXEN TXEN1 + #define UART1_BIT_UCSZ0 UCSZ10 + #define UART1_BIT_UCSZ1 UCSZ11 +#elif defined(__AVR_ATmega161__) + /* ATmega with UART */ + #error "AVR ATmega161 currently not supported by this libaray !" +#elif defined(__AVR_ATmega169__) + /* ATmega with one USART */ + #define UART0_RECEIVE_INTERRUPT USART0_RX_vect + #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_CONTROLC UCSRC + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE + #define UART0_UBRRL UBRRL + #define UART0_UBRRH UBRRH + #define UART0_BIT_U2X U2X + #define UART0_BIT_RXCIE RXCIE + #define UART0_BIT_RXEN RXEN + #define UART0_BIT_TXEN TXEN + #define UART0_BIT_UCSZ0 UCSZ0 + #define UART0_BIT_UCSZ1 UCSZ1 +#elif defined(__AVR_ATmega48__) || defined(__AVR_ATmega48A__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PA__) || defined(__AVR_ATmega48PB__) || \ + defined(__AVR_ATmega88__) || defined(__AVR_ATmega88A__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PA__) || defined(__AVR_ATmega88PB__) || \ + defined(__AVR_ATmega168__) || defined(__AVR_ATmega168A__)|| defined(__AVR_ATmega168P__)|| defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || \ + defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || \ + defined(__AVR_ATmega3250__) || defined(__AVR_ATmega3290__) ||defined(__AVR_ATmega6450__) || defined(__AVR_ATmega6490__) + /* ATmega with one USART */ + #define UART0_RECEIVE_INTERRUPT USART_RX_vect + #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_CONTROLC UCSR0C + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART0_UBRRL UBRR0L + #define UART0_UBRRH UBRR0H + #define UART0_BIT_U2X U2X0 + #define UART0_BIT_RXCIE RXCIE0 + #define UART0_BIT_RXEN RXEN0 + #define UART0_BIT_TXEN TXEN0 + #define UART0_BIT_UCSZ0 UCSZ00 + #define UART0_BIT_UCSZ1 UCSZ01 +#elif defined(__AVR_ATtiny2313__) || defined(__AVR_ATtiny2313A__) || defined(__AVR_ATtiny4313__) + /* ATtiny with one USART */ + #define UART0_RECEIVE_INTERRUPT USART_RX_vect + #define UART0_TRANSMIT_INTERRUPT USART_UDRE_vect + #define UART0_STATUS UCSRA + #define UART0_CONTROL UCSRB + #define UART0_CONTROLC UCSRC + #define UART0_DATA UDR + #define UART0_UDRIE UDRIE + #define UART0_UBRRL UBRRL + #define UART0_UBRRH UBRRH + #define UART0_BIT_U2X U2X + #define UART0_BIT_RXCIE RXCIE + #define UART0_BIT_RXEN RXEN + #define UART0_BIT_TXEN TXEN + #define UART0_BIT_UCSZ0 UCSZ0 + #define UART0_BIT_UCSZ1 UCSZ1 +#elif defined(__AVR_ATmega329__) || defined(__AVR_ATmega649__) || defined(__AVR_ATmega3290__) || defined(__AVR_ATmega6490__) ||\ + defined(__AVR_ATmega169A__) || defined(__AVR_ATmega169PA__) || \ + defined(__AVR_ATmega329A__) || defined(__AVR_ATmega329PA__) || defined(__AVR_ATmega3290A__) || defined(__AVR_ATmega3290PA__) || \ + defined(__AVR_ATmega649A__) || defined(__AVR_ATmega649P__) || defined(__AVR_ATmega6490A__) || defined(__AVR_ATmega6490P__) || \ + defined(__AVR_ATmega165__) || defined(__AVR_ATmega325__) || defined(__AVR_ATmega645__) || defined(__AVR_ATmega3250__) || defined(__AVR_ATmega6450__) || \ + defined(__AVR_ATmega165A__) || defined(__AVR_ATmega165PA__) || \ + defined(__AVR_ATmega325A__) || defined(__AVR_ATmega325PA__) || defined(__AVR_ATmega3250A__) || defined(__AVR_ATmega3250PA__) ||\ + defined(__AVR_ATmega645A__) || defined(__AVR_ATmega645PA__) || defined(__AVR_ATmega6450A__) || defined(__AVR_ATmega6450PA__) || \ + defined(__AVR_ATmega644__) + /* ATmega with one USART */ + #define UART0_RECEIVE_INTERRUPT USART0_RX_vect + #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_CONTROLC UCSR0C + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART0_UBRRL UBRR0L + #define UART0_UBRRH UBRR0H + #define UART0_BIT_U2X U2X0 + #define UART0_BIT_RXCIE RXCIE0 + #define UART0_BIT_RXEN RXEN0 + #define UART0_BIT_TXEN TXEN0 + #define UART0_BIT_UCSZ0 UCSZ00 + #define UART0_BIT_UCSZ1 UCSZ01 +#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega128A__) ||\ + defined(__AVR_ATmega640__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) || \ + defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega644P__) || \ + defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164PA__) || defined(__AVR_ATmega324A__) || defined(__AVR_ATmega324PA__) || \ + defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) ||\ + defined(__AVR_ATtiny1634__) + /* ATmega with two USART */ + #define ATMEGA_USART1 + #define UART0_RECEIVE_INTERRUPT USART0_RX_vect + #define UART1_RECEIVE_INTERRUPT USART1_RX_vect + #define UART0_TRANSMIT_INTERRUPT USART0_UDRE_vect + #define UART1_TRANSMIT_INTERRUPT USART1_UDRE_vect + #define UART0_STATUS UCSR0A + #define UART0_CONTROL UCSR0B + #define UART0_CONTROLC UCSR0C + #define UART0_DATA UDR0 + #define UART0_UDRIE UDRIE0 + #define UART0_UBRRL UBRR0L + #define UART0_UBRRH UBRR0H + #define UART0_BIT_U2X U2X0 + #define UART0_BIT_RXCIE RXCIE0 + #define UART0_BIT_RXEN RXEN0 + #define UART0_BIT_TXEN TXEN0 + #define UART0_BIT_UCSZ0 UCSZ00 + #define UART0_BIT_UCSZ1 UCSZ01 + #define UART1_STATUS UCSR1A + #define UART1_CONTROL UCSR1B + #define UART1_CONTROLC UCSR1C + #define UART1_DATA UDR1 + #define UART1_UDRIE UDRIE1 + #define UART1_UBRRL UBRR1L + #define UART1_UBRRH UBRR1H + #define UART1_BIT_U2X U2X1 + #define UART1_BIT_RXCIE RXCIE1 + #define UART1_BIT_RXEN RXEN1 + #define UART1_BIT_TXEN TXEN1 + #define UART1_BIT_UCSZ0 UCSZ10 + #define UART1_BIT_UCSZ1 UCSZ11 +#elif defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || \ + defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || \ + defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || \ + defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1287__) + #define UART0_RECEIVE_INTERRUPT USART1_RX_vect + #define UART0_TRANSMIT_INTERRUPT USART1_UDRE_vect + #define UART0_STATUS UCSR1A + #define UART0_CONTROL UCSR1B + #define UART0_CONTROLC UCSR1C + #define UART0_DATA UDR1 + #define UART0_UDRIE UDRIE1 + #define UART0_UBRRL UBRR1L + #define UART0_UBRRH UBRR1H + #define UART0_BIT_U2X U2X1 + #define UART0_BIT_RXCIE RXCIE1 + #define UART0_BIT_RXEN RXEN1 + #define UART0_BIT_TXEN TXEN1 + #define UART0_BIT_UCSZ0 UCSZ10 + #define UART0_BIT_UCSZ1 UCSZ11 +#else + #error "no UART definition for MCU available" +#endif + + + +/* + * module global variables + */ +static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE]; +static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE]; +static volatile unsigned char UART_TxHead; +static volatile unsigned char UART_TxTail; +static volatile unsigned char UART_RxHead; +static volatile unsigned char UART_RxTail; +static volatile unsigned char UART_LastRxError; + +#if defined( ATMEGA_USART1 ) +static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE]; +static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE]; +static volatile unsigned char UART1_TxHead; +static volatile unsigned char UART1_TxTail; +static volatile unsigned char UART1_RxHead; +static volatile unsigned char UART1_RxTail; +static volatile unsigned char UART1_LastRxError; +#endif + + + +ISR (UART0_RECEIVE_INTERRUPT) +/************************************************************************* +Function: UART Receive Complete interrupt +Purpose: called when the UART has received a character +**************************************************************************/ +{ + unsigned char tmphead; + unsigned char data; + unsigned char usr; + unsigned char lastRxError; + + + /* read UART status register and UART data register */ + usr = UART0_STATUS; + data = UART0_DATA; + + /* get FEn (Frame Error) DORn (Data OverRun) UPEn (USART Parity Error) bits */ +#if defined(FE) && defined(DOR) && defined(UPE) + lastRxError = usr & (_BV(FE)|_BV(DOR)|_BV(UPE) ); +#elif defined(FE0) && defined(DOR0) && defined(UPE0) + lastRxError = usr & (_BV(FE0)|_BV(DOR0)|_BV(UPE0) ); +#elif defined(FE1) && defined(DOR1) && defined(UPE1) + lastRxError = usr & (_BV(FE1)|_BV(DOR1)|_BV(UPE1) ); +#elif defined(FE) && defined(DOR) + lastRxError = usr & (_BV(FE)|_BV(DOR) ); +#endif + + /* calculate buffer index */ + tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK; + + if ( tmphead == UART_RxTail ) { + /* error: receive buffer overflow */ + lastRxError = UART_BUFFER_OVERFLOW >> 8; + }else{ + /* store new index */ + UART_RxHead = tmphead; + /* store received data in buffer */ + UART_RxBuf[tmphead] = data; + } + UART_LastRxError |= lastRxError; +} + + +ISR (UART0_TRANSMIT_INTERRUPT) +/************************************************************************* +Function: UART Data Register Empty interrupt +Purpose: called when the UART is ready to transmit the next byte +**************************************************************************/ +{ + unsigned char tmptail; + + + if ( UART_TxHead != UART_TxTail) { + /* calculate and store new buffer index */ + tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK; + UART_TxTail = tmptail; + /* get one byte from buffer and write it to UART */ + UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */ + }else{ + /* tx buffer empty, disable UDRE interrupt */ + UART0_CONTROL &= ~_BV(UART0_UDRIE); + } +} + + +/************************************************************************* +Function: uart_init() +Purpose: initialize UART and set baudrate +Input: baudrate using macro UART_BAUD_SELECT() +Returns: none +**************************************************************************/ +void uart_init(unsigned int baudrate) +{ + UART_TxHead = 0; + UART_TxTail = 0; + UART_RxHead = 0; + UART_RxTail = 0; + +#ifdef UART_TEST +#ifndef UART0_BIT_U2X +#warning "UART0_BIT_U2X not defined" +#endif +#ifndef UART0_UBRRH +#warning "UART0_UBRRH not defined" +#endif +#ifndef UART0_CONTROLC +#warning "UART0_CONTROLC not defined" +#endif +#if defined(URSEL) || defined(URSEL0) +#ifndef UART0_BIT_URSEL +#warning "UART0_BIT_URSEL not defined" +#endif +#endif +#endif + + /* Set baud rate */ + if ( baudrate & 0x8000 ) + { + #if UART0_BIT_U2X + UART0_STATUS = (1<>8)&0x80) ; + #endif + UART0_UBRRL = (unsigned char) (baudrate&0x00FF); + + /* Enable USART receiver and transmitter and receive complete interrupt */ + UART0_CONTROL = _BV(UART0_BIT_RXCIE)|(1<> 8; + }else{ + /* store new index */ + UART1_RxHead = tmphead; + /* store received data in buffer */ + UART1_RxBuf[tmphead] = data; + } + UART1_LastRxError |= lastRxError; +} + + +ISR(UART1_TRANSMIT_INTERRUPT) +/************************************************************************* +Function: UART1 Data Register Empty interrupt +Purpose: called when the UART1 is ready to transmit the next byte +**************************************************************************/ +{ + unsigned char tmptail; + + + if ( UART1_TxHead != UART1_TxTail) { + /* calculate and store new buffer index */ + tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK; + UART1_TxTail = tmptail; + /* get one byte from buffer and write it to UART */ + UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */ + }else{ + /* tx buffer empty, disable UDRE interrupt */ + UART1_CONTROL &= ~_BV(UART1_UDRIE); + } +} + + +/************************************************************************* +Function: uart1_init() +Purpose: initialize UART1 and set baudrate +Input: baudrate using macro UART_BAUD_SELECT() +Returns: none +**************************************************************************/ +void uart1_init(unsigned int baudrate) +{ + UART1_TxHead = 0; + UART1_TxTail = 0; + UART1_RxHead = 0; + UART1_RxTail = 0; + +#ifdef UART_TEST +#ifndef UART1_BIT_U2X +#warning "UART1_BIT_U2X not defined" +#endif +#ifndef UART1_UBRRH +#warning "UART1_UBRRH not defined" +#endif +#ifndef UART1_CONTROLC +#warning "UART1_CONTROLC not defined" +#endif +#if defined(URSEL) || defined(URSEL1) +#ifndef UART1_BIT_URSEL +#warning "UART1_BIT_URSEL not defined" +#endif +#endif +#endif + + /* Set baud rate */ + if ( baudrate & 0x8000 ) + { + #if UART1_BIT_U2X + UART1_STATUS = (1<>8)&0x80) ; + UART1_UBRRL = (unsigned char) baudrate; + + /* Enable USART receiver and transmitter and receive complete interrupt */ + UART1_CONTROL = _BV(UART1_BIT_RXCIE)|(1< http://tinyurl.com/peterfleury +File: $Id: uart.h,v 1.13 2015/01/11 13:53:25 peter Exp $ +Software: AVR-GCC 4.x, AVR Libc 1.4 or higher +Hardware: any AVR with built-in UART/USART +Usage: see Doxygen manual + +LICENSE: + Copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + +************************************************************************/ + +/** + * @file + * @defgroup pfleury_uart UART Library + * @code #include @endcode + * + * @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers. + * + * This library can be used to transmit and receive data through the built in UART. + * + * An interrupt is generated when the UART has finished transmitting or + * receiving a byte. The interrupt handling routines use circular buffers + * for buffering received and transmitted data. + * + * The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define + * the size of the circular buffers in bytes. Note that these constants must be a power of 2. + * You may need to adapt these constants to your target and your application by adding + * CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_TX_BUFFER_SIZE=nn to your Makefile. + * + * @note Based on Atmel Application Note AVR306 + * @author Peter Fleury pfleury@gmx.ch http://tinyurl.com/peterfleury + * @copyright (C) 2015 Peter Fleury, GNU General Public License Version 3 + */ + + +#include + +#if (__GNUC__ * 100 + __GNUC_MINOR__) < 405 +#error "This library requires AVR-GCC 4.5 or later, update to newer AVR-GCC compiler !" +#endif + + +/**@{*/ + + +/* +** constants and macros +*/ + + +/** @brief UART Baudrate Expression + * @param xtalCpu system clock in Mhz, e.g. 4000000UL for 4Mhz + * @param baudRate baudrate in bps, e.g. 1200, 2400, 9600 + */ +#define UART_BAUD_SELECT(baudRate,xtalCpu) (((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL) + +/** @brief UART Baudrate Expression for ATmega double speed mode + * @param xtalCpu system clock in Mhz, e.g. 4000000UL for 4Mhz + * @param baudRate baudrate in bps, e.g. 1200, 2400, 9600 + */ +#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) ( ((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000) + +/** @brief Size of the circular receive buffer, must be power of 2 + * + * You may need to adapt this constant to your target and your application by adding + * CDEFS += -DUART_RX_BUFFER_SIZE=nn to your Makefile. + */ +#ifndef UART_RX_BUFFER_SIZE +#define UART_RX_BUFFER_SIZE 32 +#endif + +/** @brief Size of the circular transmit buffer, must be power of 2 + * + * You may need to adapt this constant to your target and your application by adding + * CDEFS += -DUART_TX_BUFFER_SIZE=nn to your Makefile. + */ +#ifndef UART_TX_BUFFER_SIZE +#define UART_TX_BUFFER_SIZE 32 +#endif + +/* test if the size of the circular buffers fits into SRAM */ +#if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) ) +#error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM" +#endif + +/* +** high byte error return code of uart_getc() +*/ +#define UART_FRAME_ERROR 0x1000 /**< @brief Framing Error by UART */ +#define UART_OVERRUN_ERROR 0x0800 /**< @brief Overrun condition by UART */ +#define UART_PARITY_ERROR 0x0400 /**< @brief Parity Error by UART */ +#define UART_BUFFER_OVERFLOW 0x0200 /**< @brief receive ringbuffer overflow */ +#define UART_NO_DATA 0x0100 /**< @brief no receive data available */ + + +/* +** function prototypes +*/ + +/** + @brief Initialize UART and set baudrate + @param baudrate Specify baudrate using macro UART_BAUD_SELECT() + @return none +*/ +extern void uart_init(unsigned int baudrate); + + +/** + * @brief Get received byte from ringbuffer + * + * Returns in the lower byte the received character and in the + * higher byte the last receive error. + * UART_NO_DATA is returned when no data is available. + * + * @return lower byte: received byte from ringbuffer + * @return higher byte: last receive status + * - \b 0 successfully received data from UART + * - \b UART_NO_DATA + *
no receive data available + * - \b UART_BUFFER_OVERFLOW + *
Receive ringbuffer overflow. + * We are not reading the receive buffer fast enough, + * one or more received character have been dropped + * - \b UART_OVERRUN_ERROR + *
Overrun condition by UART. + * A character already present in the UART UDR register was + * not read by the interrupt handler before the next character arrived, + * one or more received characters have been dropped. + * - \b UART_FRAME_ERROR + *
Framing Error by UART + */ +extern unsigned int uart_getc(void); + + +/** + * @brief Put byte to ringbuffer for transmitting via UART + * @param data byte to be transmitted + * @return none + */ +extern void uart_putc(unsigned char data); + + +/** + * @brief Put string to ringbuffer for transmitting via UART + * + * The string is buffered by the uart library in a circular buffer + * and one character at a time is transmitted to the UART using interrupts. + * Blocks if it can not write the whole string into the circular buffer. + * + * @param s string to be transmitted + * @return none + */ +extern void uart_puts(const char *s ); + + +/** + * @brief Put string from program memory to ringbuffer for transmitting via UART. + * + * The string is buffered by the uart library in a circular buffer + * and one character at a time is transmitted to the UART using interrupts. + * Blocks if it can not write the whole string into the circular buffer. + * + * @param s program memory string to be transmitted + * @return none + * @see uart_puts_P + */ +extern void uart_puts_p(const char *s ); + +/** + * @brief Macro to automatically put a string constant into program memory + */ +#define uart_puts_P(__s) uart_puts_p(PSTR(__s)) + + + +/** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */ +extern void uart1_init(unsigned int baudrate); +/** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */ +extern unsigned int uart1_getc(void); +/** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */ +extern void uart1_putc(unsigned char data); +/** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */ +extern void uart1_puts(const char *s ); +/** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */ +extern void uart1_puts_p(const char *s ); +/** @brief Macro to automatically put a string constant into program memory */ +#define uart1_puts_P(__s) uart1_puts_p(PSTR(__s)) + +/**@}*/ + + +#endif // UART_H +