Peter Fleury uart lib added. Init call added to the project main files.

This commit is contained in:
Kai Lauterbach 2016-07-28 12:33:35 +02:00
parent 8b8727970d
commit fa7ad1ad90
9 changed files with 3385 additions and 3 deletions

View file

@ -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();
}

View file

@ -41,6 +41,7 @@
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <string.h>
#include "Descriptors.h"
@ -48,8 +49,14 @@
#include <LUFA/Drivers/USB/USB.h>
#include <LUFA/Platform/Platform.h>
#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

View file

@ -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

338
src/uart/Makefile.uart Normal file
View file

@ -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=<size in bytes> and -DUART_TX_BUFFER_SIZE=<size in bytes>
# 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 /<directory>/
#vpath %.S /<directory>/
# 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

1449
src/uart/doxygen.css Normal file

File diff suppressed because it is too large Load diff

472
src/uart/manual_uart.html Normal file
View file

@ -0,0 +1,472 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.9.1"/>
<title>AVR-GCC Libraries: UART Library &lt;uart.h&gt;</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td style="padding-left: 0.5em;">
<div id="projectname">AVR-GCC Libraries
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.9.1 -->
<div id="navrow1" class="tabs">
<ul class="tablist">
<li><a href="index.html"><span>Main&#160;Page</span></a></li>
<li><a href="modules.html"><span>Modules</span></a></li>
<li><a href="files.html"><span>Files</span></a></li>
</ul>
</div>
</div><!-- top -->
<div class="header">
<div class="summary">
<a href="#define-members">Macros</a> &#124;
<a href="#func-members">Functions</a> </div>
<div class="headertitle">
<div class="title">UART Library &lt;uart.h&gt;</div> </div>
</div><!--header-->
<div class="contents">
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<p>Interrupt UART library using the built-in UART with transmit and receive circular buffers. </p>
<div class="fragment"><div class="line"><span class="preprocessor">#include &lt;<a class="code" href="uart_8h.html">uart.h</a>&gt;</span> </div>
</div><!-- fragment --><p>This library can be used to transmit and receive data through the built in UART.</p>
<p>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.</p>
<p>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.</p>
<dl class="section note"><dt>Note</dt><dd>Based on Atmel Application Note AVR306 </dd></dl>
<dl class="section author"><dt>Author</dt><dd>Peter Fleury <a href="#" onclick="location.href='mai'+'lto:'+'pfl'+'eu'+'ry@'+'gm'+'x.c'+'h'; return false;">pfleu<span style="display: none;">.nosp@m.</span>ry@g<span style="display: none;">.nosp@m.</span>mx.ch</a> <a href="http://tinyurl.com/peterfleury">http://tinyurl.com/peterfleury</a> </dd></dl>
<dl class="section copyright"><dt>Copyright</dt><dd>(C) 2015 Peter Fleury, GNU General Public License Version 3 </dd></dl>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="define-members"></a>
Macros</h2></td></tr>
<tr class="memitem:ga367ff7b5de225ed936a63239ad4adb0b"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga367ff7b5de225ed936a63239ad4adb0b">UART_BAUD_SELECT</a>(baudRate, xtalCpu)&#160;&#160;&#160;(((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL)</td></tr>
<tr class="memdesc:ga367ff7b5de225ed936a63239ad4adb0b"><td class="mdescLeft">&#160;</td><td class="mdescRight">UART Baudrate Expression. <a href="#ga367ff7b5de225ed936a63239ad4adb0b">More...</a><br /></td></tr>
<tr class="separator:ga367ff7b5de225ed936a63239ad4adb0b"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga1a02d45130520cb651ab313e69039382"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga1a02d45130520cb651ab313e69039382">UART_BAUD_SELECT_DOUBLE_SPEED</a>(baudRate, xtalCpu)&#160;&#160;&#160;( ((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000)</td></tr>
<tr class="memdesc:ga1a02d45130520cb651ab313e69039382"><td class="mdescLeft">&#160;</td><td class="mdescRight">UART Baudrate Expression for ATmega double speed mode. <a href="#ga1a02d45130520cb651ab313e69039382">More...</a><br /></td></tr>
<tr class="separator:ga1a02d45130520cb651ab313e69039382"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga5bdd6772c246436bb14377095de79b31"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga5bdd6772c246436bb14377095de79b31">UART_RX_BUFFER_SIZE</a>&#160;&#160;&#160;32</td></tr>
<tr class="memdesc:ga5bdd6772c246436bb14377095de79b31"><td class="mdescLeft">&#160;</td><td class="mdescRight">Size of the circular receive buffer, must be power of 2. <a href="#ga5bdd6772c246436bb14377095de79b31">More...</a><br /></td></tr>
<tr class="separator:ga5bdd6772c246436bb14377095de79b31"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga05f5d709605c6317c97e4974bec3402a"><td class="memItemLeft" align="right" valign="top">#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga05f5d709605c6317c97e4974bec3402a">UART_TX_BUFFER_SIZE</a>&#160;&#160;&#160;32</td></tr>
<tr class="memdesc:ga05f5d709605c6317c97e4974bec3402a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Size of the circular transmit buffer, must be power of 2. <a href="#ga05f5d709605c6317c97e4974bec3402a">More...</a><br /></td></tr>
<tr class="separator:ga05f5d709605c6317c97e4974bec3402a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gabcdb1041d763560cd8f8e722370dfd37"><td class="memItemLeft" align="right" valign="top"><a class="anchor" id="gabcdb1041d763560cd8f8e722370dfd37"></a>
#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gabcdb1041d763560cd8f8e722370dfd37">UART_FRAME_ERROR</a>&#160;&#160;&#160;0x1000</td></tr>
<tr class="memdesc:gabcdb1041d763560cd8f8e722370dfd37"><td class="mdescLeft">&#160;</td><td class="mdescRight">Framing Error by UART. <br /></td></tr>
<tr class="separator:gabcdb1041d763560cd8f8e722370dfd37"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga3183177e3613d8785d8cc8516931beb6"><td class="memItemLeft" align="right" valign="top"><a class="anchor" id="ga3183177e3613d8785d8cc8516931beb6"></a>
#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga3183177e3613d8785d8cc8516931beb6">UART_OVERRUN_ERROR</a>&#160;&#160;&#160;0x0800</td></tr>
<tr class="memdesc:ga3183177e3613d8785d8cc8516931beb6"><td class="mdescLeft">&#160;</td><td class="mdescRight">Overrun condition by UART. <br /></td></tr>
<tr class="separator:ga3183177e3613d8785d8cc8516931beb6"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga946e3d317937e003d2057bf19e96dd1d"><td class="memItemLeft" align="right" valign="top"><a class="anchor" id="ga946e3d317937e003d2057bf19e96dd1d"></a>
#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga946e3d317937e003d2057bf19e96dd1d">UART_PARITY_ERROR</a>&#160;&#160;&#160;0x0400</td></tr>
<tr class="memdesc:ga946e3d317937e003d2057bf19e96dd1d"><td class="mdescLeft">&#160;</td><td class="mdescRight">Parity Error by UART. <br /></td></tr>
<tr class="separator:ga946e3d317937e003d2057bf19e96dd1d"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga94758f3dad6864703b7417d3e40f11df"><td class="memItemLeft" align="right" valign="top"><a class="anchor" id="ga94758f3dad6864703b7417d3e40f11df"></a>
#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga94758f3dad6864703b7417d3e40f11df">UART_BUFFER_OVERFLOW</a>&#160;&#160;&#160;0x0200</td></tr>
<tr class="memdesc:ga94758f3dad6864703b7417d3e40f11df"><td class="mdescLeft">&#160;</td><td class="mdescRight">receive ringbuffer overflow <br /></td></tr>
<tr class="separator:ga94758f3dad6864703b7417d3e40f11df"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga77ba544d423ff42d400220a05303f268"><td class="memItemLeft" align="right" valign="top"><a class="anchor" id="ga77ba544d423ff42d400220a05303f268"></a>
#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga77ba544d423ff42d400220a05303f268">UART_NO_DATA</a>&#160;&#160;&#160;0x0100</td></tr>
<tr class="memdesc:ga77ba544d423ff42d400220a05303f268"><td class="mdescLeft">&#160;</td><td class="mdescRight">no receive data available <br /></td></tr>
<tr class="separator:ga77ba544d423ff42d400220a05303f268"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gae9e143569df2285379bc55f9f5595bf9"><td class="memItemLeft" align="right" valign="top"><a class="anchor" id="gae9e143569df2285379bc55f9f5595bf9"></a>
#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gae9e143569df2285379bc55f9f5595bf9">uart_puts_P</a>(__s)&#160;&#160;&#160;<a class="el" href="group__pfleury__uart.html#ga6d78b6744db6232f52b4616402036c2f">uart_puts_p</a>(PSTR(__s))</td></tr>
<tr class="memdesc:gae9e143569df2285379bc55f9f5595bf9"><td class="mdescLeft">&#160;</td><td class="mdescRight">Macro to automatically put a string constant into program memory. <br /></td></tr>
<tr class="separator:gae9e143569df2285379bc55f9f5595bf9"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaabd7a5b0c15611ee9ecb2873cc9ee87a"><td class="memItemLeft" align="right" valign="top"><a class="anchor" id="gaabd7a5b0c15611ee9ecb2873cc9ee87a"></a>
#define&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gaabd7a5b0c15611ee9ecb2873cc9ee87a">uart1_puts_P</a>(__s)&#160;&#160;&#160;<a class="el" href="group__pfleury__uart.html#ga1e8074d0a2d5922601c5db2f9777ba79">uart1_puts_p</a>(PSTR(__s))</td></tr>
<tr class="memdesc:gaabd7a5b0c15611ee9ecb2873cc9ee87a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Macro to automatically put a string constant into program memory. <br /></td></tr>
<tr class="separator:gaabd7a5b0c15611ee9ecb2873cc9ee87a"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a name="func-members"></a>
Functions</h2></td></tr>
<tr class="memitem:gac19a76bb7d446125734a67f9f4b68991"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gac19a76bb7d446125734a67f9f4b68991">uart_init</a> (unsigned int baudrate)</td></tr>
<tr class="memdesc:gac19a76bb7d446125734a67f9f4b68991"><td class="mdescLeft">&#160;</td><td class="mdescRight">Initialize UART and set baudrate. <a href="#gac19a76bb7d446125734a67f9f4b68991">More...</a><br /></td></tr>
<tr class="separator:gac19a76bb7d446125734a67f9f4b68991"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaefaab30a8338ec46a6be35b99b1b4f09"><td class="memItemLeft" align="right" valign="top">unsigned int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gaefaab30a8338ec46a6be35b99b1b4f09">uart_getc</a> (void)</td></tr>
<tr class="memdesc:gaefaab30a8338ec46a6be35b99b1b4f09"><td class="mdescLeft">&#160;</td><td class="mdescRight">Get received byte from ringbuffer. <a href="#gaefaab30a8338ec46a6be35b99b1b4f09">More...</a><br /></td></tr>
<tr class="separator:gaefaab30a8338ec46a6be35b99b1b4f09"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gad975221bc08b901e4c7ad69f9c9a97e2"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gad975221bc08b901e4c7ad69f9c9a97e2">uart_putc</a> (unsigned char data)</td></tr>
<tr class="memdesc:gad975221bc08b901e4c7ad69f9c9a97e2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Put byte to ringbuffer for transmitting via UART. <a href="#gad975221bc08b901e4c7ad69f9c9a97e2">More...</a><br /></td></tr>
<tr class="separator:gad975221bc08b901e4c7ad69f9c9a97e2"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gae52facc0a56086a365bb0018160d8d71"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gae52facc0a56086a365bb0018160d8d71">uart_puts</a> (const char *s)</td></tr>
<tr class="memdesc:gae52facc0a56086a365bb0018160d8d71"><td class="mdescLeft">&#160;</td><td class="mdescRight">Put string to ringbuffer for transmitting via UART. <a href="#gae52facc0a56086a365bb0018160d8d71">More...</a><br /></td></tr>
<tr class="separator:gae52facc0a56086a365bb0018160d8d71"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga6d78b6744db6232f52b4616402036c2f"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga6d78b6744db6232f52b4616402036c2f">uart_puts_p</a> (const char *s)</td></tr>
<tr class="memdesc:ga6d78b6744db6232f52b4616402036c2f"><td class="mdescLeft">&#160;</td><td class="mdescRight">Put string from program memory to ringbuffer for transmitting via UART. <a href="#ga6d78b6744db6232f52b4616402036c2f">More...</a><br /></td></tr>
<tr class="separator:ga6d78b6744db6232f52b4616402036c2f"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga4db697cb5469fd70e794fa7df73a6d6a"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga4db697cb5469fd70e794fa7df73a6d6a">uart1_init</a> (unsigned int baudrate)</td></tr>
<tr class="memdesc:ga4db697cb5469fd70e794fa7df73a6d6a"><td class="mdescLeft">&#160;</td><td class="mdescRight">Initialize USART1 (only available on selected ATmegas) <a href="#ga4db697cb5469fd70e794fa7df73a6d6a">More...</a><br /></td></tr>
<tr class="separator:ga4db697cb5469fd70e794fa7df73a6d6a"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gaeb1405c641e5bc9b7224018f5e8d90de"><td class="memItemLeft" align="right" valign="top">unsigned int&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gaeb1405c641e5bc9b7224018f5e8d90de">uart1_getc</a> (void)</td></tr>
<tr class="memdesc:gaeb1405c641e5bc9b7224018f5e8d90de"><td class="mdescLeft">&#160;</td><td class="mdescRight">Get received byte of USART1 from ringbuffer. (only available on selected ATmega) <a href="#gaeb1405c641e5bc9b7224018f5e8d90de">More...</a><br /></td></tr>
<tr class="separator:gaeb1405c641e5bc9b7224018f5e8d90de"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:gab465f689d197fadfbacc374fc9411154"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#gab465f689d197fadfbacc374fc9411154">uart1_putc</a> (unsigned char data)</td></tr>
<tr class="memdesc:gab465f689d197fadfbacc374fc9411154"><td class="mdescLeft">&#160;</td><td class="mdescRight">Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) <a href="#gab465f689d197fadfbacc374fc9411154">More...</a><br /></td></tr>
<tr class="separator:gab465f689d197fadfbacc374fc9411154"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga5568f8f3913b218fd4d0346af78831b2"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga5568f8f3913b218fd4d0346af78831b2">uart1_puts</a> (const char *s)</td></tr>
<tr class="memdesc:ga5568f8f3913b218fd4d0346af78831b2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) <a href="#ga5568f8f3913b218fd4d0346af78831b2">More...</a><br /></td></tr>
<tr class="separator:ga5568f8f3913b218fd4d0346af78831b2"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ga1e8074d0a2d5922601c5db2f9777ba79"><td class="memItemLeft" align="right" valign="top">void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__pfleury__uart.html#ga1e8074d0a2d5922601c5db2f9777ba79">uart1_puts_p</a> (const char *s)</td></tr>
<tr class="memdesc:ga1e8074d0a2d5922601c5db2f9777ba79"><td class="mdescLeft">&#160;</td><td class="mdescRight">Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) <a href="#ga1e8074d0a2d5922601c5db2f9777ba79">More...</a><br /></td></tr>
<tr class="separator:ga1e8074d0a2d5922601c5db2f9777ba79"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<h2 class="groupheader">Macro Definition Documentation</h2>
<a class="anchor" id="ga367ff7b5de225ed936a63239ad4adb0b"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">#define UART_BAUD_SELECT</td>
<td>(</td>
<td class="paramtype">&#160;</td>
<td class="paramname">baudRate, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">&#160;</td>
<td class="paramname">xtalCpu&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td>&#160;&#160;&#160;(((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL)</td>
</tr>
</table>
</div><div class="memdoc">
<p>UART Baudrate Expression. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">xtalCpu</td><td>system clock in Mhz, e.g. 4000000UL for 4Mhz </td></tr>
<tr><td class="paramname">baudRate</td><td>baudrate in bps, e.g. 1200, 2400, 9600 </td></tr>
</table>
</dd>
</dl>
</div>
</div>
<a class="anchor" id="ga1a02d45130520cb651ab313e69039382"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">#define UART_BAUD_SELECT_DOUBLE_SPEED</td>
<td>(</td>
<td class="paramtype">&#160;</td>
<td class="paramname">baudRate, </td>
</tr>
<tr>
<td class="paramkey"></td>
<td></td>
<td class="paramtype">&#160;</td>
<td class="paramname">xtalCpu&#160;</td>
</tr>
<tr>
<td></td>
<td>)</td>
<td></td><td>&#160;&#160;&#160;( ((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000)</td>
</tr>
</table>
</div><div class="memdoc">
<p>UART Baudrate Expression for ATmega double speed mode. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">xtalCpu</td><td>system clock in Mhz, e.g. 4000000UL for 4Mhz </td></tr>
<tr><td class="paramname">baudRate</td><td>baudrate in bps, e.g. 1200, 2400, 9600 </td></tr>
</table>
</dd>
</dl>
</div>
</div>
<a class="anchor" id="ga5bdd6772c246436bb14377095de79b31"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">#define UART_RX_BUFFER_SIZE&#160;&#160;&#160;32</td>
</tr>
</table>
</div><div class="memdoc">
<p>Size of the circular receive buffer, must be power of 2. </p>
<p>You may need to adapt this constant to your target and your application by adding CDEFS += -DUART_RX_BUFFER_SIZE=nn to your Makefile. </p>
</div>
</div>
<a class="anchor" id="ga05f5d709605c6317c97e4974bec3402a"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">#define UART_TX_BUFFER_SIZE&#160;&#160;&#160;32</td>
</tr>
</table>
</div><div class="memdoc">
<p>Size of the circular transmit buffer, must be power of 2. </p>
<p>You may need to adapt this constant to your target and your application by adding CDEFS += -DUART_TX_BUFFER_SIZE=nn to your Makefile. </p>
</div>
</div>
<h2 class="groupheader">Function Documentation</h2>
<a class="anchor" id="gac19a76bb7d446125734a67f9f4b68991"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void uart_init </td>
<td>(</td>
<td class="paramtype">unsigned int&#160;</td>
<td class="paramname"><em>baudrate</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Initialize UART and set baudrate. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">baudrate</td><td>Specify baudrate using macro <a class="el" href="group__pfleury__uart.html#ga367ff7b5de225ed936a63239ad4adb0b" title="UART Baudrate Expression. ">UART_BAUD_SELECT()</a> </td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>none </dd></dl>
</div>
</div>
<a class="anchor" id="gaefaab30a8338ec46a6be35b99b1b4f09"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">unsigned int uart_getc </td>
<td>(</td>
<td class="paramtype">void&#160;</td>
<td class="paramname"></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Get received byte from ringbuffer. </p>
<p>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.</p>
<dl class="section return"><dt>Returns</dt><dd>lower byte: received byte from ringbuffer </dd>
<dd>
higher byte: last receive status<ul>
<li><b>0</b> successfully received data from UART</li>
<li><b>UART_NO_DATA</b> <br />
no receive data available</li>
<li><b>UART_BUFFER_OVERFLOW</b> <br />
Receive ringbuffer overflow. We are not reading the receive buffer fast enough, one or more received character have been dropped</li>
<li><b>UART_OVERRUN_ERROR</b> <br />
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.</li>
<li><b>UART_FRAME_ERROR</b> <br />
Framing Error by UART </li>
</ul>
</dd></dl>
</div>
</div>
<a class="anchor" id="gad975221bc08b901e4c7ad69f9c9a97e2"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void uart_putc </td>
<td>(</td>
<td class="paramtype">unsigned char&#160;</td>
<td class="paramname"><em>data</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Put byte to ringbuffer for transmitting via UART. </p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">data</td><td>byte to be transmitted </td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>none </dd></dl>
</div>
</div>
<a class="anchor" id="gae52facc0a56086a365bb0018160d8d71"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void uart_puts </td>
<td>(</td>
<td class="paramtype">const char *&#160;</td>
<td class="paramname"><em>s</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Put string to ringbuffer for transmitting via UART. </p>
<p>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.</p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">s</td><td>string to be transmitted </td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>none </dd></dl>
</div>
</div>
<a class="anchor" id="ga6d78b6744db6232f52b4616402036c2f"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void uart_puts_p </td>
<td>(</td>
<td class="paramtype">const char *&#160;</td>
<td class="paramname"><em>s</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Put string from program memory to ringbuffer for transmitting via UART. </p>
<p>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.</p>
<dl class="params"><dt>Parameters</dt><dd>
<table class="params">
<tr><td class="paramname">s</td><td>program memory string to be transmitted </td></tr>
</table>
</dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd>none </dd></dl>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__pfleury__uart.html#gae9e143569df2285379bc55f9f5595bf9" title="Macro to automatically put a string constant into program memory. ">uart_puts_P</a> </dd></dl>
</div>
</div>
<a class="anchor" id="ga4db697cb5469fd70e794fa7df73a6d6a"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void uart1_init </td>
<td>(</td>
<td class="paramtype">unsigned int&#160;</td>
<td class="paramname"><em>baudrate</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Initialize USART1 (only available on selected ATmegas) </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__pfleury__uart.html#gac19a76bb7d446125734a67f9f4b68991" title="Initialize UART and set baudrate. ">uart_init</a> </dd></dl>
</div>
</div>
<a class="anchor" id="gaeb1405c641e5bc9b7224018f5e8d90de"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">unsigned int uart1_getc </td>
<td>(</td>
<td class="paramtype">void&#160;</td>
<td class="paramname"></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Get received byte of USART1 from ringbuffer. (only available on selected ATmega) </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__pfleury__uart.html#gaefaab30a8338ec46a6be35b99b1b4f09" title="Get received byte from ringbuffer. ">uart_getc</a> </dd></dl>
</div>
</div>
<a class="anchor" id="gab465f689d197fadfbacc374fc9411154"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void uart1_putc </td>
<td>(</td>
<td class="paramtype">unsigned char&#160;</td>
<td class="paramname"><em>data</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__pfleury__uart.html#gad975221bc08b901e4c7ad69f9c9a97e2" title="Put byte to ringbuffer for transmitting via UART. ">uart_putc</a> </dd></dl>
</div>
</div>
<a class="anchor" id="ga5568f8f3913b218fd4d0346af78831b2"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void uart1_puts </td>
<td>(</td>
<td class="paramtype">const char *&#160;</td>
<td class="paramname"><em>s</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__pfleury__uart.html#gae52facc0a56086a365bb0018160d8d71" title="Put string to ringbuffer for transmitting via UART. ">uart_puts</a> </dd></dl>
</div>
</div>
<a class="anchor" id="ga1e8074d0a2d5922601c5db2f9777ba79"></a>
<div class="memitem">
<div class="memproto">
<table class="memname">
<tr>
<td class="memname">void uart1_puts_p </td>
<td>(</td>
<td class="paramtype">const char *&#160;</td>
<td class="paramname"><em>s</em></td><td>)</td>
<td></td>
</tr>
</table>
</div><div class="memdoc">
<p>Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="group__pfleury__uart.html#ga6d78b6744db6232f52b4616402036c2f" title="Put string from program memory to ringbuffer for transmitting via UART. ">uart_puts_p</a> </dd></dl>
</div>
</div>
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Sat Jan 31 2015 18:52:30 for AVR-GCC Libraries by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/>
</a> 1.8.9.1
</small></address>
</body>
</html>

129
src/uart/test_uart.c Normal file
View file

@ -0,0 +1,129 @@
/*************************************************************************
Title: Example program for the Interrupt controlled UART library
Author: Peter Fleury <pfleury@gmx.ch> 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 <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#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 );
}
}
}

777
src/uart/uart.c Normal file
View file

@ -0,0 +1,777 @@
/*************************************************************************
Title: Interrupt UART library with receive/transmit circular buffers
Author: Peter Fleury <pfleury@gmx.ch> 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 <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#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<<UART0_BIT_U2X); //Enable 2x speed
#endif
}
#if defined(UART0_UBRRH)
UART0_UBRRH = (unsigned char)((baudrate>>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<<UART0_BIT_RXEN)|(1<<UART0_BIT_TXEN);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef UART0_CONTROLC
#ifdef UART0_BIT_URSEL
UART0_CONTROLC = (1<<UART0_BIT_URSEL)|(1<<UART0_BIT_UCSZ1)|(1<<UART0_BIT_UCSZ0);
#else
UART0_CONTROLC = (1<<UART0_BIT_UCSZ1)|(1<<UART0_BIT_UCSZ0);
#endif
#endif
}/* uart_init */
/*************************************************************************
Function: uart_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
unsigned int uart_getc(void)
{
unsigned char tmptail;
unsigned char data;
unsigned char lastRxError;
if ( UART_RxHead == UART_RxTail ) {
return UART_NO_DATA; /* no data available */
}
/* calculate buffer index */
tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;
/* get data from receive buffer */
data = UART_RxBuf[tmptail];
lastRxError = UART_LastRxError;
/* store buffer index */
UART_RxTail = tmptail;
UART_LastRxError = 0;
return (lastRxError << 8) + data;
}/* uart_getc */
/*************************************************************************
Function: uart_putc()
Purpose: write byte to ringbuffer for transmitting via UART
Input: byte to be transmitted
Returns: none
**************************************************************************/
void uart_putc(unsigned char data)
{
unsigned char tmphead;
tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;
while ( tmphead == UART_TxTail ){
;/* wait for free space in buffer */
}
UART_TxBuf[tmphead] = data;
UART_TxHead = tmphead;
/* enable UDRE interrupt */
UART0_CONTROL |= _BV(UART0_UDRIE);
}/* uart_putc */
/*************************************************************************
Function: uart_puts()
Purpose: transmit string to UART
Input: string to be transmitted
Returns: none
**************************************************************************/
void uart_puts(const char *s )
{
while (*s)
uart_putc(*s++);
}/* uart_puts */
/*************************************************************************
Function: uart_puts_p()
Purpose: transmit string from program memory to UART
Input: program memory string to be transmitted
Returns: none
**************************************************************************/
void uart_puts_p(const char *progmem_s )
{
register char c;
while ( (c = pgm_read_byte(progmem_s++)) )
uart_putc(c);
}/* uart_puts_p */
/*
* these functions are only for ATmegas with two USART
*/
#if defined( ATMEGA_USART1 )
ISR(UART1_RECEIVE_INTERRUPT)
/*************************************************************************
Function: UART1 Receive Complete interrupt
Purpose: called when the UART1 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 = UART1_STATUS;
data = UART1_DATA;
/* get FEn (Frame Error) DORn (Data OverRun) UPEn (USART Parity Error) bits */
lastRxError = usr & (_BV(FE1)|_BV(DOR1)|_BV(UPE1) );
/* calculate buffer index */
tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;
if ( tmphead == UART1_RxTail ) {
/* error: receive buffer overflow */
lastRxError = UART_BUFFER_OVERFLOW >> 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<<UART1_BIT_U2X); //Enable 2x speed
#endif
}
UART1_UBRRH = (unsigned char)((baudrate>>8)&0x80) ;
UART1_UBRRL = (unsigned char) baudrate;
/* Enable USART receiver and transmitter and receive complete interrupt */
UART1_CONTROL = _BV(UART1_BIT_RXCIE)|(1<<UART1_BIT_RXEN)|(1<<UART1_BIT_TXEN);
/* Set frame format: asynchronous, 8data, no parity, 1stop bit */
#ifdef UART1_BIT_URSEL
UART1_CONTROLC = (1<<UART1_BIT_URSEL)|(1<<UART1_BIT_UCSZ1)|(1<<UART1_BIT_UCSZ0);
#else
UART1_CONTROLC = (1<<UART1_BIT_UCSZ1)|(1<<UART1_BIT_UCSZ0);
#endif
}/* uart_init */
/*************************************************************************
Function: uart1_getc()
Purpose: return byte from ringbuffer
Returns: lower byte: received byte from ringbuffer
higher byte: last receive error
**************************************************************************/
unsigned int uart1_getc(void)
{
unsigned char tmptail;
unsigned int data;
unsigned char lastRxError;
if ( UART1_RxHead == UART1_RxTail ) {
return UART_NO_DATA; /* no data available */
}
/* calculate buffer index */
tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;
/* get data from receive buffer */
data = UART1_RxBuf[tmptail];
lastRxError = UART1_LastRxError;
/* store buffer index */
UART1_RxTail = tmptail;
UART1_LastRxError = 0;
return (lastRxError << 8) + data;
}/* uart1_getc */
/*************************************************************************
Function: uart1_putc()
Purpose: write byte to ringbuffer for transmitting via UART
Input: byte to be transmitted
Returns: none
**************************************************************************/
void uart1_putc(unsigned char data)
{
unsigned char tmphead;
tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;
while ( tmphead == UART1_TxTail ){
;/* wait for free space in buffer */
}
UART1_TxBuf[tmphead] = data;
UART1_TxHead = tmphead;
/* enable UDRE interrupt */
UART1_CONTROL |= _BV(UART1_UDRIE);
}/* uart1_putc */
/*************************************************************************
Function: uart1_puts()
Purpose: transmit string to UART1
Input: string to be transmitted
Returns: none
**************************************************************************/
void uart1_puts(const char *s )
{
while (*s)
uart1_putc(*s++);
}/* uart1_puts */
/*************************************************************************
Function: uart1_puts_p()
Purpose: transmit string from program memory to UART1
Input: program memory string to be transmitted
Returns: none
**************************************************************************/
void uart1_puts_p(const char *progmem_s )
{
register char c;
while ( (c = pgm_read_byte(progmem_s++)) )
uart1_putc(c);
}/* uart1_puts_p */
#endif

207
src/uart/uart.h Normal file
View file

@ -0,0 +1,207 @@
#ifndef UART_H
#define UART_H
/************************************************************************
Title: Interrupt UART library with receive/transmit circular buffers
Author: Peter Fleury <pfleury@gmx.ch> 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 <uart.h>
* @code #include <uart.h> @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 <avr/pgmspace.h>
#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
* <br>no receive data available
* - \b UART_BUFFER_OVERFLOW
* <br>Receive ringbuffer overflow.
* We are not reading the receive buffer fast enough,
* one or more received character have been dropped
* - \b UART_OVERRUN_ERROR
* <br>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
* <br>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