Files
SyncHome/trunk/workspace/00_Lib/Serial/AVR-GCC-Tutorial-Der UART - Mikrocontroller_net.htm
topicchi 0b6afad8fe
2023-09-22 06:03:48 +00:00

1879 lines
112 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0065)http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART -->
<HTML
lang=de><HEAD><TITLE>AVR-GCC-Tutorial/Der UART - Mikrocontroller.net</TITLE>
<SCRIPT type=text/javascript>
var wgBreakFrames = false;
var wgContentLanguage = false;
</SCRIPT>
<META content="text/html; charset=UTF-8" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 8.00.7601.18283"><LINK title=Bearbeiten
rel=alternate type=application/x-wiki
href="/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit"><LINK
title=Bearbeiten rel=edit
href="/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit"><LINK
rel="shortcut icon" href="/favicon.ico"><LINK title="Uc-wiki (de)" rel=search
type=application/opensearchdescription+xml
href="/wikisoftware/opensearch_desc.php"><LINK rel=EditURI
type=application/rsd+xml
href="http://www.mikrocontroller.net/wikisoftware/api.php?action=rsd"><LINK
title="Atom-Feed für „Uc-wiki“" rel=alternate type=application/atom+xml
href="/wikisoftware/index.php?title=Spezial:Letzte_%C3%84nderungen&amp;feed=atom"><!-- <script type="text/javascript" src="/wikisoftware/skins/common/wikibits.js"></script> -->
<SCRIPT
src="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/load.php"></SCRIPT>
<SCRIPT>if(window.mw){
mw.config.set({"wgCanonicalNamespace":"","wgCanonicalSpecialPageName":false,"wgNamespaceNumber":0,"wgPageName":"AVR-GCC-Tutorial/Der_UART","wgTitle":"AVR-GCC-Tutorial/Der UART","wgCurRevisionId":78711,"wgArticleId":4483,"wgIsArticle":true,"wgAction":"view","wgUserName":null,"wgUserGroups":["*"],"wgCategories":["Avr-gcc Tutorial","UART und RS232"],"wgBreakFrames":false,"wgPageContentLanguage":"de","wgSeparatorTransformTable":[", .",". ,"],"wgDigitTransformTable":["",""],"wgDefaultDateFormat":"dmy","wgMonthNames":["","Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember"],"wgMonthNamesShort":["","Jan.","Feb.","Mär.","Apr.","Mai","Jun.","Jul.","Aug.","Sep.","Okt.","Nov.","Dez."],"wgRelevantPageName":"AVR-GCC-Tutorial/Der_UART","wgRestrictionEdit":[],"wgRestrictionMove":[],"wgWikiEditorEnabledModules":{"toolbar":true,"dialogs":true,"hidesig":true,"templateEditor":false,"templates":false,"preview":true,"previewDialog":false,"publish":true,"toc":false}});
}</SCRIPT>
<SCRIPT>if(window.mw){
mw.loader.implement("user.options",function(){mw.user.options.set({"ccmeonemails":0,"cols":80,"date":"default","diffonly":0,"disablemail":0,"disablesuggest":0,"editfont":"default","editondblclick":0,"editsection":1,"editsectiononrightclick":0,"enotifminoredits":0,"enotifrevealaddr":0,"enotifusertalkpages":1,"enotifwatchlistpages":0,"extendwatchlist":0,"externaldiff":0,"externaleditor":0,"fancysig":0,"forceeditsummary":0,"gender":"unknown","hideminor":0,"hidepatrolled":0,"imagesize":2,"justify":0,"math":0,"minordefault":0,"newpageshidepatrolled":0,"nocache":0,"noconvertlink":0,"norollbackdiff":0,"numberheadings":0,"previewonfirst":0,"previewontop":1,"quickbar":5,"rcdays":7,"rclimit":50,"rememberpassword":0,"rows":25,"searchlimit":20,"showhiddencats":0,"showjumplinks":1,"shownumberswatching":1,"showtoc":1,"showtoolbar":1,"skin":"mikrocontroller","stubthreshold":0,"thumbsize":2,"underline":2,"uselivepreview":0,"usenewrc":0,"watchcreations":0,"watchdefault":0,"watchdeletion":0,
"watchlistdays":3,"watchlisthideanons":0,"watchlisthidebots":0,"watchlisthideliu":0,"watchlisthideminor":0,"watchlisthideown":0,"watchlisthidepatrolled":0,"watchmoves":0,"wllimit":250,"usebetatoolbar":1,"usebetatoolbar-cgd":1,"wikieditor-preview":1,"wikieditor-publish":1,"variant":"de","language":"de","searchNs0":true,"searchNs1":false,"searchNs2":false,"searchNs3":false,"searchNs4":false,"searchNs5":false,"searchNs6":false,"searchNs7":false,"searchNs8":false,"searchNs9":false,"searchNs10":false,"searchNs11":false,"searchNs12":false,"searchNs13":false,"searchNs14":false,"searchNs15":false});;},{},{});mw.loader.implement("user.tokens",function(){mw.user.tokens.set({"editToken":"+\\","patrolToken":false,"watchToken":false});;},{},{});
/* cache key: uc_wiki:resourceloader:filter:minify-js:7:5afc608d284909c94225e82ae67c1108 */
}</SCRIPT>
<SCRIPT>if(window.mw){
mw.loader.load(["mediawiki.page.startup","mediawiki.legacy.wikibits","mediawiki.legacy.ajax"]);
}</SCRIPT>
<STYLE type=text/css>.source-c {
LINE-HEIGHT: normal
}
.source-c LI {
BORDER-BOTTOM: white 0px; BORDER-LEFT: white 0px; LINE-HEIGHT: normal; BORDER-TOP: white 0px; BORDER-RIGHT: white 0px
}
.source-c PRE {
BORDER-BOTTOM: white 0px; BORDER-LEFT: white 0px; LINE-HEIGHT: normal; BORDER-TOP: white 0px; BORDER-RIGHT: white 0px
}
.source-c.c .de1 {
PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; FONT: 1em/1.2em monospace, monospace; BACKGROUND: none transparent scroll repeat 0% 0%; VERTICAL-ALIGN: top; PADDING-TOP: 0px
}
.source-c.c .de2 {
PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 0px; PADDING-RIGHT: 0px; FONT: 1em/1.2em monospace, monospace; BACKGROUND: none transparent scroll repeat 0% 0%; VERTICAL-ALIGN: top; PADDING-TOP: 0px
}
.source-c.c {
FONT-FAMILY: monospace
}
.source-c.c .imp {
COLOR: red; FONT-WEIGHT: bold
}
.source-c.c LI {
VERTICAL-ALIGN: top; FONT-WEIGHT: normal
}
.source-c.c .li1 {
VERTICAL-ALIGN: top; FONT-WEIGHT: normal
}
.source-c.c .ln {
TEXT-ALIGN: right; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-LEFT: 2px; WIDTH: 1px; PADDING-RIGHT: 2px; VERTICAL-ALIGN: top; PADDING-TOP: 0px
}
.source-c.c .li2 {
VERTICAL-ALIGN: top; FONT-WEIGHT: bold
}
.source-c.c .kw1 {
COLOR: #b1b100
}
.source-c.c .kw2 {
COLOR: #000000; FONT-WEIGHT: bold
}
.source-c.c .kw3 {
COLOR: #000066
}
.source-c.c .kw4 {
COLOR: #993333
}
.source-c.c .co1 {
FONT-STYLE: italic; COLOR: #666666
}
.source-c.c .co2 {
COLOR: #339933
}
.source-c.c .coMULTI {
FONT-STYLE: italic; COLOR: #808080
}
.source-c.c .es0 {
COLOR: #000099; FONT-WEIGHT: bold
}
.source-c.c .es1 {
COLOR: #000099; FONT-WEIGHT: bold
}
.source-c.c .es2 {
COLOR: #660099; FONT-WEIGHT: bold
}
.source-c.c .es3 {
COLOR: #660099; FONT-WEIGHT: bold
}
.source-c.c .es4 {
COLOR: #660099; FONT-WEIGHT: bold
}
.source-c.c .es5 {
COLOR: #006699; FONT-WEIGHT: bold
}
.source-c.c .br0 {
COLOR: #009900
}
.source-c.c .sy0 {
COLOR: #339933
}
.source-c.c .st0 {
COLOR: #ff0000
}
.source-c.c .nu0 {
COLOR: #0000dd
}
.source-c.c .nu6 {
COLOR: #208080
}
.source-c.c .nu8 {
COLOR: #208080
}
.source-c.c .nu12 {
COLOR: #208080
}
.source-c.c .nu16 {
COLOR: #800080
}
.source-c.c .nu17 {
COLOR: #800080
}
.source-c.c .nu18 {
COLOR: #800080
}
.source-c.c .nu19 {
COLOR: #800080
}
.source-c.c .me1 {
COLOR: #202020
}
.source-c.c .me2 {
COLOR: #202020
}
.source-c.c .ln-xtra {
BACKGROUND-COLOR: #ffc
}
.source-c.c LI.ln-xtra {
BACKGROUND-COLOR: #ffc
}
.source-c.c DIV.ln-xtra {
BACKGROUND-COLOR: #ffc
}
.source-c.c SPAN.xtra {
DISPLAY: block
}
</STYLE>
<SCRIPT type=text/javascript
src="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/combined-top.js"></SCRIPT>
<!--<script src="/javascripts/highlightCurrentLink.js" type="text/javascript"></script>-->
<SCRIPT type=text/javascript
src="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/sorttable.js"></SCRIPT>
<LINK rel="shortcut icon" type=image/x-icon href="/favicon.ico"><LINK
rel=stylesheet type=text/css
href="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/screen.css"
media=screen><LINK rel=stylesheet type=text/css
href="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/shared.css"
media=screen><LINK rel=stylesheet type=text/css
href="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/main.css"
media=screen><LINK rel=stylesheet type=text/css
href="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/print.css"
media=print>
<STYLE type=text/css>#nav-foren-sub {
DISPLAY: none
}
</STYLE>
<STYLE type=text/css>#nav-tutorial-sub {
DISPLAY: none
}
</STYLE>
<LINK rel=stylesheet type=text/css
href="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/highslide.css"><!--[if lt IE 7]>
<link rel="stylesheet" type="text/css" href="/highslide/highslide-ie6.css" />
<![endif]--><!--
<style type="text/css">
<div id='catlinks' class='catlinks'><div id="mw-normal-catlinks" class="mw-normal-catlinks"><a href="/articles/Spezial:Kategorien" title="Spezial:Kategorien">Kategorien</a>: <ul><li><a href="/articles/Kategorie:Avr-gcc_Tutorial" title="Kategorie:Avr-gcc Tutorial">Avr-gcc Tutorial</a></li><li><a href="/articles/Kategorie:UART_und_RS232" title="Kategorie:UART und RS232">UART und RS232</a></li></ul></div></div> #nav-foren-sub {display: none;}
</style>
--><LINK
rel=stylesheet
href="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/load.css">
<META name=ResourceLoaderDynamicStyles content=""><LINK rel=stylesheet
href="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/load(1).css">
<STYLE>Alang(ar) {
TEXT-DECORATION: none
}
Alang(ckb) {
TEXT-DECORATION: none
}
Alang(fa) {
TEXT-DECORATION: none
}
Alang(kk-arab) {
TEXT-DECORATION: none
}
Alang(mzn) {
TEXT-DECORATION: none
}
Alang(ps) {
TEXT-DECORATION: none
}
Alang(ur) {
TEXT-DECORATION: none
}
</STYLE>
<SCRIPT type=text/javascript>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
(function() {
var gads = document.createElement('script');
gads.async = true;
gads.type = 'text/javascript';
var useSSL = 'https:' == document.location.protocol;
gads.src = (useSSL ? 'https:' : 'http:') +
'//www.googletagservices.com/tag/js/gpt.js';
var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(gads, node);
})();
googletag.cmd.push(function() {
//googletag.pubads().enableSingleRequest();
googletag.pubads().setTargeting('pagetype', 'article');
googletag.pubads().setTargeting('section', 'article');
if ('https:' == document.location.protocol) {
googletag.pubads().setTargeting('ssl', '1');
} else {
googletag.pubads().setTargeting('ssl', '0');
}
googletag.pubads().setTargeting('site_id', '1');
});
</SCRIPT>
<SCRIPT type=text/javascript>
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-80574-1']);
if (typeof googletag.pubads == 'function') {
_gaq.push(['_setCustomVar', 3, "GAM", "Yes", 1]);
} else {
_gaq.push(['_setCustomVar', 3, "GAM", "No", 1]);
}
_gaq.push(['_trackPageview']);
_gaq.push(['_trackPageLoadTime']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</SCRIPT>
</HEAD>
<BODY>
<DIV id=globalWrapper>
<DIV id=top>
<H1><A
href="http://www.mikrocontroller.net/">http://www.mikrocontroller.net/</A></H1></DIV>
<TABLE id=twocolumns>
<TBODY>
<TR>
<TD id=sidebar-left class=sidebar><!-- begin nav -->
<DIV class=nav-container>
<UL class=nav-first>
<LI><B><A href="http://www.mikrocontroller.net/">Home</A></B></LI>
<LI><B><A href="http://www.mikrocontroller.net/articles/AVR">AVR</A></B>
<UL>
<LI><A
href="http://www.mikrocontroller.net/articles/AVR-Tutorial">AVR-Tutorial</A></LI>
<LI><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial">AVR-GCC-Tutorial</A></LI></UL></LI>
<LI><B><A href="http://www.mikrocontroller.net/articles/ARM">ARM</A></B>
<UL>
<LI><A
href="http://www.mikrocontroller.net/articles/LPC1xxx">LPC1xxx</A></LI>
<LI><A
href="http://www.mikrocontroller.net/articles/LPC2000">LPC2000</A></LI>
<LI><A
href="http://www.mikrocontroller.net/articles/AT91SAM">AT91SAM7</A></LI>
<LI><A
href="http://www.mikrocontroller.net/articles/STM32">STM32</A></LI></UL></LI>
<LI><B><A
href="http://www.mikrocontroller.net/articles/MSP430">MSP430</A></B>
</LI>
<LI><B><A
href="http://www.mikrocontroller.net/articles/Programmierbare_Logik">FPGA,
CPLD &amp; Co.</A></B>
<UL>
<LI><A href="http://www.mikrocontroller.net/articles/FPGA">Grundlagen
zu FPGAs</A></LI>
<LI><A
href="http://www.mikrocontroller.net/articles/Hardwarebeschreibungssprachen">VHDL
&amp; Co.</A></LI>
<LI><A
href="http://www.mikrocontroller.net/articles/Xilinx_ISE">Xilinx
ISE</A></LI></UL></LI>
<LI><B><A
href="http://www.mikrocontroller.net/articles/Digitale_Signalverarbeitung">DSP</A></B>
</LI>
<LI><B><A
href="http://www.mikrocontroller.net/articles/Elektronik_Allgemein">Elektronik
allgemein</A></B>
<UL>
<LI><A
href="http://www.mikrocontroller.net/articles/SMD_L%C3%B6ten">SMD
Löten</A></LI>
<LI><A
href="http://www.mikrocontroller.net/articles/Operationsverst%C3%A4rker-Grundschaltungen">Operationsverstärker</A></LI>
<LI><A
href="http://www.mikrocontroller.net/articles/Oszilloskop">Oszilloskop</A></LI></UL></LI>
<LI><B><A href="http://www.mikrocontroller.net/forum/all">Forum</A></B>
<UL>
<LI><A
href="http://www.mikrocontroller.net/forum/mikrocontroller-elektronik">µC
&amp; Elektronik</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/analogtechnik">Analogtechnik</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/fpga-vhdl-cpld">FPGA, VHDL
&amp; Co.</A></LI>
<LI><A href="http://www.mikrocontroller.net/forum/dsp">DSP</A></LI>
<LI><A href="http://www.mikrocontroller.net/forum/gcc">GCC</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/codesammlung">Codesammlung</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/markt">Markt</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/platinen">Platinen</A></LI>
<LI><A href="http://www.mikrocontroller.net/forum/mechanik">Mechanik
&amp; Werkzeug</A></LI>
<LI><A href="http://www.mikrocontroller.net/forum/hf">HF, Funk &amp;
Felder</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/hausbus">Hausbus</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/pc-programmierung">PC-Programmierung</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/pc-hardware-software">PC
Hard- &amp; Software</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/ausbildung-studium-beruf">Ausbildung
&amp; Beruf</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/offtopic">Offtopic</A></LI>
<LI><A
href="http://www.mikrocontroller.net/forum/website">Webseite</A></LI></UL></LI>
<LI><B><A
href="http://www.mikrocontroller.net/buecher/">Buchtipps</A></B></LI>
<LI><B><A href="http://shop.mikrocontroller.net/">Shop</A></B></LI>
<LI><B><A
href="http://www.mikrocontroller.net/articles/Linksammlung">Linksammlung</A></B></LI>
<LI><B><A
href="http://www.mikrocontroller.net/articles/Hauptseite">Artikelübersicht</A></B></LI>
<LI><B><A
href="http://www.mikrocontroller.net/articles/Spezial:Recentchanges">Letzte
Änderungen</A></B></LI></UL></DIV><!-- end nav -->
<HR>
<!-- google_ad_section_start(weight=ignore) -->
<SCRIPT type=text/javascript>
<!--
function toggle_visibility(id) {
var e = document.getElementById(id);
if(e.style.display == 'block')
e.style.display = 'none';
else
e.style.display = 'block';
}
//-->
</SCRIPT>
<DIV id=p-cactions class=portlet>
<H5><A
onclick="javascript:toggle_visibility('p-cactions-box'); return false;"
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#toggle">
Dieser Artikel</A></H5>
<DIV id=p-cactions-box class=box>
<UL>
<LI id=ca-nstab-main class=selected><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART">Seite</A></LI>
<LI id=ca-talk><A
href="http://www.mikrocontroller.net/articles/Diskussion:AVR-GCC-Tutorial/Der_UART">Diskussion</A></LI>
<LI id=ca-edit><A
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit">Bearbeiten</A></LI>
<LI id=ca-history><A
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=history">Versionen/Autoren</A></LI></UL></DIV></DIV>
<DIV id=p-personal class=portlet>
<H5><A
onclick="javascript:toggle_visibility('p-personal-box'); return false;"
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#toggle">
Benutzer</A></H5>
<DIV id=p-personal-box class=box>
<UL>
<LI id=pt-anonuserpage><A class=new
href="http://www.mikrocontroller.net/articles/Benutzer:192.109.190.88">192.109.190.88</A></LI>
<LI id=pt-anontalk><A class=new
href="http://www.mikrocontroller.net/articles/Benutzer_Diskussion:192.109.190.88">Diskussionsseite
dieser IP</A></LI>
<LI id=pt-anonlogin><A
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=Spezial:Anmelden&amp;returnto=AVR-GCC-Tutorial%2FDer+UART">Anmelden</A></LI></UL></DIV></DIV><!-- LOGO
<div class="portlet" id="p-logo">
<a style="background-image: url(/wikisoftware/skins/common/images/wiki.png);"
href="/articles/Hauptseite"
title="Hauptseite"></a>
</div>
-->
<DIV id=p-search class=portlet>
<H5><A
onclick="javascript:toggle_visibility('p-search-box'); return false;"
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#toggle">
Suche</A></H5>
<DIV id=p-search-box class=box>
<FORM id=searchform name=searchform action=/articles/Spezial:Suche><INPUT
accessKey=f id=searchInputX type=text name=search><BR><INPUT class=searchButton value=Ausführen type=submit name=go>&nbsp;<INPUT class=searchButton value=Suche type=submit name=fulltext>
</FORM></DIV></DIV>
<DIV id=p-tb class=portlet>
<H5><A onclick="javascript:toggle_visibility('p-tb-box'); return false;"
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#toggle">
Werkzeuge</A></H5>
<DIV id=p-tb-box class=box>
<UL>
<LI id=t-whatlinkshere><A
href="http://www.mikrocontroller.net/articles/Spezial:Linkliste/AVR-GCC-Tutorial/Der_UART">Links
auf diese Seite</A></LI>
<LI id=t-recentchangeslinked><A
href="http://www.mikrocontroller.net/articles/Spezial:%C3%84nderungen_an_verlinkten_Seiten/AVR-GCC-Tutorial/Der_UART">Änderungen
an verlinkten Seiten</A></LI>
<LI id=t-specialpages><A
href="http://www.mikrocontroller.net/articles/Spezial:Spezialseiten">Spezialseiten</A></LI></UL></DIV></DIV><!-- google_ad_section_end --><!-- start adsense --><!-- end adsense --></TD><!-- end of the left (by default at least) column -->
<TD id=main><!-- google_ad_section_start --><A id=contentTop name=top></A>
<H1 class=firstHeading>AVR-GCC-Tutorial/Der UART</H1>
<DIV id=bodyContent><!-- tagline --><!-- <div id="siteSub">Aus Uc-wiki</div> --><!-- /tagline --><!-- subtitle -->
<DIV id=contentSub></DIV><!-- /subtitle --><!-- jumpto -->
<DIV id=jump-to-nav class=mw-jump>Wechseln zu: <A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#mw-navigation">Navigation</A>,
<A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#p-search">Suche</A>
</DIV><!-- /jumpto --><!-- bodycontent -->
<DIV dir=ltr id=mw-content-text lang=de class=mw-content-ltr>
<P>Über den <A title=UART
href="http://www.mikrocontroller.net/articles/UART">UART</A> kann ein <A
title=AVR href="http://www.mikrocontroller.net/articles/AVR">AVR</A>
leicht mit einer <A title=RS-232
href="http://www.mikrocontroller.net/articles/RS-232">RS-232</A>-Schnittstelle
eines PC oder sonstiger Geräte mit "<A title=Seriell
href="http://www.mikrocontroller.net/articles/Seriell">serieller</A>
Schnittstelle" verbunden werden. </P>
<TABLE id=toc class=toc>
<TBODY>
<TR>
<TD>
<DIV id=toctitle>
<H2>Inhaltsverzeichnis</H2></DIV>
<UL>
<LI class="toclevel-1 tocsection-1"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Allgemeines_zum_UART"><SPAN
class=tocnumber>1</SPAN> <SPAN class=toctext>Allgemeines zum
UART</SPAN></A></LI>
<LI class="toclevel-1 tocsection-2"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Die_Hardware"><SPAN
class=tocnumber>2</SPAN> <SPAN class=toctext>Die
Hardware</SPAN></A></LI>
<LI class="toclevel-1 tocsection-3"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Die_UART-Register"><SPAN
class=tocnumber>3</SPAN> <SPAN class=toctext>Die
UART-Register</SPAN></A></LI>
<LI class="toclevel-1 tocsection-4"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#UART_initialisieren"><SPAN
class=tocnumber>4</SPAN> <SPAN class=toctext>UART
initialisieren</SPAN></A></LI>
<LI class="toclevel-1 tocsection-5"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Senden_mit_dem_UART"><SPAN
class=tocnumber>5</SPAN> <SPAN class=toctext>Senden mit dem
UART</SPAN></A>
<UL>
<LI class="toclevel-2 tocsection-6"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Senden_einzelner_Zeichen"><SPAN
class=tocnumber>5.1</SPAN> <SPAN class=toctext>Senden einzelner
Zeichen</SPAN></A></LI>
<LI class="toclevel-2 tocsection-7"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Schreiben_einer_Zeichenkette_.28String.29"><SPAN
class=tocnumber>5.2</SPAN> <SPAN class=toctext>Schreiben einer
Zeichenkette (String)</SPAN></A></LI>
<LI class="toclevel-2 tocsection-8"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Schreiben_von_Variableninhalten"><SPAN
class=tocnumber>5.3</SPAN> <SPAN class=toctext>Schreiben von
Variableninhalten</SPAN></A></LI></UL></LI>
<LI class="toclevel-1 tocsection-9"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Empfangen"><SPAN
class=tocnumber>6</SPAN> <SPAN class=toctext>Empfangen</SPAN></A>
<UL>
<LI class="toclevel-2 tocsection-10"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Einzelne_Zeichen_empfangen"><SPAN
class=tocnumber>6.1</SPAN> <SPAN class=toctext>Einzelne Zeichen
empfangen</SPAN></A></LI>
<LI class="toclevel-2 tocsection-11"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Empfang_von_Zeichenketten_.28Strings.29"><SPAN
class=tocnumber>6.2</SPAN> <SPAN class=toctext>Empfang von
Zeichenketten (Strings)</SPAN></A></LI></UL></LI>
<LI class="toclevel-1 tocsection-12"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Interruptbetrieb"><SPAN
class=tocnumber>7</SPAN> <SPAN
class=toctext>Interruptbetrieb</SPAN></A>
<UL>
<LI class="toclevel-2 tocsection-13"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Empfangen_.28RX.29"><SPAN
class=tocnumber>7.1</SPAN> <SPAN class=toctext>Empfangen
(RX)</SPAN></A></LI>
<LI class="toclevel-2 tocsection-14"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#.28Baustelle.29"><SPAN
class=tocnumber>7.2</SPAN> <SPAN
class=toctext>(Baustelle)</SPAN></A></LI></UL></LI>
<LI class="toclevel-1 tocsection-15"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Software-UART"><SPAN
class=tocnumber>8</SPAN> <SPAN
class=toctext>Software-UART</SPAN></A></LI>
<LI class="toclevel-1 tocsection-16"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Handshaking"><SPAN
class=tocnumber>9</SPAN> <SPAN
class=toctext>Handshaking</SPAN></A>
<UL>
<LI class="toclevel-2 tocsection-17"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Hardwarehandshake_.28RTS.2FCTS.29"><SPAN
class=tocnumber>9.1</SPAN> <SPAN class=toctext>Hardwarehandshake
(RTS/CTS)</SPAN></A></LI>
<LI class="toclevel-2 tocsection-18"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Softwarehandshake_.28XON.2FXOFF.29"><SPAN
class=tocnumber>9.2</SPAN> <SPAN class=toctext>Softwarehandshake
(XON/XOFF)</SPAN></A></LI></UL></LI>
<LI class="toclevel-1 tocsection-19"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Galvanische_Trennung"><SPAN
class=tocnumber>10</SPAN> <SPAN class=toctext>Galvanische
Trennung</SPAN></A></LI>
<LI class="toclevel-1 tocsection-20"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Fehlersuche"><SPAN
class=tocnumber>11</SPAN> <SPAN
class=toctext>Fehlersuche</SPAN></A></LI>
<LI class="toclevel-1 tocsection-21"><A
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Der_UART#Links"><SPAN
class=tocnumber>12</SPAN> <SPAN
class=toctext>Links</SPAN></A></LI></UL></TD></TR></TBODY></TABLE>
<H2><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Allgemeines zum UART"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=1">Bearbeiten</A>]</SPAN>
<SPAN id=Allgemeines_zum_UART class=mw-headline>Allgemeines zum UART
</SPAN></H2>
<P>Mögliche Anwendungen des UART: </P>
<DL>
<DT>Debug-Schnittstelle</DT>
<DD>z.&nbsp;B. zur Anzeige von Zwischenergebnissen ("printf-debugging" -
hier besser "Logging" oder "UART-debugging") über <A title=RS-232
href="http://www.mikrocontroller.net/articles/RS-232">RS-232</A> auf
einem PC. Auf dem Rechner reicht dazu ein <A title=RS-232
href="http://www.mikrocontroller.net/articles/RS-232#Terminalprogramme">Terminalprogramm</A>
(MS-Windows: Hyperterm oder besser <A class="external autonumber"
href="https://sites.google.com/site/terminalbpp/" rel=nofollow>[1]</A>,
<A class="external text" href="http://www.der-hammer.info/terminal/"
rel=nofollow>HTerm</A>; Unix/Linux z.&nbsp;B. minicom). Ein direkter
Anschluss ist aufgrund unterschiedlicher Pegel nicht möglich, jedoch
sind entsprechende Schnittstellen-ICs wie z.&nbsp;B. ein MAX232 günstig
und leicht zu integrieren. Rechner ohne serielle Schnittstelle können
über fertige USB-seriell-Adapter angeschlossen werden. </DD>
<DT>Mensch-Maschine Schnittstelle</DT>
<DD>z.&nbsp;B. Konfiguration und Statusabfrage über eine "Kommandozeile"
oder Menüs (siehe z.&nbsp;B. Forumsbeitrag <A class="external text"
href="http://www.mikrocontroller.net/topic/52985">Auswertung
RS232-Befehle</A> und Artikel <A title=Tinykon
href="http://www.mikrocontroller.net/articles/Tinykon">Tinykon</A>)
</DD>
<DT>Übertragen von gespeicherten Werten</DT>
<DD>z.&nbsp;B. bei einem Datenlogger </DD>
<DT>Anschluss von Geräten</DT>
<DD>mit serieller Schnittstelle (z.&nbsp;B. (Funk-)Modems,
Mobiltelefone, Drucker, Sensoren, "intelligente" LC-Displays,
GPS-Empfänger). </DD>
<DT>"Feldbusse"</DT>
<DD>auf RS485/RS422-Basis mittels entsprechenden Bustreiberbausteinen
(z.&nbsp;B. MAX485) </DD>
<DT>DMX, Midi</DT>
<DD>etc. </DD>
<DT>LIN-Bus</DT>
<DD><B>L</B>ocal <B>I</B>nterconnect <B>N</B>etwork: Preiswerte
Sensoren/Aktoren in der Automobiltechnik und darüber hinaus </DD></DL>
<P>Einige AVR-Controller haben ein bis zwei vollduplexfähige UART
(<B>U</B>niversal <B>A</B>synchronous <B>R</B>eceiver and
<B>T</B>ransmitter) schon eingebaut ("Hardware-UART"). Übrigens:
Vollduplex heißt nichts anderes, als dass der Baustein gleichzeitig senden
und empfangen kann. </P>
<P>Neuere AVRs (ATmega, ATtiny) verfügen über einen bis vier
U<B>S</B>ART(s), dieser unterscheidet sich vom UART hauptsächlich durch
interne FIFO-Puffer für Ein- und Ausgabe und erweiterte
Konfigurationsmöglichkeiten. Die Puffergröße ist allerdings nur 1 Byte.
</P>
<H2><SPAN class=editsection>[<A title="Abschnitt bearbeiten: Die Hardware"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=2">Bearbeiten</A>]</SPAN>
<SPAN id=Die_Hardware class=mw-headline>Die Hardware </SPAN></H2>
<P>Der UART basiert auf normalem TTL-Pegel mit 0V (logisch 0) und 5V
(logisch 1). Die Schnittstellenspezifikation für RS-232 definiert jedoch
-3V ... -12V (logisch 1) und +3 ... +12V (logisch 0). Daher muss der
Signalaustausch zwischen AVR und Partnergerät invertiert werden. Für die
Anpassung der Pegel und das Invertieren der Signale gibt es fertige
Schnittstellenbausteine. Der bekannteste davon ist wohl der MAX232. </P>
<P>Streikt die Kommunikation per UART, so ist oft eine fehlerhafte
Einstellung der Baudrate die Ursache. Die Konfiguration auf eine bestimmte
Baudrate ist abhängig von der Taktfrequenz des Controllers. Gerade bei neu
aufgebauten Schaltungen (bzw. neu gekauften Controllern) sollte man sich
daher noch einmal vergewissern, dass der Controller auch tatsächlich mit
der vermuteten Taktrate arbeitet und nicht z.&nbsp;B. den bei einigen
Modellen werksseitig eingestellten internen <A title=Oszillator
href="http://www.mikrocontroller.net/articles/Oszillator">Oszillator</A>
statt eines externen Quarzes nutzt. Die Werte der verschiedenen fuse-bits
im Fehlerfall also beispielsweise mit <I><A title=AVRDUDE
href="http://www.mikrocontroller.net/articles/AVRDUDE">AVRDUDE</A></I>
kontrollieren und falls nötig anpassen. Grundsätzlich empfiehlt sich auch
immer ein Blick in die <A title="AVR Checkliste"
href="http://www.mikrocontroller.net/articles/AVR_Checkliste">AVR_Checkliste</A>.
</P>
<P>Controller mit nur einem Quarzanschluss (z.B Atmega328), die den Timer2
im Asynchron Modus benutzen, müssen intern mit dem RC-Oszillator getaktet
werden. Dieser sollte dann kalibriert werden: <A
title="AVR-GCC-Tutorial/Die Timer und Zähler des AVR"
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR#Kalibrieren_des_internen_Oszillators_mit_Timer2_als_Zeitbasis">Kalibrieren
des internen Oszillators mit Timer2 als Zeitbasis</A> </P>
<H2><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Die UART-Register"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=3">Bearbeiten</A>]</SPAN>
<SPAN id=Die_UART-Register class=mw-headline>Die UART-Register
</SPAN></H2>
<P>Der UART wird über vier separate Register angesprochen. Die USARTs der
ATMEGAs verfügen über mehrere zusätzliche Konfigurationsregister. Das
Datenblatt gibt darüber Auskunft. Die folgende Tabelle gibt nur die
Register für die UARTs der ATmega8/16/32 u.ä. wieder. </P>
<TABLE class=wikitable>
<TBODY>
<TR>
<TD><B>UCSRA&nbsp;&nbsp;&nbsp;</B> </TD>
<TD><B>U</B>ART <B>C</B>ontrol and <B>S</B>tatus <B>R</B>egister
<B>A</B>.<BR>
<P>Hier teilt uns der UART mit, was er gerade so macht. </P>
<TABLE style="TEXT-ALIGN: center" class=wikitable>
<TBODY>
<TR>
<TH>Bit </TH>
<TD>7 </TD>
<TD>6 </TD>
<TD>5 </TD>
<TD>4 </TD>
<TD>3 </TD>
<TD>2 </TD>
<TD>1 </TD>
<TD>0 </TD></TR>
<TR>
<TH>Name </TH>
<TD><B>RXC</B></TD>
<TD><B>TXC</B></TD>
<TD><B>UDRE</B></TD>
<TD><B>FE</B></TD>
<TD><B>DOR</B></TD>
<TD><B>PE</B></TD>
<TD><B>U2X</B></TD>
<TD><B>MPCM</B> </TD></TR>
<TR>
<TH>R/W </TH>
<TD>R</TD>
<TD>R/W</TD>
<TD>R</TD>
<TD>R</TD>
<TD>R</TD>
<TD>R</TD>
<TD>R/W</TD>
<TD>R/W </TD></TR>
<TR>
<TH>Initialwert </TH>
<TD>0</TD>
<TD>0</TD>
<TD>1</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0 </TD></TR></TBODY></TABLE>
<P><B>RXC</B> (UART Receive Complete) </P>
<DL>
<DD>Dieses Bit wird vom AVR gesetzt, wenn ein empfangenes Zeichen
vom Empfangs-Schieberegister in das Empfangs-Datenregister
transferiert wurde. </DD>
<DD>Das Zeichen muss nun schnellstmöglich aus dem Datenregister
ausgelesen werden. Falls dies nicht erfolgt, bevor ein weiteres
Zeichen komplett empfangen wurde, wird eine
Überlauf-Fehlersituation eintreten. Mit dem Auslesen des
Datenregisters wird das Bit automatisch gelöscht. </DD></DL>
<P><B>TXC</B> (UART Transmit Complete) </P>
<DL>
<DD>Dieses Bit wird vom AVR gesetzt, wenn das im
Sende-Schieberegister befindliche Zeichen vollständig ausgegeben
wurde und kein weiteres Zeichen im Sendedatenregister ansteht.
Dies bedeutet also, dass die Kommunikation vollumfänglich
abgeschlossen ist. </DD>
<DD>Dieses Bit ist wichtig bei Halbduplex-Verbindungen, wenn das
Programm nach dem Senden von Daten auf Empfang schalten muss. Im
Vollduplexbetrieb brauchen wir dieses Bit nicht zu beachten. </DD>
<DD>Das Bit wird nur dann automatisch gelöscht, wenn der
entsprechende Interrupthandler aufgerufen wird, ansonsten müssen
wir das Bit selber löschen. </DD>
<DD>Um das Bit zu löschen muss eine 1 an die entsprechende
Position geschrieben werden! </DD></DL>
<P><B>UDRE</B> (<B>U</B>ART <B>D</B>ata <B>R</B>egister
<B>E</B>mpty) </P>
<DL>
<DD>Dieses Bit zeigt an, ob der Sendepuffer bereit ist, um ein zu
sendendes Zeichen aufzunehmen. Das Bit wird vom AVR gesetzt (1),
wenn der Sendepuffer leer ist. Es wird gelöscht (0), wenn ein
Zeichen im Sendedatenregister vorhanden ist und noch nicht in das
Sende-Schieberegister übernommen wurde. Atmel empfiehlt aus
Kompatibilitätsgründen mit kommenden µC, UDRE auf 0 zu setzen,
wenn das UCSRA Register beschrieben wird. </DD>
<DD>Das Bit wird automatisch gelöscht, wenn ein Zeichen in das
Sendedatenregister geschrieben wird. </DD></DL>
<P><B>FE</B> (<B>F</B>raming <B>E</B>rror) </P>
<DL>
<DD>Dieses Bit wird vom AVR gesetzt, wenn der UART einen
Zeichenrahmenfehler detektiert, d.h. wenn das Stopbit eines
empfangenen Zeichens 0 ist. </DD>
<DD>Das Bit wird automatisch gelöscht, wenn das Stopbit des
empfangenen Zeichens 1 ist. </DD></DL>
<P><B>DOR</B> (<B>D</B>ata <B>O</B>ver <B>R</B>un) </P>
<DL>
<DD>Dieses Bit wird vom AVR gesetzt, wenn unser Programm das im
Empfangsdatenregister bereit liegende Zeichen nicht abholt bevor
das nachfolgende Zeichen komplett empfangen wurde. </DD>
<DD>Das nachfolgende Zeichen wird verworfen. </DD>
<DD>Das Bit wird automatisch gelöscht, wenn das empfangene Zeichen
in das Empfangsdatenregister transferiert werden konnte. </DD></DL>
<P><B>PE</B> (<B>P</B>arity <B>E</B>rror<B>)</B> </P>
<DL>
<DD>Dieses Bit wird vom AVR gesetzt, wenn das im
Empfangsdatenregister bereit liegende Zeichen einen Paritätsfehler
aufweist. </DD>
<DD>Das Bit wird automatisch gelöscht, wenn das empfangene Zeichen
in das Empfangsdatenregister transferiert werden konnte. </DD></DL>
<P><B>U2X</B> (Double the transmission speed) </P>
<DL>
<DD>Dieses Bit wird lediglich im asynchronen Modus genutzt. Im
synchronen Modus ist es 0 zu setzen. Wird das Bit gesetzt, so wird
der Baudraten Divisor von 16 auf 8 reduziert, was einer
Verdopplung der Transferrate gleich kommt. </DD></DL>
<P><B>MPCM</B> (<B>M</B>ulti <B>P</B>rozessor <B>C</B>ommunication
<B>M</B>ode) </P>
<DL>
<DD>Dieses Bit aktiviert die Multi-Prozessor-Kommunikation. Jeder
eintreffende Frame der keine Adressinformation enthält wird
dadurch ignoriert. </DD></DL></TD></TR>
<TR>
<TD><B>UCSRB &nbsp;&nbsp;&nbsp;</B> </TD>
<TD><B>U</B>ART <B>C</B>ontrol and <B>S</B>tatus <B>R</B>egister
<B>B</B>.<BR>
<P>In diesem Register stellen wir ein, wie wir den UART verwenden
möchten.<BR>Das Register ist wie folgt aufgebaut: </P>
<TABLE style="TEXT-ALIGN: center" class=wikitable>
<TBODY>
<TR>
<TH>Bit </TH>
<TD>7 </TD>
<TD>6 </TD>
<TD>5 </TD>
<TD>4 </TD>
<TD>3 </TD>
<TD>2 </TD>
<TD>1 </TD>
<TD>0 </TD></TR>
<TR>
<TH>Name </TH>
<TD><B>RXCIE</B></TD>
<TD><B>TXCIE</B></TD>
<TD><B>UDRIE</B></TD>
<TD><B>RXEN</B></TD>
<TD><B>TXEN</B></TD>
<TD><B>UCSZ2</B></TD>
<TD><B>RXB8</B></TD>
<TD><B>TXB8</B> </TD></TR>
<TR>
<TH>R/W </TH>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R</TD>
<TD>R/W </TD></TR>
<TR>
<TH>Initialwert </TH>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0 </TD></TR></TBODY></TABLE>
<P><B>RXCIE</B> (<B>RX</B> <B>C</B>omplete <B>I</B>nterrupt
<B>E</B>nable) </P>
<DL>
<DD>Wenn dieses Bit gesetzt ist, wird ein UART RX Complete
Interrupt ausgelöst, wenn ein Zeichen vom UART empfangen wurde.
Das Global Enable Interrupt Flag muss selbstverständlich auch
gesetzt sein. </DD></DL>
<P><B>TXCIE</B> (<B>TX</B> <B>C</B>omplete <B>I</B>nterrupt
<B>E</B>nable) </P>
<DL>
<DD>Wenn dieses Bit gesetzt ist, wird ein UART TX Complete
Interrupt ausgelöst, wenn ein Zeichen vom UART gesendet wurde. Das
Global Enable Interrupt Flag muss selbstverständlich auch gesetzt
sein. </DD></DL>
<P><B>UDRIE</B> (<B>U</B>ART <B>D</B>ata <B>R</B>egister
<B>E</B>mpty <B>I</B>nterrupt <B>E</B>nable) </P>
<DL>
<DD>Wenn dieses Bit gesetzt ist, wird ein UART Datenregister Leer
Interrupt ausgelöst, wenn der UART wieder bereit ist um ein neues
zu sendendes Zeichen zu übernehmen. Das Global Enable Interrupt
Flag muss selbstverständlich auch gesetzt sein. </DD></DL>
<P><B>RXEN</B> (<B>R</B>eceiver <B>E</B>nable) </P>
<DL>
<DD>Nur wenn dieses Bit gesetzt ist, arbeitet der Empfänger des
UART überhaupt. Wenn das Bit nicht gesetzt ist, kann der
entsprechende Pin des AVR als normaler I/O-Pin verwendet werden.
</DD></DL>
<P><B>TXEN</B> (<B>T</B>ransmitter <B>E</B>nable) </P>
<DL>
<DD>Nur wenn dieses Bit gesetzt ist, arbeitet der Sender des UART
überhaupt. Wenn das Bit nicht gesetzt ist, kann der entsprechende
Pin des AVR als normaler I/O-Pin verwendet werden. </DD></DL>
<P><B>UCSZ2</B> (Characters Size) </P>
<DL>
<DD>Dieses Bit setzt in Verbindung mit dem UCSZ1:0 Bits im UCSRC
Register die Anzahl von Datenbits eines Frames beim Empfang oder
Senden. </DD></DL>
<P><B>RXB8</B> (Receive Data Bit 8) </P>
<DL>
<DD>Wenn das vorher erwähnte CHR9-Bit gesetzt ist, dann enthält
dieses Bit das 9. Datenbit eines empfangenen Zeichens. </DD></DL>
<P><B>TXB8</B> (Transmit Data Bit 8) </P>
<DL>
<DD>Wenn das vorher erwähnte CHR9-Bit gesetzt ist, dann muss in
dieses Bit das 9. Bit des zu sendenden Zeichens eingeschrieben
werden bevor das eigentliche Datenbyte in das Datenregister
geschrieben wird. </DD></DL></TD></TR>
<TR>
<TD><B>UCSRC &nbsp;&nbsp;&nbsp;</B> </TD>
<TD><B>U</B>ART <B>C</B>ontrol and <B>S</B>tatus <B>R</B>egister
<B>C</B>.<BR>
<TABLE style="TEXT-ALIGN: center" class=wikitable>
<TBODY>
<TR>
<TH>Bit </TH>
<TD>7 </TD>
<TD>6 </TD>
<TD>5 </TD>
<TD>4 </TD>
<TD>3 </TD>
<TD>2 </TD>
<TD>1 </TD>
<TD>0 </TD></TR>
<TR>
<TH>Name </TH>
<TD><B>URSEL</B></TD>
<TD><B>UMSEL</B></TD>
<TD><B>UPM1</B></TD>
<TD><B>UPM0</B></TD>
<TD><B>USBS</B></TD>
<TD><B>UCSZ1</B></TD>
<TD><B>UCSZ0</B></TD>
<TD><B>UCPOL</B> </TD></TR>
<TR>
<TH>R/W </TH>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W</TD>
<TD>R/W </TD></TR>
<TR>
<TH>Initialwert </TH>
<TD>1</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>1</TD>
<TD>1</TD>
<TD>0 </TD></TR></TBODY></TABLE>
<P><B>URSEL</B> (Register Select) </P>
<DL>
<DD>Dieses Bit selektiert die Auswahl des UCSRC- bzw. des UBRRH
Registers. Beim Lesen von UCSRC wird es als 1 gelesen. Beim
Schreiben auf UCSRC muss es auf 1 gesetzt werden. </DD></DL>
<DL>
<DD>Achtung: Manche Prozessoren verfügen über dieses Bit, andere
wiederrum nicht. Was hat es damit auf sich?<BR>Um Zugriffsadressen
einzusparen, wurde von Atmel ein etwas seltsamer Weg gewählt. Das
UCSRC Register und das High-Byte des Baudratenregisters teilen
sich dieselbe Registeradresse! Um der Hardware mitzuteilen, welche
Bedeutung ein zugewiesener Wert haben soll, entweder neue Belegung
des Baudratenregisters oder eben Konfiguration des UCSRC
Registers, dient dieses Bit. Ist es nicht gesetzt, dann wird eine
Zuweisung immer als Zuweisung an das High-Byte des
Baudratenregisters angesehen, selbst wenn das so nicht
beabsichtigt war. Nur dann wenn dieses Bit gesetzt ist, dann wird
eine Zuweisung auch tatsächlich als eine Zuweisung an das UCSRC
Register gewertet und die Konfiguration verändert. Lässt man das
Bit irrtümlich weg, dann verursacht eine Zuweisung an UCSRC eine
Veränderung der Baudrateneinstellung! </DD></DL>
<P><B>UMSEL</B> (USART Mode Select) </P>
<DL>
<DD>Durch dieses Bit kann eine asynchrone oder synchrone
Übertragung eingestellt werden. Durch Setzen des Bits wird eine
synchrone Übertragung eingestellt. </DD></DL>
<P><B>UPM1:0</B> (Parity Mode) </P>
<TABLE style="TEXT-ALIGN: center" class=wikitable>
<TBODY>
<TR>
<TD><B>UPM1</B></TD>
<TD><B>UPM0</B></TD>
<TD><B>Parity Mode</B> </TD></TR>
<TR>
<TD>0</TD>
<TD>0</TD>
<TD>Disabled </TD></TR>
<TR>
<TD>0</TD>
<TD>1</TD>
<TD>Reserved </TD></TR>
<TR>
<TD>1</TD>
<TD>0</TD>
<TD>Enabled, Even Priority </TD></TR>
<TR>
<TD>1</TD>
<TD>1</TD>
<TD>Enabled, OddPriority </TD></TR></TBODY></TABLE>
<P><B>USBS</B> (<B>U</B>SART <B>S</B>top <B>B</B>it <B>S</B>elect)
</P>
<DL>
<DD>Diese Bits setzen die Anzahl der zu sendenden Stopbits eines
Frames. Beim Setzen werden 2 Stopbits übertragen, andernfalls nur
1 Stopbit. </DD></DL>
<TABLE style="TEXT-ALIGN: center" class=wikitable>
<TBODY>
<TR>
<TD><B>USBS</B></TD>
<TD><B>Anzahl der Stop Bits</B> </TD></TR>
<TR>
<TD>0</TD>
<TD>1 </TD></TR>
<TR>
<TD>1</TD>
<TD>2 </TD></TR></TBODY></TABLE>
<P><B>UCSZ1:0</B> (Character Size) </P>
<DL>
<DD>Diese Bits setzen in Verbindung mit UCSZ2 aus dem UCSRB
Register die Anzahl der Datenbits eines Frames. </DD>
<DD>Diese Bits setzen den entsprechenden Paritätsmodus. </DD></DL>
<TABLE style="TEXT-ALIGN: center" class=wikitable>
<TBODY>
<TR>
<TD><B>UCSZ2</B></TD>
<TD><B>UCSZ1</B></TD>
<TD><B>UCSZ0</B></TD>
<TD><B>Character Size</B> </TD></TR>
<TR>
<TD>0</TD>
<TD>0</TD>
<TD>0</TD>
<TD>5-Bit </TD></TR>
<TR>
<TD>0</TD>
<TD>0</TD>
<TD>1</TD>
<TD>6-Bit </TD></TR>
<TR>
<TD>0</TD>
<TD>1</TD>
<TD>0</TD>
<TD>7-Bit </TD></TR>
<TR>
<TD>0</TD>
<TD>1</TD>
<TD>1</TD>
<TD>8-Bit </TD></TR>
<TR>
<TD>1</TD>
<TD>0</TD>
<TD>0</TD>
<TD>Reserved </TD></TR>
<TR>
<TD>1</TD>
<TD>0</TD>
<TD>1</TD>
<TD>Reserved </TD></TR>
<TR>
<TD>1</TD>
<TD>1</TD>
<TD>0</TD>
<TD>Reserved </TD></TR>
<TR>
<TD>1</TD>
<TD>1</TD>
<TD>1</TD>
<TD>9-Bit </TD></TR></TBODY></TABLE>
<P><B>UCPOL</B> (Clock Polarity) </P>
<P><BR></P></TD></TR>
<TR>
<TD><B>UDR</B> </TD>
<TD><B>U</B>ART <B>D</B>ata <B>R</B>egister.<BR>
<P>Hier werden Daten zwischen UART und CPU übertragen. Da der UART
im Vollduplexbetrieb gleichzeitig empfangen und senden kann, handelt
es sich hier physikalisch um 2 Register, die aber über die gleiche
I/O-Adresse angesprochen werden. Je nachdem, ob ein Lese- oder ein
Schreibzugriff auf den UART erfolgt wird automatisch das richtige
UDR angesprochen. </P></TD></TR>
<TR>
<TD><B>UBRR</B> </TD>
<TD><B>U</B>ART <B>B</B>aud <B>R</B>ate <B>R</B>egister.<BR>
<P>In diesem Register müssen wir dem UART mitteilen, wie schnell wir
gerne kommunizieren möchten. Der Wert, der in dieses Register
geschrieben werden muss, errechnet sich nach folgender Formel (wenn
U2X Bit 0 gesetzt ist): </P>
<P><BR></P>
<DL>
<DD><IMG class=tex
alt="&#10;\mathrm{UBRR} = \frac{\mathrm{Taktfrequenz}}{\mathrm{Baudrate} \cdot 16} - 1&#10;"
src="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/1c9afe865faedff3411f0d0e74fc2261.png">
</DD></DL>
<P>Es sind Baudraten bis über 115200 Baud möglich, je nach
Controller und CPU-Frequenz. Siehe Datenblatt.
</P></TD></TR></TBODY></TABLE>
<H2><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: UART initialisieren"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=4">Bearbeiten</A>]</SPAN>
<SPAN id=UART_initialisieren class=mw-headline>UART initialisieren
</SPAN></H2>
<P>Wir wollen nun Daten mit dem UART auf die serielle Schnittstelle
ausgeben. Dazu müssen wir den UART zuerst mal initialisieren. Dazu setzen
wir je nach gewünschter Funktionsweise die benötigten Bits im <B>U</B>ART
<B>C</B>ontrol <B>R</B>egister. </P>
<P>Da wir vorerst nur senden möchten und noch keine Interrupts auswerten
wollen, gestaltet sich die Initialisierung wirklich sehr einfach, da wir
lediglich das <B>Transmitter Enable</B> Bit setzen müssen: </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1> UCSRB <SPAN class=sy0>|=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>TXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN></PRE></DIV></DIV>
<P>Neuere AVRs mit USART haben mehrere Konfigurationsregister und
erfordern eine etwas andere Konfiguration. Für einen ATmega16 z.&nbsp;B.:
</P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1> UCSRB <SPAN class=sy0>|=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>TXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// UART TX einschalten</SPAN>
UCSRC <SPAN class=sy0>=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>URSEL<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN> <SPAN class=sy0>&lt;&lt;</SPAN> UCSZ1<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN> <SPAN class=sy0>&lt;&lt;</SPAN> UCSZ0<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// Asynchron 8N1</SPAN></PRE></DIV></DIV>
<P>Nun ist noch das Baudratenregister <B>UBRR</B> der verwendeten UARTs
einzustellen, bzw. bei neueren AVRs die beiden Register <B>UBRRL</B> und
<B>UBRRH</B>. . Die Berechnung wird während des Compilerlaufs ausgeführt,
beansprucht also in der gezeigten Form weder Speicher noch Rechenzeit des
Controllers. Das Ergebniss wird jedoch als ganzzahliger Wert eingesetzt,
d.h. Nachkommastellen werden einfach abgeschnitten und es erfolgt keine
Rundung. Aus diesem Grund kann man sich eines kleinen Tricks bedienen,
indem vor der eigentlichen Division bei der Zuweisung die Hälfte des
Wertes dazu addiert wird. Allgemein formuliert bedeutet das: <CODE>int i =
( a + b/2 ) / b;</CODE>. Dies wird in der unten angegebenen Berechnung von
UBRR_VAL ausgenutzt um den Fehler zu minimieren. (Eine ausführliche
Erklärung zum <I>cleveren Runden</I> findet sich in einer <A
class="external text"
href="http://www.mikrocontroller.net/topic/170617#1631916">Forumsdiskussion</A>.)
</P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=coMULTI>/*
UART-Init:
Berechnung des Wertes für das Baudratenregister
aus Taktrate und gewünschter Baudrate
*/</SPAN>
&nbsp;
<SPAN class=co2>#ifndef F_CPU</SPAN>
<SPAN class=coMULTI>/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
F_CPU im Makefile definiert werden, eine nochmalige Definition
hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
#ifndef/#endif
&nbsp;
Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
verwendet wird und dort eine andere, nicht zur Hardware passende
Taktrate eingestellt ist: Dann wird die folgende Definition
nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
noch nicht definiert: */</SPAN>
<SPAN class=co2>#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"</SPAN>
<SPAN class=co2>#define F_CPU 4000000UL // Systemtakt in Hz - Definition als unsigned long beachten </SPAN>
<SPAN class=co1>// Ohne ergeben sich unten Fehler in der Berechnung</SPAN>
<SPAN class=co2>#endif</SPAN>
&nbsp;
<SPAN class=co2>#define BAUD 9600UL // Baudrate</SPAN>
&nbsp;
<SPAN class=co1>// Berechnungen</SPAN>
<SPAN class=co2>#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden</SPAN>
<SPAN class=co2>#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate</SPAN>
<SPAN class=co2>#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.</SPAN>
&nbsp;
<SPAN class=co2>#if ((BAUD_ERROR&lt;990) || (BAUD_ERROR&gt;1010))</SPAN>
<SPAN class=co2>#error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! </SPAN>
<SPAN class=co2>#endif</SPAN></PRE></DIV></DIV>
<P>Die Makros sind sehr praktisch, da damit sowohl automatisch der Wert
für UBRR, als auch die Abweichung in der generierten (möglichen) von der
gewünschten Baudrate berechnet wird. Im Falle einer zu hohen Abweichung
(+/-1%) wird eine Fehlermeldung ausgegeben und der Compilerablauf
abgebrochen. Damit können viele Probleme mit "UART sendet komische
Zeichen" vermieden werden. Ausserdem kann man mühelos die Einstellung an
eine neue Taktfrequenz bzw. Baudrate anpassen, ohne selber rechnen oder in
Tabellen nachschlagen zu müssen. </P>
<P>Die eigentliche Initialisierung der UART Register kann im Hauptprogramm
main() vorgenommen werden. Öfters wird jedoch eine Funktion z.&nbsp;B.
uart_init() dafür geschrieben, die in der eigenen Codesammlung in mehreren
Projekten verwendet werden kann. </P>
<P>Für einige AVR (z.&nbsp;B. ATmega169, ATmega48/88/168, AT90CAN jedoch
nicht für z.&nbsp;B. ATmega16/32, ATmega128, ATtiny2313) wird durch die
Registerdefinitionen der avr-libc (io*.h) auch für Controller mit zwei
UBRR-Registern (UBRRL/UBRRH) ein UBRR bzw. UBRR0 als "16-bit-Register"
definiert und man kann den Wert direkt per UBRR = UBRR_VAL zuweisen.
Intern werden dann zwei Zuweisungen für UBRRH und UBRRL generiert. </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=coMULTI>/* UART-Init Bsp. ATmega48 */</SPAN>
&nbsp;
<SPAN class=kw4>void</SPAN> uart_init<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
UBRR0 <SPAN class=sy0>=</SPAN> UBRR_VAL<SPAN class=sy0>;</SPAN>
UCSR0B <SPAN class=sy0>|=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>TXEN0<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=co1>// Frame Format: Asynchron 8N1</SPAN>
UCSR0C <SPAN class=sy0>=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UCSZ01<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UCSZ00<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Die einzelne Anweisung ist nicht bei allen Controllern möglich, da die
beiden Register nicht bei allen aufeinanderfolgende Addressen aufweisen.
Die getrennte Zuweisung an UBRRH und UBRRL wie im nächsten Beispiel
gezeigt, ist universeller und portabler und daher vorzuziehen. Wichtig
ist, dass UBRRH <B>vor</B> UBRRL geschrieben wird: </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=coMULTI>/* UART-Init Bsp. ATmega16 */</SPAN>
&nbsp;
<SPAN class=kw4>void</SPAN> uart_init<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
UBRRH <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&gt;&gt;</SPAN> <SPAN class=nu0>8</SPAN><SPAN class=sy0>;</SPAN>
UBRRL <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&amp;</SPAN> <SPAN class=nu12>0xFF</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
UCSRB <SPAN class=sy0>|=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>TXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// UART TX einschalten</SPAN>
UCSRC <SPAN class=sy0>=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>URSEL<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UCSZ1<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UCSZ0<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// Asynchron 8N1 </SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Inzwischen gibt es in der avr-libc Makros für obige Berechnung der UBRR
Registerwerte aus Taktrate F_CPU und Baudrate BAUD. Dazu wird die
Includedatei <A class="external text"
href="http://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html"
rel=nofollow>&lt;util/setbaud.h&gt;</A> eingebunden, nachdem F_CPU und die
gewünschte Baudrate definiert wurden. Einige Beispiele zur Anwendung
finden sich in der Dokumentation der avr-libc. Im Quellcode kann dann
analog zur oben gezeigten Vorgehensweise einfach das Makro UBRR_VALUE
(bzw. UBRRH_VALUE und UBRRL_VALUE) an der entsprechenden Stelle eingesetzt
werden. Es wird auch automatisch ermittelt, ob der U2X-Modus (vgl.
Datenblatt) zu geringeren Abweichungen führt und dann dem Makro USE_U2X
ein Wert ungleich null zugewiesen. Ein Beispiel (angelehnt an die
avr-libc-Dokumentation): </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#include &lt;avr/io.h&gt; </SPAN>
<SPAN class=co2>#define F_CPU 1000000 /* evtl. bereits via Compilerparameter definiert */</SPAN>
<SPAN class=co2>#define BAUD 9600</SPAN>
<SPAN class=co2>#include &lt;util/setbaud.h&gt;</SPAN>
&nbsp;
<SPAN class=kw4>void</SPAN> uart_init<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
UBRRH <SPAN class=sy0>=</SPAN> UBRRH_VALUE<SPAN class=sy0>;</SPAN>
UBRRL <SPAN class=sy0>=</SPAN> UBRRL_VALUE<SPAN class=sy0>;</SPAN>
<SPAN class=coMULTI>/* evtl. verkuerzt falls Register aufeinanderfolgen (vgl. Datenblatt)
UBRR = UBRR_VALUE;
*/</SPAN>
<SPAN class=co2>#if USE_2X</SPAN>
<SPAN class=coMULTI>/* U2X-Modus erforderlich */</SPAN>
UCSRA <SPAN class=sy0>|=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN> <SPAN class=sy0>&lt;&lt;</SPAN> U2X<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=co2>#else</SPAN>
<SPAN class=coMULTI>/* U2X-Modus nicht erforderlich */</SPAN>
UCSRA <SPAN class=sy0>&amp;=</SPAN> ~<SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN> <SPAN class=sy0>&lt;&lt;</SPAN> U2X<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=co2>#endif</SPAN>
&nbsp;
<SPAN class=co1>// hier weitere Initialisierungen (TX und/oder RX aktivieren, Modus setzen </SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Siehe auch: </P>
<UL>
<LI><A class="external text"
href="http://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html"
rel=nofollow>Dokumentation der avr-libc zu &lt;util/setbaud.h&gt;</A>
</LI>
<LI><A class="external text"
href="http://www.wormfood.net/avrbaudcalc.php" rel=nofollow>WormFood's
AVR Baud Rate Calculator</A> online. </LI>
<LI><A class="external text"
href="http://www.gjlay.de/helferlein/avr-uart-rechner.html"
rel=nofollow>AVR Baudraten-Rechner</A> in JavaScript </LI></UL>
<H2><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Senden mit dem UART"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=5">Bearbeiten</A>]</SPAN>
<SPAN id=Senden_mit_dem_UART class=mw-headline>Senden mit dem UART
</SPAN></H2>
<H3><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Senden einzelner Zeichen"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=6">Bearbeiten</A>]</SPAN>
<SPAN id=Senden_einzelner_Zeichen class=mw-headline>Senden einzelner
Zeichen </SPAN></H3>
<P>Um nun ein Zeichen auf die Schnittstelle auszugeben, müssen wir
dasselbe lediglich in das <B>U</B>ART <B>D</B>ata <B>R</B>egister
schreiben. Vorher ist zu prüfen, ob das UART-Modul bereit ist, das zu
sendende Zeichen entgegenzunehmen. Die Bezeichnungen des/der
Statusregisters mit dem Bit UDRE ist abhängig vom Controllertypen (vgl.
Datenblatt). </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co1>// bei neueren AVRs steht der Status in UCSRA/UCSR0A/UCSR1A, hier z.B. fuer ATmega16:</SPAN>
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=sy0>!</SPAN><SPAN class=br0>(</SPAN>UCSRA <SPAN class=sy0>&amp;</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UDRE<SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN> <SPAN class=coMULTI>/* warten bis Senden moeglich */</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
UDR <SPAN class=sy0>=</SPAN> <SPAN class=st0>'x'</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=coMULTI>/* schreibt das Zeichen x auf die Schnittstelle */</SPAN></PRE></DIV></DIV>
<H3><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Schreiben einer Zeichenkette (String)"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=7">Bearbeiten</A>]</SPAN>
<SPAN id=Schreiben_einer_Zeichenkette_.28String.29
class=mw-headline>Schreiben einer Zeichenkette (String) </SPAN></H3>
<P>Die Aufgabe "String senden" wird durch zwei Funktionen abgearbeitet.
Die universelle/controllerunabhängige Funktion uart_puts übergibt jeweils
ein Zeichen der Zeichenkette an eine Funktion uart_putc, die abhängig von
der vorhandenen Hardware implementiert werden muss. In der Funktion zum
Senden eines Zeichens ist darauf zu achten, dass vor dem Senden geprüft
wird, ob der UART bereit ist den "Sendeauftrag" entgegenzunehmen. </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=coMULTI>/* ATmega16 */</SPAN>
<SPAN class=kw4>int</SPAN> uart_putc<SPAN class=br0>(</SPAN><SPAN class=kw4>unsigned</SPAN> <SPAN class=kw4>char</SPAN> c<SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=sy0>!</SPAN><SPAN class=br0>(</SPAN>UCSRA <SPAN class=sy0>&amp;</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UDRE<SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN> <SPAN class=coMULTI>/* warten bis Senden moeglich */</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
UDR <SPAN class=sy0>=</SPAN> c<SPAN class=sy0>;</SPAN> <SPAN class=coMULTI>/* sende Zeichen */</SPAN>
<SPAN class=kw1>return</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
&nbsp;
<SPAN class=coMULTI>/* puts ist unabhaengig vom Controllertyp */</SPAN>
<SPAN class=kw4>void</SPAN> uart_puts <SPAN class=br0>(</SPAN><SPAN class=kw4>char</SPAN> <SPAN class=sy0>*</SPAN>s<SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=sy0>*</SPAN>s<SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN> <SPAN class=coMULTI>/* so lange *s&nbsp;!= '\0' also ungleich dem "String-Endezeichen(Terminator)" */</SPAN>
uart_putc<SPAN class=br0>(</SPAN><SPAN class=sy0>*</SPAN>s<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
s<SPAN class=sy0>++;</SPAN>
<SPAN class=br0>}</SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Die in uart_putc verwendeten Schleifen, in denen gewartet wird bis die
UART-Hardware zum senden bereit ist, sind insofern etwas kritisch, da
während des Sendens eines Strings nicht mehr auf andere Ereignisse
reagiert werden kann. Universeller ist die Nutzung von FIFO(first-in
first-out)-Puffern, in denen die zu sendenden bzw. empfangenen
Zeichen/Bytes zwischengespeichert und in Interruptroutinen an die
U(S)ART-Hardware weitergegeben bzw. von ihr ausgelesen werden. Dazu
existieren fertige Komponenten (Bibliotheken, Libraries), die man recht
einfach in eigene Entwicklungen integrieren kann. Es empfiehlt sich, diese
Komponenten zu nutzen und das Rad nicht neu zu erfinden. </P>
<H3><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Schreiben von Variableninhalten"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=8">Bearbeiten</A>]</SPAN>
<SPAN id=Schreiben_von_Variableninhalten class=mw-headline>Schreiben von
Variableninhalten </SPAN></H3>
<P>Sollen Inhalte von Variablen (Ganzzahlen, Gleitkomma) in
"menschenlesbarer" Form gesendet werden, ist vor dem Transfer eine
Umwandlung in Zeichen ("ASCII") erforderlich. Bei nur einer Ziffer ist
diese Umwandlung relativ einfach: man addiert den ASCII-Wert von Null zur
Ziffer und kann diesen Wert direkt senden. </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#include &lt;avr/io.h&gt;</SPAN>
<SPAN class=co2>#include &lt;stdlib.h&gt;</SPAN>
<SPAN class=co1>//...</SPAN>
&nbsp;
<SPAN class=co1>// hier uart_putc (s.o.)</SPAN>
&nbsp;
<SPAN class=kw4>int</SPAN> main <SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=co1>// Ausgabe von 0123456789</SPAN>
<SPAN class=kw4>char</SPAN> c<SPAN class=sy0>;</SPAN>
&nbsp;
uart_init<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
<SPAN class=kw1>for</SPAN> <SPAN class=br0>(</SPAN><SPAN class=kw4>uint8_t</SPAN> i<SPAN class=sy0>=</SPAN><SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN> i<SPAN class=sy0>&lt;=</SPAN><SPAN class=nu0>9</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=sy0>++</SPAN>i<SPAN class=br0>)</SPAN> <SPAN class=br0>{</SPAN>
c <SPAN class=sy0>=</SPAN> i <SPAN class=sy0>+</SPAN> <SPAN class=st0>'0'</SPAN><SPAN class=sy0>;</SPAN>
uart_putc<SPAN class=br0>(</SPAN> c <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=co1>// verkuerzt: uart_putc( i + '0' );</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=br0>)</SPAN> <SPAN class=br0>{</SPAN>
<SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
<SPAN class=kw1>return</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// never reached </SPAN>
&nbsp;
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Soll mehr als eine Ziffer ausgegeben werden, bedient man sich
zweckmäßigerweise vorhandener Funktionen zur Umwandlung von Zahlen in
Zeichenketten/Strings. Die Funktion der avr-libc zur Umwandlung von
vorzeichenbehafteten 16bit-Ganzzahlen (int16_t) in Zeichenketten heißt
<I>itoa</I> (Integer to ASCII). Man muss der Funktion einen
Speicherbereich zur Verarbeitung (buffer) mit Platz für alle Ziffern, das
String-Endezeichen ('\0') und evtl. das Vorzeichen bereitstellen. </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#include &lt;avr/io.h&gt;</SPAN>
<SPAN class=co2>#include &lt;stdlib.h&gt;</SPAN>
&nbsp;
<SPAN class=co1>//...</SPAN>
&nbsp;
<SPAN class=co1>// hier uart_init, uart_putc, uart_puts (s.o.)</SPAN>
&nbsp;
<SPAN class=kw4>int</SPAN> main<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw4>char</SPAN> s<SPAN class=br0>[</SPAN><SPAN class=nu0>7</SPAN><SPAN class=br0>]</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=kw4>int16_t</SPAN> i <SPAN class=sy0>=</SPAN> <SPAN class=sy0>-</SPAN><SPAN class=nu0>12345</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
uart_init<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
<SPAN class=kw3>itoa</SPAN><SPAN class=br0>(</SPAN> i<SPAN class=sy0>,</SPAN> s<SPAN class=sy0>,</SPAN> <SPAN class=nu0>10</SPAN> <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// 10 fuer radix -&gt; Dezimalsystem</SPAN>
uart_puts<SPAN class=br0>(</SPAN> s <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
<SPAN class=co1>// da itoa einen Zeiger auf den Beginn von s zurueckgibt verkuerzt auch:</SPAN>
uart_puts<SPAN class=br0>(</SPAN> <SPAN class=kw3>itoa</SPAN><SPAN class=br0>(</SPAN> i<SPAN class=sy0>,</SPAN> s<SPAN class=sy0>,</SPAN> <SPAN class=nu0>10</SPAN> <SPAN class=br0>)</SPAN> <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=br0>)</SPAN> <SPAN class=br0>{</SPAN>
<SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
<SPAN class=kw1>return</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// never reached </SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Für vorzeichenlose 16bit-Ganzzahlen (uint16_t) exisitert <I>utoa</I>.
Die Funktionen für 32bit-Ganzzahlen (int32_t und uint32_t) heißen
<I>ltoa</I> bzw. <I>ultoa</I>. Da 32bit-Ganzzahlen mehr Stellen aufweisen
können, ist ein entsprechend größerer Pufferspeicher vorzusehen. </P>
<P>Auch Gleitkommazahlen (float/double) können mit bereits vorhandenen
Funktionen in Zeichenfolgen umgewandelt werden, dazu existieren die
Funktionen <I>dtostre</I> und <I>dtostrf</I>. dtostre nutzt
Exponentialschreibweise ("engineering"-Format). (Hinweis: z.Zt. existiert
im avr-gcc kein "echtes" double, intern wird immer mit "einfacher
Genauigkeit", entsprechend float, gerechnet.) </P>
<P>dtostrf und dtostre benötigen die libm.a der avr-libc. Bei Nutzung von
Makefiles ist der Parameter -lm in in LDFLAGS anzugeben (Standard in den
WinAVR/mfile-Makefilevorlagen). Nutzt man AVRStudio als IDE für den
GNU-Compiler (gcc-Plugin) ist die libm.a unter Libaries auszuwählen:
Project -&gt; Configurations Options -&gt; Libaries -&gt; libm.a mit dem
Pfeil nach rechts einbinden. Siehe auch die <A title=FAQ
href="http://www.mikrocontroller.net/articles/FAQ#Aktivieren_der_Floating_Point_Version_von_sprintf_beim_WinAVR_mit_AVR-Studio">FAQ</A>
</P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#include &lt;avr/io.h&gt;</SPAN>
<SPAN class=co2>#include &lt;stdlib.h&gt;</SPAN>
&nbsp;
<SPAN class=co1>//...</SPAN>
&nbsp;
<SPAN class=co1>// hier uart_init, uart_putc, uart_puts (s.o.)</SPAN>
&nbsp;
<SPAN class=coMULTI>/* lt. avr-libc Dokumentation:
char* dtostrf(
double __val,
char __width,
char __prec,
char * __s
)
*/</SPAN>
&nbsp;
<SPAN class=kw4>int</SPAN> main<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=co1>// Pufferspeicher ausreichend groß</SPAN>
<SPAN class=co1>// evtl. Vorzeichen + width + Endezeichen:</SPAN>
<SPAN class=kw4>char</SPAN> s<SPAN class=br0>[</SPAN><SPAN class=nu0>8</SPAN><SPAN class=br0>]</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=kw4>float</SPAN> f <SPAN class=sy0>=</SPAN> <SPAN class=sy0>-</SPAN><SPAN class=nu16>12.345</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
uart_init<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
dtostrf<SPAN class=br0>(</SPAN> f<SPAN class=sy0>,</SPAN> <SPAN class=nu0>6</SPAN><SPAN class=sy0>,</SPAN> <SPAN class=nu0>3</SPAN><SPAN class=sy0>,</SPAN> s <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
uart_puts<SPAN class=br0>(</SPAN> s <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=co1>// verkürzt: uart_puts( dtostrf( f, 7, 3, s ) );</SPAN>
&nbsp;
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=br0>)</SPAN> <SPAN class=br0>{</SPAN>
<SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
<SPAN class=kw1>return</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// never reached </SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<H2><SPAN class=editsection>[<A title="Abschnitt bearbeiten: Empfangen"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=9">Bearbeiten</A>]</SPAN>
<SPAN id=Empfangen class=mw-headline>Empfangen </SPAN></H2>
<H3><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Einzelne Zeichen empfangen"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=10">Bearbeiten</A>]</SPAN>
<SPAN id=Einzelne_Zeichen_empfangen class=mw-headline>Einzelne Zeichen
empfangen </SPAN></H3>
<P>Zum Empfang von Zeichen muss der Empfangsteil des UART bei der
Initialisierung aktiviert werden, indem das RXEN-Bit im jeweiligen
Konfigurationsregister (UCSRB bzw UCSR0B/UCSR1B) gesetzt wird. Im
einfachsten Fall wird solange gewartet, bis ein Zeichen empfangen wurde,
dieses steht dann im UART-Datenregister (UDR bzw. UDR0 und UDR1 bei AVRs
mit 2 UARTS) zur Verfügung (sogen. "Polling-Betrieb"). Ein Beispiel für
den ATmega16: </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#include &lt;inttypes.h&gt;</SPAN>
<SPAN class=co2>#include &lt;avr/io.h&gt;</SPAN>
&nbsp;
<SPAN class=coMULTI>/* Siehe auch obere Baudrateneinstellung */</SPAN>
<SPAN class=coMULTI>/* USART-Init beim ATmega16 */</SPAN>
&nbsp;
<SPAN class=kw4>void</SPAN> uart_init<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
UBRRH <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&gt;&gt;</SPAN> <SPAN class=nu0>8</SPAN><SPAN class=sy0>;</SPAN>
UBRRL <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&amp;</SPAN> <SPAN class=nu12>0xFF</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
UCSRC <SPAN class=sy0>=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>URSEL<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UCSZ1<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UCSZ0<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// Asynchron 8N1 </SPAN>
UCSRB <SPAN class=sy0>|=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>RXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// UART RX einschalten</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
<SPAN class=coMULTI>/* Zeichen empfangen */</SPAN>
<SPAN class=kw4>uint8_t</SPAN> uart_getc<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=sy0>!</SPAN><SPAN class=br0>(</SPAN>UCSRA <SPAN class=sy0>&amp;</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>RXC<SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN> <SPAN class=co1>// warten bis Zeichen verfuegbar</SPAN>
<SPAN class=sy0>;</SPAN>
<SPAN class=kw1>return</SPAN> UDR<SPAN class=sy0>;</SPAN> <SPAN class=co1>// Zeichen aus UDR an Aufrufer zurueckgeben</SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Und die Anwendung in einem Beispiel: </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#include &lt;avr/io.h&gt;</SPAN>
<SPAN class=co2>#include &lt;stdlib.h&gt;</SPAN>
&nbsp;
<SPAN class=co1>// hier Makro für die Baudratenberechnung </SPAN>
&nbsp;
<SPAN class=co1>// hier uart_init, uart_getc (s.o.)</SPAN>
&nbsp;
<SPAN class=kw4>int</SPAN> main<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
uart_init<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw4>uint8_t</SPAN> c<SPAN class=sy0>;</SPAN>
c <SPAN class=sy0>=</SPAN> uart_getc<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
<SPAN class=co1>// hier etwas mit c machen z.B. auf PORT ausgeben</SPAN>
DDRC <SPAN class=sy0>=</SPAN> <SPAN class=nu12>0xFF</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// PORTC Ausgang</SPAN>
PORTC <SPAN class=sy0>=</SPAN> c<SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN>
<SPAN class=kw1>return</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// never reached </SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Die Funktion uart_getc() blockiert allerdings den Programmablauf, denn
es wird gewartet, bis ein Zeichen empfangen wird! Möchte man das Warten
vermeiden, kann das RXC-Bit in einer Programmschleife abgefragt werden und
dann nur bei gesetztem RXC-Bit UDR ausgelesen werden. </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#include &lt;avr/io.h&gt;</SPAN>
<SPAN class=co2>#include &lt;stdlib.h&gt;</SPAN>
&nbsp;
<SPAN class=co1>// hier Makro für die Baudratenberechnung </SPAN>
&nbsp;
<SPAN class=co1>// hier uart_init, uart_getc (s.o.)</SPAN>
&nbsp;
<SPAN class=kw4>int</SPAN> main<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
uart_init<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw1>if</SPAN> <SPAN class=br0>(</SPAN> <SPAN class=br0>(</SPAN>UCSRA <SPAN class=sy0>&amp;</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>RXC<SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN> <SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=co1>// Zeichen wurde empfangen, jetzt abholen</SPAN>
<SPAN class=kw4>uint8_t</SPAN> c<SPAN class=sy0>;</SPAN>
c <SPAN class=sy0>=</SPAN> uart_getc<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=co1>// hier etwas mit c machen z.B. auf PORT ausgeben</SPAN>
DDRC <SPAN class=sy0>=</SPAN> <SPAN class=nu12>0xFF</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// PORTC Ausgang</SPAN>
PORTC <SPAN class=sy0>=</SPAN> c<SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN>
<SPAN class=kw1>else</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=co1>// Kein Zeichen empfangen, Restprogramm ausführen...</SPAN>
<SPAN class=br0>}</SPAN>
<SPAN class=br0>}</SPAN>
<SPAN class=kw1>return</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// never reached </SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Eleganter und in den meisten Anwendungsfällen "stabiler" ist die
Vorgehensweise, die empfangenen Zeichen in einer Interrupt-Routine
einzulesen und zur späteren Verarbeitung in einem Eingangsbuffer
(FIFO-Buffer) zwischenzuspeichern. Dazu existieren fertige und gut
getestete <A title=Libraries
href="http://www.mikrocontroller.net/articles/Libraries">Bibliotheken</A>
und Quellcodekomponenten (z.&nbsp;B. UART-Library von P. Fleury,
procyon-avrlib und einige in der "Academy" von avrfreaks.net). </P>
<P>Siehe auch: </P>
<UL>
<LI><A class="external text"
href="http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html"
rel=nofollow>Dokumenation der avr-libc/stdlib.h</A> </LI>
<LI><A class="external text"
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Die_Nutzung_von_sprintf_und_printf">Die
Nutzung von sprintf und printf</A> </LI>
<LI><A class="external text"
href="http://homepage.hispeed.ch/peterfleury/" rel=nofollow>Peter
Fleurys</A> UART-Bibiliothek fuer avr-gcc/avr-libc </LI></UL>
<P><BR>TODO: 9bit </P>
<H3><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Empfang von Zeichenketten (Strings)"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=11">Bearbeiten</A>]</SPAN>
<SPAN id=Empfang_von_Zeichenketten_.28Strings.29 class=mw-headline>Empfang
von Zeichenketten (Strings) </SPAN></H3>
<P>Beim Empfang von Zeichenketten, muß man sich zunächst darüber im klaren
sein, daß es ein Kriterium geben muß, an dem der µC erkennen kann, wann
ein Text zu Ende ist. Sehr oft wird dazu das Zeichen 'Return' benutzt, um
das Ende eines Textes zu markieren. Dies ist vom Benutzer einfach
eingebbar und er ist auch daran gewöhnt, daß er eine Eingabezeile mit
einem Druck auf die Return Taste abgeschlossen wird. </P>
<P>Prinzipiell gibt es jedoch keine Einschränkung bezüglich dieses
speziellen Zeichens. Es muß nur sichergestellt werden, daß dieses
spezielle 'Ende eines Strings' - Zeichen nicht mit einem im Text
vorkommenden Zeichen verwechselt werden kann. Wenn also im zu
übertragenden Text beispielsweise kein ';' vorkommt, dann spricht nichts
dagegen, den Benutzer die Eingabe eines Textes mit einem ';' abschließen
zu lassen. </P>
<P>Im Folgenden wird die durchaus übliche Annahme getroffen, daß eine
Stringübertragung identisch ist mit der Übertragung einer Textzeile und
daher mit einem Return ('\n') abgeschlossen wird. </P>
<P>Das Problem der Übertragung eines Strings reduziert sich damit auf die
Aufgabenstellung: Empfange und sammle Zeichen in einem char Array, bis
entweder das Array voll ist oder das Text Ende Zeichen' empfangen wurde.
Danach wird der empfangene Text noch mit einem '\0' Zeichen abgeschlossen
um einen Standard C-String daraus zu machen, mit dem dann weiter
gearbeitet werden kann. </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=coMULTI>/* Zeichen empfangen */</SPAN>
<SPAN class=kw4>uint8_t</SPAN> uart_getc<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw1>while</SPAN> <SPAN class=br0>(</SPAN><SPAN class=sy0>!</SPAN><SPAN class=br0>(</SPAN>UCSRA <SPAN class=sy0>&amp;</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>RXC<SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN><SPAN class=br0>)</SPAN> <SPAN class=co1>// warten bis Zeichen verfuegbar</SPAN>
<SPAN class=sy0>;</SPAN>
<SPAN class=kw1>return</SPAN> UDR<SPAN class=sy0>;</SPAN> <SPAN class=co1>// Zeichen aus UDR an Aufrufer zurueckgeben</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
<SPAN class=kw4>void</SPAN> uart_gets<SPAN class=br0>(</SPAN> <SPAN class=kw4>char</SPAN><SPAN class=sy0>*</SPAN> Buffer<SPAN class=sy0>,</SPAN> <SPAN class=kw4>uint8_t</SPAN> MaxLen <SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw4>uint8_t</SPAN> NextChar<SPAN class=sy0>;</SPAN>
<SPAN class=kw4>uint8_t</SPAN> StringLen <SPAN class=sy0>=</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN>
&nbsp;
NextChar <SPAN class=sy0>=</SPAN> uart_getc<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// Warte auf und empfange das nächste Zeichen</SPAN>
&nbsp;
<SPAN class=co1>// Sammle solange Zeichen, bis:</SPAN>
<SPAN class=co1>// * entweder das String Ende Zeichen kam</SPAN>
<SPAN class=co1>// * oder das aufnehmende Array voll ist</SPAN>
<SPAN class=kw1>while</SPAN><SPAN class=br0>(</SPAN> NextChar <SPAN class=sy0>!=</SPAN> <SPAN class=st0>'<SPAN class=es1>\n</SPAN>'</SPAN> <SPAN class=sy0>&amp;&amp;</SPAN> StringLen <SPAN class=sy0>&lt;</SPAN> MaxLen <SPAN class=sy0>-</SPAN> <SPAN class=nu0>1</SPAN> <SPAN class=br0>)</SPAN> <SPAN class=br0>{</SPAN>
<SPAN class=sy0>*</SPAN>Buffer<SPAN class=sy0>++</SPAN> <SPAN class=sy0>=</SPAN> NextChar<SPAN class=sy0>;</SPAN>
StringLen<SPAN class=sy0>++;</SPAN>
NextChar <SPAN class=sy0>=</SPAN> uart_getc<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN>
&nbsp;
<SPAN class=co1>// Noch ein '\0' anhängen um einen Standard</SPAN>
<SPAN class=co1>// C-String daraus zu machen</SPAN>
<SPAN class=sy0>*</SPAN>Buffer <SPAN class=sy0>=</SPAN> <SPAN class=st0>'<SPAN class=es5>\0</SPAN>'</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Beim Aufruf ist darauf zu achten, dass das empfangende Array auch mit
einer vernünftigen Größe definiert wird. </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1> <SPAN class=kw4>char</SPAN> Line<SPAN class=br0>[</SPAN><SPAN class=nu0>40</SPAN><SPAN class=br0>]</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// String mit maximal 39 zeichen</SPAN>
&nbsp;
uart_gets<SPAN class=br0>(</SPAN> Line<SPAN class=sy0>,</SPAN> <SPAN class=kw4>sizeof</SPAN><SPAN class=br0>(</SPAN> Line <SPAN class=br0>)</SPAN> <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN></PRE></DIV></DIV>
<P>Bei der Benutzung von sizeof() ist allerdings zu beachten, dass
sizeof() nicht die Anzahl der Elemente des Arrays liefert, sondern die
Länge in Byte. Da ein char nur ein Byte lang ist, passt der Aufruf
'uart_gets(Line, sizeof( Line ) );' in diesem Fall. Falls man - aus
welchen Gründen auch immer - andere Datentypen benutzen möchte, sollte man
zur korrekten Angabe der Array-Länge folgende Vorgehensweise bevorzugen:
</P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1> <SPAN class=kw4>int</SPAN> Line<SPAN class=br0>[</SPAN><SPAN class=nu0>40</SPAN><SPAN class=br0>]</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// Array vom Typ int</SPAN>
&nbsp;
uart_gets<SPAN class=br0>(</SPAN> Line<SPAN class=sy0>,</SPAN> <SPAN class=kw4>sizeof</SPAN><SPAN class=br0>(</SPAN> Line <SPAN class=br0>)</SPAN> <SPAN class=sy0>/</SPAN> <SPAN class=kw4>sizeof</SPAN><SPAN class=br0>(</SPAN> Line<SPAN class=br0>[</SPAN><SPAN class=nu0>0</SPAN><SPAN class=br0>]</SPAN> <SPAN class=br0>)</SPAN> <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN></PRE></DIV></DIV>
<H2><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Interruptbetrieb"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=12">Bearbeiten</A>]</SPAN>
<SPAN id=Interruptbetrieb class=mw-headline>Interruptbetrieb</SPAN></H2>
<P>Hier wird das Grundwissen des Artikels <A title=Interrupt
href="http://www.mikrocontroller.net/articles/Interrupt">Interrupt</A> und
des Abschnitts <A title=AVR-GCC-Tutorial
href="http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmieren_mit_Interrupts">AVR-GCC-Tutorial:
Programmieren_mit_Interrupts</A> vorausgesetzt. </P>
<H3><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Empfangen (RX)"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=13">Bearbeiten</A>]</SPAN>
<SPAN id=Empfangen_.28RX.29 class=mw-headline>Empfangen (RX) </SPAN></H3>
<P>Beim ATmega8 muss das <B>RXCIE</B> Bit im Register UCSRB gesetzt
werden, damit ein Interrupt beim Empfang eines Zeichens ausgelöst werden
kann. </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=coMULTI>/* siehe auch obere Baudrateneinstellung */</SPAN>
<SPAN class=coMULTI>/* USART-Init beim ATmega16 */</SPAN>
<SPAN class=kw4>void</SPAN> uart_init<SPAN class=br0>(</SPAN><SPAN class=kw4>void</SPAN><SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
UBRRH <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&gt;&gt;</SPAN> <SPAN class=nu0>8</SPAN><SPAN class=sy0>;</SPAN>
UBRRL <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&amp;</SPAN> <SPAN class=nu12>0xFF</SPAN><SPAN class=sy0>;</SPAN>
UCSRC <SPAN class=sy0>=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>URSEL<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UCSZ1<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>UCSZ0<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// Asynchron 8N1 </SPAN>
UCSRB <SPAN class=sy0>|=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>RXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>TXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0>&lt;&lt;</SPAN>RXCIE<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// UART RX, TX und RX Interrupt einschalten</SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Natürlich muss "Global Interrupt Enable" mittels des Befehls sei()
aktiviert sein. Interrupt-spezifische Definitionen werden über die
Includedatei eingebunden: </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#include &lt;avr/interrupt.h&gt;</SPAN></PRE></DIV></DIV>
<P>Der Interrupt wird immer ausgelöst, wenn ein Zeichen erfolgreich
empfangen wurde. Zusätzlich braucht man die Interruptserviceroutine (ISR).
</P>
<P>In diesem Beispiel enthält die ISR einen FIFO-Puffer (First in, First
out). Dafür werden ein paar globale Variablen und Makros benötigt: </P>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1><SPAN class=co2>#define UART_MAXSTRLEN 10</SPAN>
&nbsp;
<SPAN class=kw4>volatile</SPAN> <SPAN class=kw4>uint8_t</SPAN> uart_str_complete <SPAN class=sy0>=</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// 1 .. String komplett empfangen</SPAN>
<SPAN class=kw4>volatile</SPAN> <SPAN class=kw4>uint8_t</SPAN> uart_str_count <SPAN class=sy0>=</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=kw4>volatile</SPAN> <SPAN class=kw4>char</SPAN> uart_string<SPAN class=br0>[</SPAN>UART_MAXSTRLEN <SPAN class=sy0>+</SPAN> <SPAN class=nu0>1</SPAN><SPAN class=br0>]</SPAN> <SPAN class=sy0>=</SPAN> <SPAN class=st0>""</SPAN><SPAN class=sy0>;</SPAN></PRE></DIV></DIV>
<DIV dir=ltr class="mw-geshi mw-code mw-content-ltr">
<DIV class="c source-c"><PRE class=de1>ISR<SPAN class=br0>(</SPAN>USART_RXC_vect<SPAN class=br0>)</SPAN>
<SPAN class=br0>{</SPAN>
<SPAN class=kw4>unsigned</SPAN> <SPAN class=kw4>char</SPAN> nextChar<SPAN class=sy0>;</SPAN>
&nbsp;
<SPAN class=co1>// Daten aus dem Puffer lesen</SPAN>
nextChar <SPAN class=sy0>=</SPAN> UDR<SPAN class=sy0>;</SPAN>
<SPAN class=kw1>if</SPAN><SPAN class=br0>(</SPAN> uart_str_complete <SPAN class=sy0>==</SPAN> <SPAN class=nu0>0</SPAN> <SPAN class=br0>)</SPAN> <SPAN class=br0>{</SPAN> <SPAN class=co1>// wenn uart_string gerade in Verwendung, neues Zeichen verwerfen</SPAN>
&nbsp;
<SPAN class=co1>// Daten werden erst in uart_string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird</SPAN>
<SPAN class=kw1>if</SPAN><SPAN class=br0>(</SPAN> nextChar <SPAN class=sy0>!=</SPAN> <SPAN class=st0>'<SPAN class=es1>\n</SPAN>'</SPAN> <SPAN class=sy0>&amp;&amp;</SPAN>
nextChar <SPAN class=sy0>!=</SPAN> <SPAN class=st0>'<SPAN class=es1>\r</SPAN>'</SPAN> <SPAN class=sy0>&amp;&amp;</SPAN>
uart_str_count <SPAN class=sy0>&lt;</SPAN> UART_MAXSTRLEN <SPAN class=br0>)</SPAN> <SPAN class=br0>{</SPAN>
uart_string<SPAN class=br0>[</SPAN>uart_str_count<SPAN class=br0>]</SPAN> <SPAN class=sy0>=</SPAN> nextChar<SPAN class=sy0>;</SPAN>
uart_str_count<SPAN class=sy0>++;</SPAN>
<SPAN class=br0>}</SPAN>
<SPAN class=kw1>else</SPAN> <SPAN class=br0>{</SPAN>
uart_string<SPAN class=br0>[</SPAN>uart_str_count<SPAN class=br0>]</SPAN> <SPAN class=sy0>=</SPAN> <SPAN class=st0>'<SPAN class=es5>\0</SPAN>'</SPAN><SPAN class=sy0>;</SPAN>
uart_str_count <SPAN class=sy0>=</SPAN> <SPAN class=nu0>0</SPAN><SPAN class=sy0>;</SPAN>
uart_str_complete <SPAN class=sy0>=</SPAN> <SPAN class=nu0>1</SPAN><SPAN class=sy0>;</SPAN>
<SPAN class=br0>}</SPAN>
<SPAN class=br0>}</SPAN>
<SPAN class=br0>}</SPAN></PRE></DIV></DIV>
<P>Zur Funktion: Wurde eine komplette Zeichenkette empfangen, also das
Ende (\n oder \r) erkannt oder die maximale Länge <I>UART_MAXSTRLEN</I>
erreicht, wird die globale Variable <I>uart_str_complete</I> auf '1'
gesetzt. Damit wird dem Hauptprogramm, welches auf diese Variable pollt,
mitgeteilt, dass die Zeichenkette <I>uart_string</I> zur Verarbeitung
bereit steht. Nach der Verarbeitung der Zeichenkette in der entsprechenden
main-Routine, muss die Variable <I>uart_str_complete</I> wieder auf '0'
zurück gesetzt werden. Dadurch werden alle neu empfangenen Zeichen wieder
in den globalen Puffer geschrieben. </P>
<H3><SPAN class=editsection>[<A title="Abschnitt bearbeiten: (Baustelle)"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=14">Bearbeiten</A>]</SPAN>
<SPAN id=.28Baustelle.29 class=mw-headline>(Baustelle) </SPAN></H3>
<UL>
<LI>Empfangen (Receive) (Anm.: z.T. erledigt)
<UL>
<LI>ggf. Fallstricke (<A class="external text"
href="http://www.mikrocontroller.net/topic/84256#707214">UDR in der
ISR lesen!</A>) </LI>
<LI>Komplettes, einfaches Beispiel (<A class="external text"
href="http://www.mikrocontroller.net/topic/84228#707052">Echo</A>
(noch buggy beim Datenzugriff, siehe Lit. 2+3!)), ggf. LED zur
ISR-Empfangsanzeige oder Overflow-Anzeige </LI></UL></LI></UL>
<UL>
<LI>Senden (Transmit)
<UL>
<LI>Variante "UART Data Register Empty" (UDRE) <A
class="external autonumber"
href="http://www.mikrocontroller.net/topic/101472#882716">[2]</A>
</LI>
<LI>Variante "UART Transmit Complete" (TXC) </LI></UL></LI></UL>
<UL>
<LI>FIFO-Puffer <A class="external autonumber"
href="http://www.mikrocontroller.net/topic/101472#882716">[3]</A>,
Ringpuffer (Byte Buffering (circular)) </LI></UL>
<UL>
<LI>UART-Bibliotheken
<UL>
<LI><A class="external text"
href="http://homepage.hispeed.ch/peterfleury/avr-software.html"
rel=nofollow>UART-Library</A> von Peter Fleury (UART (interrupt
driven), Byte Buffering (circular)) </LI>
<LI><A class="external text"
href="http://beaststwo.org/avr-uart/index.shtml" rel=nofollow>Updated
AVR UART Library</A> (modernisierte und erweiterte Version der
Bibliothek von Peter Fleury) </LI>
<LI><A class="external text"
href="http://www.procyonengineering.com/embedded/avr/avrlib/"
rel=nofollow>Procyon AVRlib</A> von Pascal Stang (UART (interrupt
driven), Byte Buffering (circular), VT100 Terminal Output) </LI>
<LI><A class="external text"
href="http://die-seite.ch/microcontroller/uart_driver.c"
rel=nofollow>uart_driver.c</A> Beispieltreiber in C mit minimalstem
Code fuer ATMega8. Sendet und empfaengt Strings ueber Interrupts (von
Markus Zimmermann) </LI></UL></LI></UL>
<UL>
<LI>Literatur
<UL>
<LI><A class="external text"
href="http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;file=viewtopic&amp;t=48188"
rel=nofollow>avrfreaks.net Tutorial</A> inkl. Diskussion (engl.) </LI>
<LI>avr-libc FAQ: <A class="external text"
href="http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_16bitio"
rel=nofollow>Why do some 16-bit timer registers sometimes get
trashed?</A> </LI></UL></LI></UL>
<H2><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Software-UART"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=15">Bearbeiten</A>]</SPAN>
<SPAN id=Software-UART class=mw-headline>Software-UART</SPAN></H2>
<P>Falls die Zahl der vorhandenen Hardware-UARTs nicht ausreicht, können
weitere Schnittstellen über sogennante Software-UARTs ergänzt werden. Es
gibt dazu (mindestens) zwei Ansätze: </P>
<UL>
<LI>Der bei AVRs üblichste Ansatz basiert auf dem Prinzip, dass ein
externer Interrupt-Pin für den Empfang ("RX") genutzt wird. Das Startbit
löst den Interrupt aus, in der Interrupt-Routine (ISR) wird der externe
Interrupt deaktiviert und ein Timer aktiviert. In der Interrupt-Routine
des Timers wird der Zustand des Empfangs-Pins entsprechend der Baudrate
abgetastet. Nach Empfang des Stop-Bits wird der externe Interrupt wieder
aktiviert. Senden kann über einen beliebigen Pin ("TX") erfolgen, der
entsprechend der Baudrate und dem zu sendenden Zeichen auf 0 oder 1
gesetzt wird. Die Implementierung ist nicht ganz einfach, es existieren
dazu aber fertige Bibliotheken (z.&nbsp;B. bei <A class="external text"
href="http://www.avrfreaks.net/" rel=nofollow>avrfreaks</A> oder in der
<A class="external text"
href="http://www.procyonengineering.com/embedded/avr/avrlib/"
rel=nofollow>Procyon avrlib</A>). </LI>
<LI>Ein weiterer Ansatz erfordert keinen Pin mit "Interrupt-Funktion"
aber benötigt mehr Rechenzeit. Jeder Input-Pin kann als Empfangspin (RX)
dienen. Über einen Timer wird der Zustand des RX-Pins mit einem
vielfachen der Baudrate abgetastet (dreifach scheint üblich) und High-
bzw. Lowbits anhand einer Mindestanzahl identifiziert. (Beispiel:
"Generic Software Uart" Application-Note von IAR) </LI></UL>
<P>Neuere AVRs (z.&nbsp;B. ATtiny26 oder ATmega48,88,168,169) verfügen
über ein Universal Serial Interface (USI), das teilweise UART-Funktion
übernehmen kann. Atmel stellt eine Application-Note bereit, in der die
Nutzung des USI als UART erläutert wird (im Prinzip
"Hardware-unterstützter Software-UART"). </P>
<H2><SPAN class=editsection>[<A title="Abschnitt bearbeiten: Handshaking"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=16">Bearbeiten</A>]</SPAN>
<SPAN id=Handshaking class=mw-headline>Handshaking</SPAN></H2>
<P>Wenn der Sender ständig sendet, wird irgendwann der Fall eintreten, daß
der Empfänger nicht bereit ist, neue Zeichen zu empfangen. In diesem Fall
muß durch ein <B>Handshake-Verfahren</B> die Situation bereinigt werden.
Handshake bedeutet nichts anderes, als daß der Empfänger dem Sender
mitteilt, daß er zur Zeit keine Daten annehmen kann und der Sender die
Übertragung der nächsten Zeichen solange einstellen soll, bis der
Empfänger signalisiert, daß er wieder Zeichen aufnehmen kann. </P>
<H3><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Hardwarehandshake (RTS/CTS)"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=17">Bearbeiten</A>]</SPAN>
<SPAN id=Hardwarehandshake_.28RTS.2FCTS.29
class=mw-headline>Hardwarehandshake (RTS/CTS)</SPAN></H3>
<P>Beim Hardwarehandshake werden zusätzlich zu den beiden
Daten-Übertragungsleitungen noch 2 weitere Leitungen benötigt: <B>RTS</B>
(<B>R</B>equest <B>T</B>o <B>S</B>end) und <B>CTS</B> (<B>C</B>lear
<B>T</B>o <B>S</B>end). Jeder der beiden Kommunikationspartner ist
verpflichtet, bevor ein Zeichen gesendet wird, den Zustand der <B>RTS</B>
Leitung zu überprüfen. Nur wenn die Gegenstelle darauf
Empfangsbereitschaft signalisiert, darf das Zeichen gesendet werden. Um
der Gegenstelle zu signalisieren, daß sie zur Zeit keine Zeichen schicken
soll, wird die Leitung <B>CTS</B> benutzt. </P>
<H3><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Softwarehandshake (XON/XOFF)"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=18">Bearbeiten</A>]</SPAN>
<SPAN id=Softwarehandshake_.28XON.2FXOFF.29
class=mw-headline>Softwarehandshake (XON/XOFF)</SPAN></H3>
<P>Beim Softwarehandshake sind keine speziellen Leitungen notwendig.
Stattdessen werden besondere ASCII-Zeichen benutzt, die der Gegenstelle
signalisieren, das Senden einzustellen bzw. wieder aufzunehmen. </P>
<UL>
<LI><B>XOFF</B> Aufforderung das Senden einzustellen </LI>
<LI><B>XON</B> Gegenstelle darf wieder senden </LI></UL>
<P>Nachteilig bei einem Softwarehandshake ist, dass dadurch keine direkte
binäre Datenübertragung mehr möglich ist, denn von den möglichen 256
Bytewerten werden ja nun zwei (nämlich für <B>XON</B> und für <B>XOFF</B>)
für besondere Zwecke benutzt und fallen daher aus. In einem
quasi-zufälligen Bytestrom, den eine Binärdatei darstellt, kämen diese
beiden reservierten früher oder später vor und würden dann den Strom
ungewollt stoppen und starten. </P>
<H2><SPAN class=editsection>[<A
title="Abschnitt bearbeiten: Galvanische Trennung"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=19">Bearbeiten</A>]</SPAN>
<SPAN id=Galvanische_Trennung class=mw-headline>Galvanische
Trennung</SPAN></H2>
<P>Für eine geringe Überspannungsfestigkeit empfielt es sich, die
Datenkanäle über Optokoppler zu führen. Es bietet sich z.b. der 6N138 an,
ein "normaler" CNY-17 ist für hohe Baudraten nicht brauchbar. </P>
<H2><SPAN class=editsection>[<A title="Abschnitt bearbeiten: Fehlersuche"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=20">Bearbeiten</A>]</SPAN>
<SPAN id=Fehlersuche class=mw-headline>Fehlersuche</SPAN></H2>
<P>Erstaunlich oft wird im Forum der Hilferuf laut: "Meine UART
funktioniert nicht, was mache ich falsch". In der überwiegenden Mehrzahl
der Fälle stellt sich dann heraus, daß es sich um ein Hardwareproblem
handelt, wobei da wiederrum der Löwenanteil auf das Konto einer nicht
korrekt eingestellten Taktrate geht: Der µC benutzt nicht einen
angeschlossenen Quarz, so wie er auch im Programm eingetragen ist, sondern
läuft immer noch mit dem internen RC-Takt. Daraus resultiert aber auch,
daß der Baudraten Konfigurationswert falsch berechnet wird. </P>
<P>Hilfreich zum Aufspüren solcher Fehler ist auch die <A
title="AVR Checkliste"
href="http://www.mikrocontroller.net/articles/AVR_Checkliste#UART.2FUSART">AVR-Checkliste</A>.
</P>
<H2><SPAN class=editsection>[<A title="Abschnitt bearbeiten: Links"
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;action=edit&amp;section=21">Bearbeiten</A>]</SPAN>
<SPAN id=Links class=mw-headline>Links</SPAN></H2>
<P>Tipps zur Verarbeitung von Strings sind in den <A title=FAQ
href="http://www.mikrocontroller.net/articles/FAQ">FAQ</A>. </P><!--
NewPP limit report
Preprocessor visited node count: 295/1000000
Preprocessor generated node count: 556/1000000
Postexpand include size: 0/2097152 bytes
Template argument size: 0/2097152 bytes
Highest expansion depth: 2/40
Expensive parser function count: 0/100
--><!-- Saved in parser cache with key uc_wiki:pcache:idhash:4483-0!0!0!!de!*!* and timestamp 20131127081841 --></DIV><!-- /bodycontent --><!-- printfooter -->
<DIV class=printfooter>Von „<A
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;oldid=78711">http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;oldid=78711</A>
</DIV><!-- /printfooter --><!-- catlinks -->
<DIV id=catlinks class=catlinks>
<DIV id=mw-normal-catlinks class=mw-normal-catlinks><A
title=Spezial:Kategorien
href="http://www.mikrocontroller.net/articles/Spezial:Kategorien">Kategorien</A>:
<UL>
<LI><A title="Kategorie:Avr-gcc Tutorial"
href="http://www.mikrocontroller.net/articles/Kategorie:Avr-gcc_Tutorial">Avr-gcc
Tutorial</A></LI>
<LI><A title="Kategorie:UART und RS232"
href="http://www.mikrocontroller.net/articles/Kategorie:UART_und_RS232">UART
und RS232</A></LI></UL></DIV></DIV><!-- /catlinks -->
<DIV class=visualClear></DIV><!-- debughtml --><!-- /debughtml --><!-- start adsense --><!-- end adsense -->
<DIV
class=visualClear></DIV></DIV></TD><!-- google_ad_section_end --></TR></TBODY></TABLE><!--
<div class="visualClear"></div>
<div id="footer" style="clear:both">
<div id="f-poweredbyico"><a href="//www.mediawiki.org/"><img src="/wikisoftware/skins/common/images/poweredby_mediawiki_88x31.png" height="31" width="88" alt="Powered by MediaWiki" /></a></div> <ul id="f-list">
<li id="f-lastmod"> Diese Seite wurde zuletzt am 30. September 2013 um 19:33 Uhr geändert.</li> <li id="f-viewcount">Diese Seite wurde bisher 204.247-mal abgerufen.</li> <li id="f-about"><a href="/articles/Uc-wiki:%C3%9Cber_Uc-wiki" title="Uc-wiki:Über Uc-wiki">Über Uc-wiki</a></li> <li id="f-disclaimer"><a href="/articles/Uc-wiki:Impressum" title="Uc-wiki:Impressum">Impressum</a></li> </ul>
</div>--></DIV>
<DIV id=bottom>
<DIV id=impress><A
href="mailto:webmaster@mikrocontroller.net?subject=Mikrocontroller.net">mailto:webmaster@mikrocontroller.net?subject=Mikrocontroller.net</A>
<A href="http://www.mikrocontroller.net/contact">Impressum</A> <A
href="http://www.mikrocontroller.net/user/conditions">Nutzungsbedingungen</A>
<A
href="mailto:webmaster@mikrocontroller.net?subject=Anfrage%20zu%20Werbung%20auf%20Mikrocontroller.net">Werbung
auf Mikrocontroller.net</A> </DIV>
<DIV id=powered><!-- powered by Ruby on Rails --></DIV><A
href="http://www.mikrocontroller.net/util/rb"><!-- nothing --></A><!-- <a href="http://www.mikrocontroller.net/hp/curlews.php">nothing to see here</a> --></DIV>
<SCRIPT>if(window.mw){
mw.loader.state({"site":"loading","user":"missing","user.groups":"ready"});
}</SCRIPT>
<SCRIPT>if(window.mw){
mw.loader.load(["mediawiki.action.view.postEdit","mediawiki.user","mediawiki.page.ready","mediawiki.searchSuggest","mediawiki.hidpi"], null, true);
}</SCRIPT>
<SCRIPT
src="AVR-GCC-Tutorial-Der%20UART%20-%20Mikrocontroller_net-Dateien/load(1).php"></SCRIPT>
<!-- Served in 0.076 secs. --></BODY></HTML>