<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=84.167.184.249</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=84.167.184.249"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/84.167.184.249"/>
	<updated>2026-04-14T15:03:48Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Avr-akku-kapazitaet-messen&amp;diff=25253</id>
		<title>Avr-akku-kapazitaet-messen</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Avr-akku-kapazitaet-messen&amp;diff=25253"/>
		<updated>2007-12-28T21:59:53Z</updated>

		<summary type="html">&lt;p&gt;84.167.184.249: Meine Erfahrungen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Messen der Akkukapazität mit einem AVR ==&lt;br /&gt;
&lt;br /&gt;
Entstehen soll ein sehr einfaches Gerät, das die Kapazität der Akkus anzeigt.&lt;br /&gt;
&lt;br /&gt;
Um das Projekt zu starten, sollten erst einmal die grundlegenden Spezifikationen festgelegt werden:&lt;br /&gt;
&lt;br /&gt;
* Die Schaltung soll einfach sein (Leichter Nahbau)&lt;br /&gt;
* Es werden nur Lade- / Entladespannungen bis 2.56 Volt unterstützt. Das reicht für AAA / AA / B / C / D - Zellen. Es werden nur einzelne NiCD / NiMH -zellen getestet&lt;br /&gt;
* Stromsenke (LM317, MOS-FET)&lt;br /&gt;
* 2-zeiliges LC-Display&lt;br /&gt;
* Entladestrom fest eingestellt durch einen 6 Ohm Entladdewiderstand&lt;br /&gt;
* Stromversorgung: Netzteil&lt;br /&gt;
* Entladen / Laden von bis zu 4 Akkus gleichzeitig. Jeder für sich, unabhängig voneinander.&lt;br /&gt;
* Verwendung eines einfachen unzuverlässigen Batteriehalters. Wenn die Spannung vom Akku für eine kurze Zeit (&amp;lt; 5Sec) ausfällt, soll das ignoriert werden&lt;br /&gt;
* Messen der Entladespannung, während der Entladestrom fließt, und Abschalten des Entladestroms, um die Leerlaufspannung messen zu können.&lt;br /&gt;
* Abschätzen (berechnen) des Entladestromes, ohne den Strom zu messen.  Stattdessen wird die Entladespannung über dem bekannten Entladewiederstand gemessen und der Strom und der integrierte Strom berechnet.&lt;br /&gt;
* Bedienung über die serielle Schnittstelle.&lt;br /&gt;
* Abfragen des Entladezustandes (Warten auf Akku, Entladen, Warten bis Akku entfernt) über die serielle Schnittstelle.&lt;br /&gt;
* Möglichkeit den Akku zu laden (Befehl über die serielle Schnittstelle)&lt;br /&gt;
* Abschätzen (berechnen) des Ladestroms aus der Akkuspannung, der Versorgungsspannung und des bekannten ladesstrombestimmenden Festwiderstandes.&lt;br /&gt;
* Begrenzung der Ladung durch Vorgabe der maximalen Ladespannung&lt;br /&gt;
* Begrenzung der Ladung durch Vorgabe des maximales Ladestromintegrals.&lt;br /&gt;
* Bilden eine Tabelle der Entladespannungen (alle Minuten eine Abfrage) durch Excel. (Excel benutzt porl.dll um die Entladespannung abzufragen.)&lt;br /&gt;
* Bilden einer Entladegrafik durch Excel.&lt;br /&gt;
&lt;br /&gt;
Die größte Problematik eines Akku - Testers sind die Übergangswiderstände zwischen der AA / AAA - Zelle und dem (billigen, China-) Batteriehalter.&lt;br /&gt;
&lt;br /&gt;
Diese sind Abhängig von der Lage des Akkus (Einfaches Drehen des Akkus verändert die angezeigte Entladespannung eines AA - Akkus mal geschwind um 60 mV&lt;br /&gt;
&lt;br /&gt;
Hier mal eine Beispielschaltung aus dem Forum:&lt;br /&gt;
[http://www.mikrocontroller.net/forum/read-1-199581.html Akku-Kapazitätsmessung mit AVR]&lt;br /&gt;
&lt;br /&gt;
[[Bild:1AStromsenke.jpg|1A Stromsenke mit LM317.jpg]]&lt;/div&gt;</summary>
		<author><name>84.167.184.249</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Muluwuw&amp;diff=25250</id>
		<title>Muluwuw</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Muluwuw&amp;diff=25250"/>
		<updated>2007-12-28T16:26:52Z</updated>

		<summary type="html">&lt;p&gt;84.167.184.249: Erstellt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Multiplikation von 2 16-bit-Zahlen =&lt;br /&gt;
&lt;br /&gt;
Wenn wir schriftlich zwei Zahlen multiplizieren, kommen immer größere Zahlen heraus, als jeder der beiden Faktoren.&lt;br /&gt;
&lt;br /&gt;
Beispiel: 999 * 99999 = 99899001&lt;br /&gt;
&lt;br /&gt;
Weil hier eine dreistellige Zahl mit einer fünfstelligen Zahl multipliziert wurde, kann das Ergebnis achtstellig sein.&lt;br /&gt;
&lt;br /&gt;
Das ist bei Binärzahlen genauso:&lt;br /&gt;
&lt;br /&gt;
Wenn eine 8-Bit-Zahl mit einer 8-Bit-Zahl multipliziert wird, wird ein 16-bit-Ergebnis herauskommen.&lt;br /&gt;
&lt;br /&gt;
== Der Programmcode 16 bit mal 16 bit ergibt 32 bit ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// This routine multiplies two 16 bit integers,&lt;br /&gt;
// The return value is a 32 bit integer&lt;br /&gt;
//&lt;br /&gt;
// See also mulswsw.cpp : Signed 16 bit * signed 16 bit &lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;heport.h&amp;gt;&lt;br /&gt;
#include &amp;lt;heimath.h&amp;gt;		// definition of mul_uw_uw&lt;br /&gt;
#ifdef AVR&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef AVR&lt;br /&gt;
// Other processors do not need speed up&lt;br /&gt;
FUNCT ulong mul_uw_uw( uword x , uword y )&lt;br /&gt;
{&lt;br /&gt;
ulong res ;&lt;br /&gt;
&lt;br /&gt;
res = (ulong)x * (ulong)y ;&lt;br /&gt;
return res ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#else&lt;br /&gt;
&lt;br /&gt;
#if 0 /* Software- Multiply */&lt;br /&gt;
// input:&lt;br /&gt;
// r23_r22 = x.h_x.l&lt;br /&gt;
// r25_r24 = y.h_y.l&lt;br /&gt;
// may destroy r18 r19 r20 r21 r22 r23 r24* r25* r26* r27*&lt;br /&gt;
// may not destroy r14 r15 r16 r17 r28=YL r29=YH&lt;br /&gt;
// return r25_r24_r23_r22&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
FUNCT ulong dummy_mul_uw_uw( uword x , uword y )&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
// asm(&amp;quot; .text &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot;  .global mul_uw_uw&amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; See as well mul_uc_uc : 8 bit by 8 bit, result 16 bits &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Function mul_uw_uw &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; multiply unsigned 16 bit by 16 bit &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Input: &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ;     r23:r22   : The factor &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ;     r25:r24   : The factor &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Results &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ;     r25:r24:r23:r22    : result &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Destroyed registers &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ;     r18 r19 r20 r21 r26 r27&amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; This program is verified by qqarith.asm &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
//asm(&amp;quot; _Z9mul_uw_uwtt: &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot;mul_uw_uw: &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	push r16 ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Clear start values &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	mov r26,r22 ; factor x to interim storage &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	mov	r27,r23 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	mov r18,r24 ; factor y to interim storage &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	mov	r19,r25 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	clr r20 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	clr r21 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Clear result r25:r24;r23;r22 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	clr r22 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	clr r23 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	clr r24 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	clr r25 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; mul_uw_uw_3: &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	lsr	r27 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	ror	r26		; next binary digit of right factor to carry &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	brcc	mul_uw_uw_4 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Add the (shifted) left factor into result &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	add	r22,r18 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	adc	r23,r19 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	adc	r24,r20 ; add 0&amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	adc	r25,r21 ; add 0&amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; mul_uw_uw_4: &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; shift the factor y by 1 bit to left&amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	add	r18,r18 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	adc	r19,r19 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	adc	r20,r20 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	adc	r21,r21 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	mov	r16,r26		; no more of right factor left &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	or	r16,r27 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	brne mul_uw_uw_3 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; result is 32 bits in r25:r24:r23:r22 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	pop	r16 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	ret &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
return 0 ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#else&lt;br /&gt;
&lt;br /&gt;
// Hardware multiply MUL&lt;br /&gt;
// input:&lt;br /&gt;
// r23_r22 = x.h_x.l&lt;br /&gt;
// r25_r24 = y.h_y.l&lt;br /&gt;
// may destroy r18 r19 r20 r21 r22 r23 r24* r25* r26* r27*&lt;br /&gt;
// may not destroy r14 r15 r16 r17 r28=YL r29=YH&lt;br /&gt;
// return r25_r24_r23_r22&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
FUNCT slong dummy_mul_uw_uw( sword x , sword y )&lt;br /&gt;
{&lt;br /&gt;
//asm(&amp;quot; .text &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; .global mul_uw_uw&amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; See as well mul_uc_uc : 8 bit by 8 bit, result 16 bits &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Function mul_uw_uw &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; multiply unsigned 16 bit by 16 bit &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Input: &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ;     r23:r22   : The factor &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ;     r25:r24   : The factor &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Results &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ;     r25:r24:r23:r22    : result&amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Destroyed registers &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ;     r18 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; This program is verified by qqarith.asm &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
//asm(&amp;quot; _Z9mul_uw_uwtt: &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot;mul_uw_uw: &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	push r0 ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	push r1 ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	push r16 ; &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; ; Clear start values &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	clr	r16 &amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	mov r20,r22 ; factor x to interim storage &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	mov	r21,r23 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	mov r18,r24 ; factor y to interim storage &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	mov	r19,r25 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
asm(&amp;quot; 	mul	r20,r18 ; low byte * low byte&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	mov	r22,r0 ; low byte of low result word&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	mov	r23,r1 ; high byte of low result word&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	mul	r21,r19 ; high byte * high byte&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	mov	r24,r0 ; high result word&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	mov	r25,r1 ; high result word&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	mul	r20,r19 ; low byte * high byte&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	add	r23,r0 ; medium result word&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	adc	r24,r1 ; medium result word&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	adc	r25,r16 ; carry to highest byte&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	mul	r21,r18 ; low byte * high byte&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	add	r23,r0 ; medium result word&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	adc	r24,r1 ; medium result word&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; 	adc	r25,r16 ; carry to highest byte&amp;quot; &amp;quot;\n&amp;quot; );&lt;br /&gt;
asm(&amp;quot; ; result is 32 bits in r25:r24:r23:r22 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	pop	r16 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	pop	r1 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	pop	r0 &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
asm(&amp;quot; 	ret &amp;quot; &amp;quot;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
return 0 ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Register r1 braucht nicht gerettet werden, muss dann vor der Rückkehr auf 0 gesetzt werden.&lt;/div&gt;</summary>
		<author><name>84.167.184.249</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Festkommaarithmetik&amp;diff=25247</id>
		<title>Festkommaarithmetik</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Festkommaarithmetik&amp;diff=25247"/>
		<updated>2007-12-28T16:11:58Z</updated>

		<summary type="html">&lt;p&gt;84.167.184.249: /* ADC allgemein */  Umwandlung, Rundung und Ausgabe in Einem&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Das Problem ==&lt;br /&gt;
&lt;br /&gt;
Ein immer wiederkehrendes Problem ist die Anzeige von Messwerten per UART/RS232 oder LCD. Die Messwerte werden praktisch immer von [[AD-Wandler]]n oder anderen Sensoren in digitaler Form geliefert. Doch wie wandelt man diese in eine &amp;quot;normale&amp;quot; Anzeige wie z.B. 4,56V um?&lt;br /&gt;
&lt;br /&gt;
Der einfachste Ansatz ist der Einsatz von Gleitkommazahlen. Dabei gilt nahezu immer die Formel&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Eingangsspannung = \frac{ADC \hbox{-} Wert \cdot Referenzspannung}{ 2^{Bitbreite_{ADC}}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Den so errechneten Wert der Eingangsspannung kann man einfach per C-Funktion&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
sprintf(mein_string, &amp;quot;%2.4f&amp;quot;, Eingangsspannung);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
in einen String umwandeln und dann auf ein LCD oder den UART ausgeben.&lt;br /&gt;
&lt;br /&gt;
Soweit so gut. Das Problem ist &amp;quot;nur&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* Das Rechnen mit Gleitkommazahlen ist auf den meisten Mikrocontrollern mit recht viel Rechenzeit sowie Programmspeicher verbunden, da diese keine Befehle zur direkten Verarbeitung von Gleitkommazahlen haben. Alle Rechnungen werden mit Hilfe von Bibliotheksfunktionen nachgebildet.&lt;br /&gt;
* Die Ausgabe von Gleitkommazahlen per sprintf und Konsorten benötigt ebenfalls sehr viel Programmspeicher, da diese Funktionen sehr mächtig und damit umfangreich sind&lt;br /&gt;
&lt;br /&gt;
== Die Lösung ==&lt;br /&gt;
&lt;br /&gt;
Die allerwenigsten Anwendungen benötigen die volle Leistung von Gleitkommazahlen (Dynamikbereich). Wesentlich sinnvoller ist die Anwendung von Festkommazahlen. Diese sind normale Integerzahlen (ganzzahlig ohne Kommastellen), allerdings mit &amp;quot;gedachten&amp;quot; Kommastellen. Wie geht das? Ganz einfach. Anstatt 10,45 kann man auch 1045 schreiben und die beiden letzten Stellen als Nachkommastellen betrachten. 1045 kann man in einer ganz normalen 16 Bit Integervariable speichern. Und auch damit rechnen!&lt;br /&gt;
&lt;br /&gt;
Anstatt nun in Gleitkomma zu schreiben und zu rechnen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U = \frac{756 \cdot 5,0}{1024}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wird geschrieben&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U = \frac{756 \cdot 5000}{1024}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Referenzspannung wird in 1/1000 V (mV) ausgedrückt und damit gerechnet. Das Ergebnis ist eine Spannung in mV. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;B&amp;gt;Wichtig&amp;lt;/B&amp;gt; ist dabei, daß&lt;br /&gt;
&lt;br /&gt;
* erst alle Multiplikationen und dann erst die Divisionen durchgeführt werden, um Rundungsfehler zu minimieren&lt;br /&gt;
* in sämtlichen Zwischenergebnissen keine arithmetischen Überläufe auftreten, also genügend grosse Variablen benutzen (16/32/64 Bit Integer)&lt;br /&gt;
&lt;br /&gt;
Doch wie wird nun diese Zahl in einen darstellbaren String umgewandelt? Im einfachsten Fall durch Verwendung der C-Funktion itoa (Integer to ASCII). Diese ist auf vielen Mikrocontrollern als C-Bibliothek verfügbar. Wenn dies jedoch nicht so sein sollte muss man sie selber schreiben. Und da wir hier etwas lernen wollen, werden wir das auch tun.&lt;br /&gt;
&lt;br /&gt;
== ITOA selbst gemacht ==&lt;br /&gt;
&lt;br /&gt;
Wie funktioniert nun die Umwandlung einer Zahl in einen String? Ganz einfach. Für jede Stelle der Dezimalzahl muss ein ASCII-Zeichen erzeugt werden. Wenn z.B. die Zahl 28943 in einen String gewandelt werden soll muss am Ende der String die ASCII-Codes 0x32, 0x38, 0x39, 0x34, 0x33 und 0x00 (Stringabschlusszeichen, Stringterminator) enthalten. Wie man bei genauem Hinsehen sieht, besteht der ASCII-Code einer Zahl zwischen 0..9 immer aus 0x30 + Zahl. Das ist einfach. Und wie kommt man nun an die einzelnen Ziffern? Dazu wird eine MODULO Operation durchgeführt. Diese liefert den Rest einer ganzzahligen Division.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
28943 MOD 10 =       3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun gehts an die nächste Stelle. Dazu wird die Zahl einfach durch 10 dividiert&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
28943 / 10 = 2894&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und nun das Spiel von vorn.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
2894 MOD 10 =        4&lt;br /&gt;
2894 / 10   = 289&lt;br /&gt;
289 MOD 10  =        9&lt;br /&gt;
289 / 10    = 28&lt;br /&gt;
28 MOD 10   =        8&lt;br /&gt;
28 / 10     = 2&lt;br /&gt;
2 MOD 10    =        2&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das wars eigentlich schon. Beachtet werden muss nur, dass bei dieser Methode die einzelnen Stellen in umgekehrter Reihenfolge entstehen: Die höchstwertigen Stellen kommen erst zum Schluss.&lt;br /&gt;
&lt;br /&gt;
Hier ist nun unsere erste einfache Funktion, um eine vorzeichenlose 32 Bit Zahl in einen String umzuwandeln. Diese kann maximal 10 Dezimalstellen haben (0..4294967295), also wird ein Speicher für 11 Bytes benötigt (letztes Byte für den Stringterminator).  Bei dem Verfahren wird die Zahl rückwärts berechnet. Das muss bei der Ablage im Speicher berücksichtigt werden. Im Sinne der Verständlichkeit wurde bewusst auf Optimierungen und kompakt/kryptische Schreibweisen verzichtet. Der Syntax ist Standard-C und somit auf jedem Compiler nutzbar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
Funktion zur Umwandlung einer vorzeichenlosen 32 Bit Zahl in einen String&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void my_uitoa(uint32_t zahl, char* string) {&lt;br /&gt;
  int8_t i;                             // schleifenzähler&lt;br /&gt;
&lt;br /&gt;
  string[10]=&#039;\0&#039;;                       // String Terminator&lt;br /&gt;
  for(i=9; i&amp;gt;=0; i--) {&lt;br /&gt;
    string[i]=(zahl % 10) +&#039;0&#039;;         // Modulo rechnen, dann den ASCII-Code von &#039;0&#039; addieren&lt;br /&gt;
    zahl /= 10;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion gibt auch führende Nullen aus. Das ist erstmal OK, denn so wissen wir immer wo unser gedachtes Komma ist. Bei der Ausgabe können die führenden Nullen unterdrückt werden. Wie das geht, wird weiter unten beschrieben.&lt;br /&gt;
&lt;br /&gt;
Benötigt man neben der Ausgabe für vorzeichenlose (unsigned) Werte auch noch eine Funktion für vorzeichenbehaftete Werte, so ist auch dieses keine Hexerei. Dazu verwenden wir ein zusätzliches Byte im String um das Vorzeichen zu speichern. Der String muss nun also mindestens 12 Bytes Speicherplatz zur Verfügung stellen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
Funktion zur Umwandlung einer vorzeichenbehafteten 32 Bit Zahl in einen String&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void my_itoa(int32_t zahl, char* string) {&lt;br /&gt;
  uint8_t i;&lt;br /&gt;
&lt;br /&gt;
  string[11]=&#039;\0&#039;;                  // String Terminator&lt;br /&gt;
  if( zahl &amp;lt; 0 ) {                  // ist die Zahl negativ?&lt;br /&gt;
    string[0] = &#039;-&#039;;              &lt;br /&gt;
    zahl = -zahl;&lt;br /&gt;
  }&lt;br /&gt;
  else string[0] = &#039; &#039;;             // Zahl ist positiv&lt;br /&gt;
&lt;br /&gt;
  for(i=10; i&amp;gt;=1; i--) {&lt;br /&gt;
    string[i]=(zahl % 10) +&#039;0&#039;;     // Modulo rechnen, dann den ASCII-Code von &#039;0&#039; addieren&lt;br /&gt;
    zahl /= 10;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Digitaler Temperatursensor ===&lt;br /&gt;
&lt;br /&gt;
Anstatt eines ADC-Wertes werden oft auch Digitalwerte von Temperatursensoren verarbeitet. Der Weg ist hier identisch. Allerdings hat man keine Referenzspannung oder Referenztemperatur. Das ist aber kein Beinbruch. Z.B. der LM74 hat eine Auflösung von 1/16°C = 0,0625°C. Um das Messergebnis ohne Verlust von Auflösung auszugeben könnte man als erstes den Digitalwert auf 1/100 °C umrechnen. Das geschieht mit der Multiplikation mit 6,25. Doch Stop, das ist ja schon wieder ne Gleitkommazahl. Doch kein Problem, wir wissen ja wie wir das Problem lösen. Wir schieben das Komma um zwei Stellen nach rechts und multiplizieren mit 625 und wissen, dass das Ergbniss nun in 1/10000°C vorliegt. Über den physikalischen Sinn dieser Auflösung müssen wir nicht nachdenken, wichtig ist für uns nur, dass jetzt die Zahl einfach per itoa() umwandelbar ist. Allgemein kann man folgenden Ablauf zur Berechnung des Korrekturfaktors angeben&lt;br /&gt;
&lt;br /&gt;
* Den Korrekturfaktur &amp;lt;B&amp;gt;K&amp;lt;/B&amp;gt; mit vollen Kommastellen berechnen, dabei ist die neue Auflösung sinnvollerweise eine Dezimalzahl ( 0,1; 0,001 etc.) und kleiner als die alte Auflösung.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;K  = \frac{alte~Aufloesung}{neue~Aufloesung}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Den berechneten Korrekturfaktor solange mit 10 multiplizieren bis alle Nachkommastellen verschwunden sind bzw. durch Rundung ein akzeptabler Fehler entsteht. Für jede Multiplikation des Faktors mit 10 muss die neue Auflösung durch 10 dividiert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Temperatur = Sensorwert \cdot K&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;B&amp;gt;Beispiel:&amp;lt;/B&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alte Auflösung: 1/32°C&amp;lt;BR&amp;gt;&lt;br /&gt;
Neue Auflösung: 1/100°C&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;K = \frac{\frac{1}{32}}{\frac{1}{100}} = 3,125&amp;lt;/math&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Der Korrekturfaktor 3,125 kann zweimal mit 10 multipliziert werden und dann auf 312 gerundet werden, das entspricht einem Rundungsfehler von gerade mal 1/624 = 0,16% ! Die neue Auflösung beträgt 1/10000°C. Wenn der Sensor nur 7 Bit Werte liefert kann das Ergebnis in einer 16 Bit Variablen gespeichert werden, darüber hinaus ist eine 32 Bit Variable notwendig.&lt;br /&gt;
&lt;br /&gt;
=== ADC allgemein ===&lt;br /&gt;
&lt;br /&gt;
Wenn man das obige ADC-Beispiel allgemein beschreiben will, dann gilt folgender Ablauf&lt;br /&gt;
&lt;br /&gt;
* Korrekturfaktor mit vollen Kommastellen berechnen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;alte Aufloesung = \frac{Referenzspannung}{2^{Bitbreite_{ADC}}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;K  = \frac{alte~Aufloesung}{neue~Aufloesung}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Den berechneten Korrekturfaktor K solange mit 10 multiplizieren bis alle Nachkommastellen verschwunden sind bzw. durch Rundung ein akzeptabler Fehler entsteht. Für jede Multiplikation des Faktors mit 10 muss die neue Auflösung durch 10 dividiert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;Eingangsspannung = ADC \hbox{-} Wert \cdot K&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;B&amp;gt;Beispiel:&amp;lt;/B&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Referenzspannung : 5V&amp;lt;BR&amp;gt;&lt;br /&gt;
ADC Bitbreite : 10&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;alte Aufloesung = \frac{5V}{2^{10}} = \frac{5}{1024} = 0,0048828125\,V&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
neue Auflösung:  0,001 V = 1mV&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;K = \frac{0,0048828125 V}{0,001V} = 4,8828125&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Korrekturfaktor 4,8828125 wird zweimal mit 10 multipliziert und dann auf 488 gerundet, das entspricht einem Rundungsfehler von gerade mal 0,05% ! Die neue Auflösung ist 0,00001 V = 10uV. Das Ergebnis muss in einer 32 Bit Variablen gespeichert werden, denn der grösste Messwert ergibt 1023*488 = 499224. Der Vorteil dieses allgemeinen Ansatzes ist vor allem, daß nur eine Multiplikation benötigt wird, im Gegensatz zu unserem allerersten Beispiel, welches eine Multiplikation und eine Division benötigt. Das spart einiges an Rechenzeit und Programmspeicherplatz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Für die Ausgabe der ADC-Spannung eignet sich folgendes Unterprogramm nach [[User:HJHerbert]]:&lt;br /&gt;
&lt;br /&gt;
 ulong round[5] = &lt;br /&gt;
 	{&lt;br /&gt;
 	65536L/2/1 ,&lt;br /&gt;
 	65536L/2/10 ,&lt;br /&gt;
 	65536L/2/100 ,&lt;br /&gt;
 	65536L/2/1000 ,&lt;br /&gt;
 	65536L/2/10000 &lt;br /&gt;
 	} ;&lt;br /&gt;
 &lt;br /&gt;
 void out_uwfx( &lt;br /&gt;
 		uword w,		// Der ADC-Wert, linksbuendig&lt;br /&gt;
                                         // 0xffff = 0.999999, 0x8000 = 0.500 &lt;br /&gt;
 		uword prec,		// Anzahl der Nachkommastellen&lt;br /&gt;
 		uword n )		// Der Wert, den w=(0xffff+1) repräsentiert&lt;br /&gt;
 {&lt;br /&gt;
 ulong ul ;&lt;br /&gt;
 uword teil ;&lt;br /&gt;
 uword x ;&lt;br /&gt;
 uchar i ; &lt;br /&gt;
&lt;br /&gt;
 ul = mul_uw_uw(w, n);&lt;br /&gt;
 if ( prec &amp;lt; 5 )&lt;br /&gt;
 	{&lt;br /&gt;
 	ul += round[prec] ;&lt;br /&gt;
 	}&lt;br /&gt;
 x = (uword)(ul &amp;gt;&amp;gt; 16) ;&lt;br /&gt;
 teil = (uword)ul ;&lt;br /&gt;
 out_uint16( x );			// Anzeige des ganzzahligen Teils&lt;br /&gt;
 out_char( &#039;.&#039; );&lt;br /&gt;
 for ( i = 0 ; i &amp;lt; prec ; ++i )&lt;br /&gt;
 	{&lt;br /&gt;
 	ul = mul_uw_uw(teil, 10);&lt;br /&gt;
 	x = (uword)(ul &amp;gt;&amp;gt; 16) ;&lt;br /&gt;
 	teil = (uword)ul ;		// Der Ueberlauf wurde schon angezeigt&lt;br /&gt;
 	out_char( x + &#039;0&#039; );	        // noch eine Nachkommastelle&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Dieses Ausgabeprogramm kann dann so aufgerufen werden:&lt;br /&gt;
&lt;br /&gt;
 out_puts( &amp;quot; B=&amp;quot; );&lt;br /&gt;
 out_uwfx( 756&amp;lt;&amp;lt;6, 4, 1 );	// with rounding 756/1024 = 0.73828125&lt;br /&gt;
 out_puts( &amp;quot; C=&amp;quot; );&lt;br /&gt;
 out_uwfx( 756&amp;lt;&amp;lt;6, 4, 5 );	// output unsigned fixed point number 756*5/1024 = 3.69140625&lt;br /&gt;
 out_nl();&lt;br /&gt;
&lt;br /&gt;
Damit wird angezeigt:  B=0.7383 C=3.6914&lt;br /&gt;
&lt;br /&gt;
Hinweis: Um 6 Bits nach links wird geschoben, weil der maximale ADC-Wert 1023 ist und 10 Bits hat. Nach dem Linksschieben ist der code in den oberen 10 Bits des 16-Bit-Wortes.&lt;br /&gt;
&lt;br /&gt;
Die hierbei verwendeten Unterprogramme sind:&lt;br /&gt;
* out_uint16( uword x ) // Ausgabe einer ganzen Zahl&lt;br /&gt;
* mul_uw_uw( uword a, uword b) // 32-Bit-Ergebnis einer 16bit x 16bit Multiplikation, siehe [[muluwuw]]&lt;br /&gt;
&lt;br /&gt;
== Ergebnis runden ==&lt;br /&gt;
&lt;br /&gt;
Nach der Umrechung des ADC/Sensor-Wertes und dem Aufruf von my_uitoa() kann man sehr einfach eine Rundung durchführen. Dazu muss nur die erste Stelle, welche durch Rundung wegfallen soll, geprüft werden. Ist sie kleiner als der ASCII-Code von &#039;5&#039; (0x35) dann muss abgerundet werden, sprich alles bleibt wie es ist. Im anderen Fall muss aufgerundet werden, was bedeutet dass die letzte angezeigte Dezimalstelle um eins erhöht werden muss. Doch aufgepasst! Wenn z.B. in unserem String die Zahl 1995 steht und die letzte Stelle durch Rundung wegfallen soll, kommte es zum Übertrag. Die letzte 9 wird zur 0 + Übertrag. Die nächste linksstehende Stelle muss erhöht werden. Das ist &amp;quot;dummerweise&amp;quot; auch eine 9, also wieder ein Übertrag. Die letzte Ziffer ist 1, die wird nur auf zwei erhöht und der Übertrag endet.&lt;br /&gt;
&lt;br /&gt;
Basierend auf unserer Funktion my_uitoa() soll hier eine einfache Rundungsfunktion gezeigt werden. Auch diese arbeitet mit einem 11 Byte String, welcher vorher durch my_uitoa erzeugt wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
Funktion zur Rundung einer vorzeichenlosen 32 Bit Zahl im Stringformat&lt;br /&gt;
&lt;br /&gt;
Parameter:&lt;br /&gt;
&lt;br /&gt;
char* string:  Zeiger auf String, welcher mit my_uitoa() erzeugt wurde&lt;br /&gt;
uint8_t digit: Offset im String, zeigt auf die Stelle welche zur Rundung ausgewertet werden soll&lt;br /&gt;
               gültiger Wertebereich ist 1..9 !&lt;br /&gt;
               Der Offset von 1 zeigt auf die zweite Stelle von links&lt;br /&gt;
               Der Offset von 9 zeigt auf die letzte Stelle von links&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void my_round(char* string, uint8_t digit) {&lt;br /&gt;
  uint8_t i;&lt;br /&gt;
&lt;br /&gt;
  if (string[digit]&amp;gt;=&#039;5&#039;) {         // Aufrunden?&lt;br /&gt;
    for(i=(digit-1); i&amp;gt;=0; i--) {&lt;br /&gt;
      string[i] += 1;               // Aufrunden&lt;br /&gt;
      if (string[i]&amp;lt;=&#039;9&#039;)&lt;br /&gt;
        break;                      // kein Übertrag, schleife verlassen&lt;br /&gt;
      else&lt;br /&gt;
        string[i]=&#039;0&#039;;              // Übertrag und Überlauf&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  for(i=digit; i&amp;lt;10; i++) string[i] =&#039;0&#039;;   // gerundete Stellen auf Null setzen&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion ist auch auf einen String anwendbar, welcher mit my_itoa() erzeugt wurde (also vorzeichenbehaftete Zahlen). Allerdings muss der Funktion ein Pointer auf das zweite Byte (char) übergeben werden, da im ersten das Vorzeichen gespeichert ist. Das geschieht am einfachsten so.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
my_round(my_sting+1, 5);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ergebnis ausgeben ==&lt;br /&gt;
&lt;br /&gt;
Nun haben wir unseren Messwert in eine Zahl mit der richtigen Einheit umgewandelt und gerundet. Jetzt folgt der letzte Schritt, die Ausgabe auf einen UART oder LCD. Dazu ist es meist wünschenswert führende Nullen nicht anzuzeigen. Also anstatt 0095,89 will man 95,89 ausgeben. Bei negativen Zahlen kommt noch das Vorzeichen hinzu.&lt;br /&gt;
&lt;br /&gt;
=== Ausgabe auf LCD (HD44780 &amp;amp; CO) ===&lt;br /&gt;
&lt;br /&gt;
Zunächst wollen wir unsere Zahl auf einem LCD ausgeben. Dazu braucht man die entsprechende Funktion lcd_data(), wie sie z.B. im [[AVR-GCC-Tutorial#LCD_Ansteuerung]] zu finden ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
Funktion zur Anzeige einer 32 Bit Zahl im Stringformat&lt;br /&gt;
auf einem LCD mit HD44780 Controller&lt;br /&gt;
&lt;br /&gt;
Parameter:&lt;br /&gt;
&lt;br /&gt;
char* string  : Zeiger auf String, welcher mit my_itoa() erzeugt wurde&lt;br /&gt;
uint8_t start : Offset im String, ab der die Zahl ausgegeben werden soll,&lt;br /&gt;
                das ist notwenig wenn Zahlen mit begrenztem Zahlenbereich&lt;br /&gt;
                ausgegeben werden sollen&lt;br /&gt;
                Vorzeichenlose Zahlen      : 0..10&lt;br /&gt;
                Vorzeichenbehaftete zahlen : 1..11&lt;br /&gt;
uint8_t komma : Offset im String, zeigt auf die Stelle an welcher das virtuelle&lt;br /&gt;
                Komma steht (erste Nachkommastelle)&lt;br /&gt;
                komma muss immer grösser oder gleich start sein !&lt;br /&gt;
&lt;br /&gt;
uint8_t frac  : Anzahl der Nachkommastellen&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void my_print_LCD(char* string, uint8_t start, uint8_t komma, uint8_t frac) {&lt;br /&gt;
&lt;br /&gt;
  uint8_t i;            // Zähler&lt;br /&gt;
  uint8_t flag=0;       // Merker für führende Nullen&lt;br /&gt;
&lt;br /&gt;
  // Vorzeichen ausgeben  &lt;br /&gt;
  if (string[0]==&#039;-&#039;) lcd_data(&#039;-&#039;); else lcd_data(&#039; &#039;);&lt;br /&gt;
&lt;br /&gt;
  // Vorkommastellen ohne führende Nullen ausgeben&lt;br /&gt;
  for(i=start; i&amp;lt;komma; i++) {&lt;br /&gt;
    if (flag==1 || string[i]!=&#039;0&#039;) {&lt;br /&gt;
      lcd_data(string[i]);&lt;br /&gt;
      flag = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else lcd_data(&#039; &#039;);         // Leerzeichen&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  lcd_data(&#039;,&#039;);                // Komma ausgeben&lt;br /&gt;
&lt;br /&gt;
  // Nachkommastellen ausgeben&lt;br /&gt;
  for(; i&amp;lt;(komma+frac); i++) lcd_data(string[i]);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion gibt zunächst das Vorzeichen aus, das ist einfach. Danach werden die Vorkommastellen ausgegeben. Aber es wird nur dann ein Zeichen ausgegeben, wenn vorher schon mal eins ausgegeben wurde (flag ==1) oder das aktuelle Zeichen keine &#039;0&#039; ist. Danach werden ganz normal die Nachkommastellen ausgegeben, hier ist eine Unterdrückung führender Nullen sogar mathematisch falsch!&lt;br /&gt;
&lt;br /&gt;
Genutzt wird die Funktion beispielsweise so, um dreistellige Zahlen bis 999 mit zwei Nachkommastellen auszugeben. Die Zahl selber hat sechs Nachkommastellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
char my_string[12]=&amp;quot;-0034567891\0&amp;quot;;&lt;br /&gt;
my_print_LCD(my_string, 2, 5, 2);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf dem LCD erscheint dann &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
- 34.56&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion kann auch verwendet werden, um vorzeichenlose Zahlen auszugeben, welche mit my_uitoa() erzeugt wurden. Da an der ersten Stelle nie ein &#039;-&#039; steht, wird auch nie ein &#039;-&#039; ausgegeben.&lt;br /&gt;
&lt;br /&gt;
=== Ausgabe auf UART ===&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe auf einen UART ist nahezu identisch. Auch hier braucht man eine Funktion putc(), welche ein einzelnes Zeichen auf den UART schreiben kann wie z.B. im [[AVR-Tutorial:UART:GCC]] beschrieben ist. Der Unterschied zur LCD-Ausgabe besteht darin, dass zwischen dem Vorzeichen und der Zahl keinerlei Leerzeichen eingefügt werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
&lt;br /&gt;
Funktion zur Ausgabe einer 32 Bit Zahl im Stringformat&lt;br /&gt;
auf den UART&lt;br /&gt;
&lt;br /&gt;
Parameter:&lt;br /&gt;
&lt;br /&gt;
char* string  : Zeiger auf String, welcher mit my_itoa() erzeugt wurde&lt;br /&gt;
uint8_t start : Offset im String, ab der die Zahl ausgegeben werden soll,&lt;br /&gt;
                das ist notwenig wenn Zahlen mit begrenztem Zahlenbereich&lt;br /&gt;
                ausgegeben werden sollen&lt;br /&gt;
                Vorzeichenlose Zahlen      : 0..10&lt;br /&gt;
                Vorzeichenbehaftete zahlen : 1..11&lt;br /&gt;
uint8_t komma : Offset im String, zeigt auf die Stelle an welcher das virtuelle&lt;br /&gt;
                Komma steht (erste Nachkommastelle);&lt;br /&gt;
                komma muss immer grösser oder gleich start sein !&lt;br /&gt;
&lt;br /&gt;
uint8_t frac  : Anzahl der Nachkommastellen&lt;br /&gt;
&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void my_print_UART(char* string, uint8_t start, uint8_t komma, uint8_t frac) {&lt;br /&gt;
&lt;br /&gt;
  uint8_t i;            // Zähler&lt;br /&gt;
  uint8_t flag=0;       // Merker für führende Nullen&lt;br /&gt;
&lt;br /&gt;
  // Vorkommastellen ohne führende Nullen ausgeben&lt;br /&gt;
  for(i=start; i&amp;lt;komma; i++) {&lt;br /&gt;
    if (flag==1 || string[i]!=&#039;0&#039;) {&lt;br /&gt;
      if (flag==0 &amp;amp;&amp;amp; string[0]==&#039;-&#039;) putc(&#039;-&#039;);     // negatives Vorzeichen ausgeben&lt;br /&gt;
      putc(string[i]);&lt;br /&gt;
      flag = 1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  putc(&#039;,&#039;);                // Komma ausgeben&lt;br /&gt;
&lt;br /&gt;
  // Nachkommastellen ausgeben&lt;br /&gt;
  for(; i&amp;lt;(komma+frac); i++) putc(string[i]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion kann auch verwendet werden, um vorzeichenlose Strings auszugeben, welche mit my_uitoa() erzeugt wurden. Da an der ersten Stelle nie ein &#039;-&#039; steht, wird auch nie ein &#039;-&#039; ausgegeben.&lt;/div&gt;</summary>
		<author><name>84.167.184.249</name></author>
	</entry>
</feed>