1879 lines
112 KiB
HTML
1879 lines
112 KiB
HTML
<!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&action=edit"><LINK
|
||
title=Bearbeiten rel=edit
|
||
href="/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&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&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 & 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
|
||
& 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
|
||
& 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
|
||
& 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
|
||
& Werkzeug</A></LI>
|
||
<LI><A href="http://www.mikrocontroller.net/forum/hf">HF, Funk &
|
||
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- & Software</A></LI>
|
||
<LI><A
|
||
href="http://www.mikrocontroller.net/forum/ausbildung-studium-beruf">Ausbildung
|
||
& 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&action=edit">Bearbeiten</A></LI>
|
||
<LI id=ca-history><A
|
||
href="http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&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&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> <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&action=edit&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. 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. B. minicom). Ein direkter
|
||
Anschluss ist aufgrund unterschiedlicher Pegel nicht möglich, jedoch
|
||
sind entsprechende Schnittstellen-ICs wie z. 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. B. Konfiguration und Statusabfrage über eine "Kommandozeile"
|
||
oder Menüs (siehe z. 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. B. bei einem Datenlogger </DD>
|
||
<DT>Anschluss von Geräten</DT>
|
||
<DD>mit serieller Schnittstelle (z. 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. 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&action=edit&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. 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&action=edit&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 </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 </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 </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=" \mathrm{UBRR} = \frac{\mathrm{Taktfrequenz}}{\mathrm{Baudrate} \cdot 16} - 1 "
|
||
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&action=edit&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><<</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. 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><<</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><<</SPAN>URSEL<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN> <SPAN class=sy0><<</SPAN> UCSZ1<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN> <SPAN class=sy0><<</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>
|
||
|
||
<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
|
||
|
||
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>
|
||
|
||
<SPAN class=co2>#define BAUD 9600UL // Baudrate</SPAN>
|
||
|
||
<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>
|
||
|
||
<SPAN class=co2>#if ((BAUD_ERROR<990) || (BAUD_ERROR>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. B.
|
||
uart_init() dafür geschrieben, die in der eigenen Codesammlung in mehreren
|
||
Projekten verwendet werden kann. </P>
|
||
<P>Für einige AVR (z. B. ATmega169, ATmega48/88/168, AT90CAN jedoch
|
||
nicht für z. 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>
|
||
|
||
<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><<</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><<</SPAN>UCSZ01<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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>
|
||
|
||
<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>>></SPAN> <SPAN class=nu0>8</SPAN><SPAN class=sy0>;</SPAN>
|
||
UBRRL <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&</SPAN> <SPAN class=nu12>0xFF</SPAN><SPAN class=sy0>;</SPAN>
|
||
|
||
UCSRB <SPAN class=sy0>|=</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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><<</SPAN>URSEL<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</SPAN>UCSZ1<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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><util/setbaud.h></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 <avr/io.h> </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 <util/setbaud.h></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> 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><<</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>&=</SPAN> ~<SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN> <SPAN class=sy0><<</SPAN> U2X<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
|
||
<SPAN class=co2>#endif</SPAN>
|
||
|
||
<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 <util/setbaud.h></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&action=edit&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&action=edit&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>&</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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>
|
||
|
||
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&action=edit&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>&</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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>
|
||
|
||
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>
|
||
|
||
|
||
<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 != '\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&action=edit&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 <avr/io.h></SPAN>
|
||
<SPAN class=co2>#include <stdlib.h></SPAN>
|
||
<SPAN class=co1>//...</SPAN>
|
||
|
||
<SPAN class=co1>// hier uart_putc (s.o.)</SPAN>
|
||
|
||
<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>
|
||
|
||
uart_init<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
|
||
|
||
<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><=</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>
|
||
|
||
<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>
|
||
|
||
<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>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 <avr/io.h></SPAN>
|
||
<SPAN class=co2>#include <stdlib.h></SPAN>
|
||
|
||
<SPAN class=co1>//...</SPAN>
|
||
|
||
<SPAN class=co1>// hier uart_init, uart_putc, uart_puts (s.o.)</SPAN>
|
||
|
||
<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>
|
||
|
||
uart_init<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</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=sy0>;</SPAN> <SPAN class=co1>// 10 fuer radix -> Dezimalsystem</SPAN>
|
||
uart_puts<SPAN class=br0>(</SPAN> s <SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
|
||
|
||
<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>
|
||
|
||
<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>
|
||
|
||
<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 -> Configurations Options -> Libaries -> 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 <avr/io.h></SPAN>
|
||
<SPAN class=co2>#include <stdlib.h></SPAN>
|
||
|
||
<SPAN class=co1>//...</SPAN>
|
||
|
||
<SPAN class=co1>// hier uart_init, uart_putc, uart_puts (s.o.)</SPAN>
|
||
|
||
<SPAN class=coMULTI>/* lt. avr-libc Dokumentation:
|
||
char* dtostrf(
|
||
double __val,
|
||
char __width,
|
||
char __prec,
|
||
char * __s
|
||
)
|
||
*/</SPAN>
|
||
|
||
<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>
|
||
|
||
uart_init<SPAN class=br0>(</SPAN><SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN>
|
||
|
||
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>
|
||
|
||
<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>
|
||
|
||
<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&action=edit&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&action=edit&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 <inttypes.h></SPAN>
|
||
<SPAN class=co2>#include <avr/io.h></SPAN>
|
||
|
||
<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>>></SPAN> <SPAN class=nu0>8</SPAN><SPAN class=sy0>;</SPAN>
|
||
UBRRL <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&</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><<</SPAN>URSEL<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</SPAN>UCSZ1<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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><<</SPAN>RXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>;</SPAN> <SPAN class=co1>// UART RX einschalten</SPAN>
|
||
<SPAN class=br0>}</SPAN>
|
||
|
||
<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>&</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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 <avr/io.h></SPAN>
|
||
<SPAN class=co2>#include <stdlib.h></SPAN>
|
||
|
||
<SPAN class=co1>// hier Makro für die Baudratenberechnung </SPAN>
|
||
|
||
<SPAN class=co1>// hier uart_init, uart_getc (s.o.)</SPAN>
|
||
|
||
<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>
|
||
|
||
<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 <avr/io.h></SPAN>
|
||
<SPAN class=co2>#include <stdlib.h></SPAN>
|
||
|
||
<SPAN class=co1>// hier Makro für die Baudratenberechnung </SPAN>
|
||
|
||
<SPAN class=co1>// hier uart_init, uart_getc (s.o.)</SPAN>
|
||
|
||
<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>&</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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. 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&action=edit&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>&</SPAN> <SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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>
|
||
|
||
<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>
|
||
|
||
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>
|
||
|
||
<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>&&</SPAN> StringLen <SPAN class=sy0><</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>
|
||
|
||
<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>
|
||
|
||
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>
|
||
|
||
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&action=edit&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&action=edit&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>>></SPAN> <SPAN class=nu0>8</SPAN><SPAN class=sy0>;</SPAN>
|
||
UBRRL <SPAN class=sy0>=</SPAN> UBRR_VAL <SPAN class=sy0>&</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><<</SPAN>URSEL<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</SPAN>UCSZ1<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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><<</SPAN>RXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</SPAN>TXEN<SPAN class=br0>)</SPAN><SPAN class=sy0>|</SPAN><SPAN class=br0>(</SPAN><SPAN class=nu0>1</SPAN><SPAN class=sy0><<</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 <avr/interrupt.h></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>
|
||
|
||
<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>
|
||
|
||
<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>
|
||
|
||
<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>&&</SPAN>
|
||
nextChar <SPAN class=sy0>!=</SPAN> <SPAN class=st0>'<SPAN class=es1>\r</SPAN>'</SPAN> <SPAN class=sy0>&&</SPAN>
|
||
uart_str_count <SPAN class=sy0><</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&action=edit&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&file=viewtopic&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&action=edit&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. 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. 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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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&action=edit&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
|
||
Post‐expand 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&oldid=78711">http://www.mikrocontroller.net/wikisoftware/index.php?title=AVR-GCC-Tutorial/Der_UART&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>
|