Forum: Mikrocontroller und Digitale Elektronik Variablengröße bei Berechnung


von Maddin (Gast)


Lesenswert?

Ich habe eine 16bit Variable "receivebuffer" und will mit dieser 
folgende Berechung durchführen.

A=(receivebuffer*200)/2047

Der maximale Wert für A ist also 200 und belegt somit nur ein Byte. Bei 
der multiplikation mit 200 übersteigt der sich in diesem Fall ergebene 
Zwischenwert die 16Bit. Ist das für den verwendeten IAR C/C++ Compiler 
kritisch? Gehen mir dabei Werte verloren? Oder muss ich für A zuerst 
mehr als 16bit reservieren? Kann ich ja später wieder auf 8Bit 
maskieren.

Gruß

Maddin

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:

> Der maximale Wert für A ist also 200 und belegt somit nur ein Byte

uninteressant

> Bei
> der multiplikation mit 200 übersteigt der sich in diesem Fall ergebene
> Zwischenwert die 16Bit.

Das ist ein Problem

> Ist das für den verwendeten IAR C/C++ Compiler
> kritisch?

Nicht nur für den.

> Gehen mir dabei Werte verloren?

Ja

> Oder muss ich für A zuerst
> mehr als 16bit reservieren?

Das spielt keine Rolle.
Bei der Wahl der Operation spielt es keine Rolle was mit dem Ergebnis 
weiter passiert. Einzig die beteiligten Operanden bestimmen wie die 
Operation durchgeführt wird.

receivebuffer ist ein int
200 ist ein int

also wird da eine int*int Multiplikation durchgeführt. Und die sollte 
besser nicht überlaufen.

http://www.mikrocontroller.net/articles/FAQ#Datentypen_in_Operationen

von H.Joachim S. (crazyhorse)


Lesenswert?

A=((long)receivebuffer*200)/2047

sollte funktionieren. Die Berechnung wird mit long gemacht, 
anschliessend auf char zugewiesen.
Gibt ne Warnung, aber wenn du dir sicher bist...

von Maddin (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
>> Oder muss ich für A zuerst
>> mehr als 16bit reservieren?
>
> Das spielt keine Rolle.

Und wenn ich vorher receivebuffer als Datentyp long festlege? Dann hauts 
doch hin oder?

Oder gleich so wie Herr Seifert meinte.

von Matthias L. (Gast)


Lesenswert?

Lass mich mal orakeln:

Das ist ne Berechnung für einen ADC. Der Wert A kommt von nem 11bit 
Wandler und du willst die Größe normieren?

Stimmts? Wenn ja, behaupte ich mal, das statt der 2047 eine 2048 hin 
muss.

von Maddin (Gast)


Lesenswert?

Matthias Lipinsky schrieb:
> Das ist ne Berechnung für einen ADC. Der Wert A kommt von nem 11bit
> Wandler und du willst die Größe normieren?

nöö

> Stimmts? Wenn ja, behaupte ich mal, das statt der 2047 eine 2048 hin
> muss.

nöö

Willst weiter raten oder soll ich dich aufklären? ;)

von Matthias L. (Gast)


Lesenswert?

>Willst weiter raten oder soll ich dich aufklären? ;)

Ich bitte darum..

von H.Joachim S. (crazyhorse)


Lesenswert?

11-bit-Wandler? Noch nie gesehen :-)

von Maddin (Gast)


Lesenswert?

Es handelt sich dabei um den TSIC306. Ein genauer Temperatursensor mit 
einer Auflösung von 0.1°C. Dieser gibt die Temperatur (je nach Modell) 
per 11Bit Wert aus. Das Protokoll ist relativ einfach aufgebaut. 
2Packete mit je 8Bit und Parität. Du hast also nicht ganz unrecht mit 
ADC. Schließlich wird da irgendwo etwas analog-dital gewandelt.

Motivation wars für mich endlich mal eine vertrauenswürdige 
Temperaturangabe zu erhalten. Auf meine, Schreibtisch steht son 
noname-Wecker mit Temp-anzeige. Der interne ADC mit Temp-Sensor des 
MSP430 stimmte mich auch nie zufrieden, deshalb hab ich mir den 
arschteuren TSIC306 angeschafft.
Das beste ist aber die breits erwähnte Auflösung von 0.1°C. Und nachdem 
ich es nun geschafft habe die nachkommastelle bei der Berechnung zu 
retten und diese ber UART sicher (dank eurer Hilfe) mit HTERM 
auszulesen, freuh ich mich wie Bolle.

Gruß

Maddin

von Matthias L. (Gast)


Lesenswert?

also wird wohl doch eine 2048 da hin gehören...

von Maddin (Gast)


Lesenswert?

Matthias Lipinsky schrieb:
> also wird wohl doch eine 2048 da hin gehören...

nöö

von ... ... ... (Gast)


Lesenswert?

Matthias Lipinsky schrieb:
> also wird wohl doch eine 2048 da hin gehören...
Gibt es zu diesem Thema immer noch keinen Eintrag in der µc.net-FAQ? 
Wird glaube ich Zeit, am besten mit kompletter Threadliste, in denen das 
schon durchgekaut wurde... ;-)

Ach ja, laut diesem pdf, stimmt 2047...
Beitrag "Re: Temperatursensor TSIC 306 TO92"

von Maddin (Gast)


Lesenswert?

... ... ... schrieb:
> Ach ja, laut diesem pdf, stimmt 2047...
> Beitrag "Re: Temperatursensor TSIC 306 TO92"

Nich ohne Grund sag ichs die ganze Zeit. Aber wenn jemand begründeter 
Weise das Datenblatt kritisiert....

von Karl H. (kbuchegg)


Lesenswert?

Das heisst nicht viel.
Auch Datenblätter sind in diesem Punkt schon falsch gewesen.


Höchst wahrscheinlich ist 2048 tatsächlich richtig :-)
Die Begründung ist analog zu der hier

http://www.mikrocontroller.net/articles/AVR-Tutorial:_ADC#Ein_paar_ADC-Grundlagen

und der SChlüssel zum Verständnis besteht darin, zu akzeptieren, dass 
dir der ADC nicht mitteilt: die SPannung ist so und so hoch.
Sondern er teilt dir mit: Die Messspannung ist größer gleich dem Wert x 
und sie ist kleiner gleich dem Wert y. Der ADC sagt dir also in welchem 
Bereich sich die Spannung bewegt. Und mit 11 Bit gibt es nun mal 2048 
Bereiche, in denen sich die Spannung bewegen kann.

Mit kleineren Zahlen (zb einem 3 Bit ADC) wird es besser ersichtlich, 
warum man eigentlich duch 2 hoch n dividieren müsste, warum man statt 
dessen aber auch mit 2 hoch (n-1) dividieren kann und was die 
Unterschiede dabei sind.
Und ich rede jetzt nicht davon, dass sich ein µC bei einer Division 
durch 2048 leichter tut als bei einer Div. durch 2047.

Es sieht nun einmal Scheisse aus, wenn auf deinem Messgerät mit einem 
3Bit ADC und einer Referenzspannung von 8V beim Anlegen von 8V auf der 
Anzeige 7V steht. Auch wenn es technisch korrekt ist, denn der ADC hat 
dir korrekterweise gesagt, dass die zu messende Spannung sich im Bereich 
7V bis 8V bewegt.

von Maddin (Gast)


Lesenswert?

Ja das ist ja eigentlich alles klar Herr Buchegger, aber was ist wenn 
bei der Umrechnung in eine entsprechende Temperatur ein derartiger Drift 
vorliegt, dass dieser von Seiten der Entwickler durch eine Änderung der 
Übertragungsfunktion (Anstieg) korrigiert wird.
Es geht ja hier nicht um die Frage in welchem Bereich der Temperatur ADC 
eine Spannung misst sondern inwievern Temperaturänderungen sich auf den 
gemessenen Wert auswirken.
Sie nehmen ja stillschweigend an die Messung einer Temperatur geschieht 
genauso wie das anlegen einer Spannung. Irgendwo muss ja noch etwas 
zwischen Temperaturgröße und ADC-Inputgröße sein. Sowas wie ein 
Kaltleiter oder Heißleiter.

Oder?

Gruß

Maddin

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:

Ich seh jetzt ehrlich den Zusammenhang nicht.
Es geht doch schlicht darum, dass ein Wert von 2047 (also das Maximum) 
eben nicht bedeutet, dass die zu messende Größe exakt auf dem Maximum 
ist. Sondern es geht darum, dass dir dieser Messwert nur mitteilt, dass 
sich die Messgröße irgendwo im letzten Messintervall befindet.

In der Praxis ist das bei genügend großer Auflösung ziemlich irrelevent, 
geb ich schon zu. Da wird der Messfehler schon höher sein, bzw. wir 
reden hier bei einem einem Deltamesswert von 1 um eine 
Temperaturdifferenz von ein paar Hunderstel (wenn überhaupt) Grad.

Wenn es aber sowieso irrelevant ist, dann kann man auch richtigerweise 
durch 2048 dividieren.
Also Folge davon kann mann dann die Umrechnung

    Wert * 200 / 2048

kürzen auf

    Wert * 50 / 512

und kommt plötzlich mit int Rechnerei über die Runde :-)

von Maddin (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Sondern es geht darum, dass dir dieser Messwert nur mitteilt, dass
> sich die Messgröße irgendwo im letzten Messintervall befindet.

Bestreitet ja auch niemand. Ich würde gern nur bestätigt haben (und das 
ist schwierig), ob sich nun die 2074 anstatt der 2048 auf Grund der 
Unwissenheit der Autoren in die Doku geschlichen haben ODER ob 
vielleicht mit voller Absicht 2047 anstatt 2048 verwendet werden um 
Fehler/Nichtlinearitäten in der Übertragungsfunktion Temperatur - 
Messwert des ADC - digitaler Wert auszugleichen... ??

von ... ... ... (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Das heisst nicht viel.
> Auch Datenblätter sind in diesem Punkt schon falsch gewesen.
> Höchst wahrscheinlich ist 2048 tatsächlich richtig
Ich finde 2048 auch logischer, gibt ja auch genug Datenblätter wo 2048 
drinsteht bzw. damals waren es 4096. Es ist mir nur aufgefallen. ;-)
Hier kann man Maddin also nicht soviel vorwerfen, außer vielleicht der 
Ton. ;-)

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:

> vielleicht mit voller Absicht 2047 anstatt 2048 verwendet werden um
> Fehler/Nichtlinearitäten in der Übertragungsfunktion Temperatur -
> Messwert des ADC - digitaler Wert auszugleichen... ??

Wie willst du denn da Nichtlinearitäten ausgleichen?

Ob 2047 oder 2048, die Umrechnung ist und bleibt eine lineare Gleichung. 
Wenn Nichtlinearitäten ausgeglichen werden müssen, dann hat man es immer 
mit einer nicht-linearen-Gleichung zu tun.

Die Kurve, die die Abhängigkeit des tatsächlichen Messwerts von der zu 
messenden Größe beschreibt ist dann keine Gerade sondern irgendwie 
gebogen. Die Formel wird dann so gewählt, dass die sie diesen Bogen 
wieder geradebiegt.

von Maddin (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Die Formel wird dann so gewählt, dass die sie diesen Bogen
> wieder geradebiegt.

Ja und ich frage, ob es dies mit 2047 vielleicht besser als mit 2048 
tut....

von Karl H. (kbuchegg)


Lesenswert?

Du hörst nicht zu.

Mit einer linearen Gleichung kann man keinen gebogenen Funktionsgraphen 
geradebiegen. Daher kann 2047 versus 2048 nichts mit einer Begradigung 
einer Funktion (vulgo Linearisieren eines nichtlinearen Zusammenhangs) 
zu tun haben. Warum? Weil das nur ein Parameter in einer linearen 
Umrechnung ist. Wenn es um das Bereigen von Nichtlinearitäten gehen 
würde, dann müsste die Umrechnungsformel komplett anders aussehen.

von Maddin (Gast)


Lesenswert?

Nein das verstehe ich wirklich nicht. Man nehme eine gebogene Funktion 
und nähere sie mit einer linearen Funktion an 2 Punkten an. Wo ist da 
das Problem? Für den linearen Teil der gebogenen Funktion wird das dann 
doch sehr gut hinhauen.
Des Weiteren Sie sagten, es liege hier eine gebogene Funktion vor. Laut 
Datenblatt wird die Temperatur mit Hilfe einer linearen Funktion 
berechnet. Nach ihrem letzten Post ist aber gerade dies unmöglich.
Das verstehe ich wirklich nicht.

Gruß

Maddin

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:
> Nein das verstehe ich wirklich nicht. Man nehme eine gebogene Funktion
> und nähere sie mit einer linearen Funktion an 2 Punkten an.

Das hat dann aber nichts mehr mit Linearisieren einer Nichtlinearen 
Funktion zu tun.
Das ist einfach nur lineare Interpolation.


> Des Weiteren Sie sagten,

meinst du mich?

Wenns recht ist, sind wir per Du.

> es liege hier eine gebogene Funktion vor.

Ich sagte das nicht.
Du sagtest, ob die 2047 wohl aus irgendwelchen 
Linearisierungsbestrebungen resultieren würden? Und ich hab argumentiert 
warum das nicht sein kann.

> Laut
> Datenblatt wird die Temperatur mit Hilfe einer linearen Funktion
> berechnet.

Dann ist es ja gut.

> Nach ihrem letzten Post ist aber gerade dies unmöglich.

Nicht wirklich.

Ich habe eine Hypothese getroffen:
Unter der Annahme, dass der Zusammenhang eben keine Gerade wäre sondern 
irgendeine gebogene Funktion .... könnten dann die 2047 (anstelle der 
2048) daher rühren, dass man diese gebogene Funktion gerade biegen 
möchte.

Und die Antwort darauf ist: nein.
Ob 2047 oder 2048 macht keinen Unterschied in dieser Beziehung. Nur 
durch ändern dieses Zahlenwertes kann man nicht eine gebogene Funktion 
begradigen. Das würde nur dann gehen, wenn der Hersteller etwas anderes 
als einen lineare Formel zur Umrechnung vorschreibt. Da er das aber 
nicht tut, gibt es da auch keinen Zusammenhang mit den 2047

Jetzt klarer?

von Matthias L. (Gast)


Lesenswert?

Man, da hab ich ja wieder was angezettelt hier ;-)

von Maddin (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ich habe eine Hypothese getroffen:

Ja sorry, das hatte ich in der Schnelle überlesen.

> Jetzt klarer?

Was die Linearisierung angeht schon. Nur immer noch unbefriedigt was die 
2048 angeht. Da prallen wohl Welten aufeinander. Und so lange sich der 
Autor des Datenblattes hier nicht über die 2047 rechtfertigen kann nehem 
ich die mal so an.
Trotzdem stimmt der Sachverhalt natürlich, dass man beim Berechnen der 
Bereichspannung immer 1 zum Maximalwert des digitalen Wertes addiert.


Gruß

Maddin

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:
> Karl heinz Buchegger schrieb:
>> Ich habe eine Hypothese getroffen:
>
> Ja sorry, das hatte ich in der Schnelle überlesen.
>
>> Jetzt klarer?
>
> Was die Linearisierung angeht schon. Nur immer noch unbefriedigt was die
> 2048 angeht. Da prallen wohl Welten aufeinander. Und so lange sich der
> Autor des Datenblattes hier nicht über die 2047 rechtfertigen kann nehem
> ich die mal so an.

Kannst du auch.
Denn: In der Praxis ist das eine akademische Frage :-)
probiers mit kleineren Werten aus. Du wirst (fast) dieselben Werte 
erhalten. Bei 2047 versus 2048 und einem Zielbereich 0..200 sowieso. Da 
ist der Unterschied irgendwo in der 3. Nachkommastelle und damit völlig 
uninteressant (solange er nicht dazu führt, dass aus 2.99 auf der 
Anzeige eine glatte 3.0 wird und damit bei Anzeige von nur dem 
ganzzahligen Anteil in dem einen Fall eine 2 und im anderen Fall eine 3 
auf der Anzeige steht)

Was jedoch nicht akademisch ist:
Um durch 2047 dividieren zu können, muss eine echte Division 
durchgeführt werden. Bei 2048 reicht Bitschieben.
Und in deinem speziellen Fall natürlich auch noch, dass du durch die 
2048 im Bruch Kürzungsmöglichkeiten bekommst, die dir die ganze 
Berechnung aus dem Zahlenraum long in den Zahlenraum int drücken.
Gut, bei einem Thermometer ist auch das wahrscheinlich nicht das große 
Problem.

von max (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Da
> ist der Unterschied irgendwo in der 3. Nachkommastelle und damit völlig
> uninteressant

Warscheinlich hat der Sensor auch ein Error von 1 LSB, somit ist das 
eigentlich egal, oder?


Karl heinz Buchegger schrieb:
> kürzen auf
>
>     Wert * 50 / 512

2047 kann man aber nicht kürzen (wobei 2048 auch kein Problem sein 
sollte, siehe erster Absatz).

Aber nur aus interesse.. kann man nicht

A = (Wert / 2047) * 200

schreiben???

von H.Joachim S. (crazyhorse)


Lesenswert?

mit float-Zahlen wäre das kein Problem, mit Integer-Berechnung verlierst 
du damit jede Menge Genauigkeit.
Durchdenke es mal, oder kloppe es mal in Excel ein :-)

von Karl H. (kbuchegg)


Lesenswert?

max schrieb:

>> kürzen auf
>>
>>     Wert * 50 / 512
>
> 2047 kann man aber nicht kürzen

Eben.
Aber mit 2048 kann man kürzen :-)

Man kann sogar noch weiter kürzen   Wert * 25 / 256
Was dann (ja nach Compiler) noch besser ist, weil hier noch
nicht mal geschoben werden braucht, sondern einfach nur das LSB
weggeschmissen wird und das HSB zum Ergebnis erklärt wird.


> Aber nur aus interesse.. kann man nicht
>
> A = (Wert / 2047) * 200
>
> schreiben???

können tut man schon.
:-)

'Wert' kann welche Werte annehmen?
'Wert' hat welchen Datentyp
Was ergibt daher  Wert / 2047

(immer 0; es sei denn Wert ist 2047, dann kommt 1 raus)

von max (Gast)


Lesenswert?

ach jaa.. da hab ich wohl nicht an int gedacht^^ tut mir sorry

von Rechner (Gast)


Lesenswert?

Ist ne ünschöne Variante sollte aber auch gehen

mit ints ..
 tempi=0;
 tempt=0;
 tempe=0;
 tempf=0;
 tempg=0;
 temph=0;

 temperatur_roh=temperatur; //755
 tempi=temperatur*20;     // 15100
 tempt=tempi/2047;       // 15100/2047=7
 tempe=(tempt*2047);     // 14239
 tempf=tempi-tempe;      // 771
 tempf=tempf*10;      // 7710
 tempf=tempf/2047;      //7710/2047=3
 tempg=(tempt*2047)+(tempf*2047)/10;  //14943
 temph=tempi-tempg;      // 157
 temph=temph*100;      //15700
 temph=temph/2047;
 temperatur=tempt*100+tempf*10+temph;
 temperatur=temperatur-500;

von Maddin (Gast)


Lesenswert?

Ich sprach ja bereits davon die Nachkommastelle ebenfalls zu berechnen. 
Zur Zeit mache ich das so:
1
tempCv = (((uint32)receivebuffer*200)/2047) - 50; //Vorkommstellen
2
tempCn = ((uint32)receivebuffer*200); //erster Schritt für Nachkommastelle
3
while (tempCn/2047) tempCn = tempCn - 2047;  //ziehe solange 2047 ab bis 2047 nicht mehr vollständig in den Wert passt (die Division durch 2047 also 0), Vorkommstellen fliegen somit raus
4
5
tempCn = (tempCn * 10)/2047; //Nachkommastelle berechnen, tempCn nun zwischen 0 und 9
6
7
ausgabe von tempCv und tempCn

Ist das gut so? Lässt sich die Laufzeit verkürzen?

von Karl H. (kbuchegg)


Lesenswert?

Wenn du hier

tempCv = (((uint32)receivebuffer*200)/2047) - 50; //Vorkommstellen

sowieso auf 32 Bit Arithmetik ausweichst, dann kanst du auch gleich
1
  uint32_t Degrees = ( receivebuffer * 2000UL ) / 2047;
2
3
  tempCv = Degrees / 10;
4
  tempCn = Degrees % 10;

rechnen.
Ist einfacher und bei dem was du da rumrechnest wahrscheinlich auch 
nicht langsamer.

Edit: Es ist mit Sicherheit nicht langsamer. So langsam kann der gcc 32 
Bit Divisionen gar nicht implementieren.

von Horst H. (horha)


Lesenswert?

Hallo,

dieses
1/(K-1) = 1/K +1/K^2+1/K^3+...
Messwert/(K-1) = m*(1/K +1/K^2+1/K^3+..1/K^n)

mit K=2048  und Messwert = 2047
2047/2047 ~ 2047/2048+ 2047/2048 /2048

1 ~ 0,99511718+0,000488042=0,999999761
Dann ist die Abweichung im Bereich von 1/2048^2 < 1e-6

Also würde ich den Messwert*200 / 2048= Messwert*25 / 256 
teilen/schieben

Also nur *25, diesen Intwert kopieren um 3 bit(=11-8 )  nach rechts 
schieben.
Darauf dann 4 zum runden addieren
1
wert = 25*Tsic_Wert; // Tsic_Wert = 2047 wert = 51175
2
temp = wert;         // temp = 51175  wert = 51175
3
temp = temp >>3;     // temp =  6396  wert = 51175   //  / 8 
4
temp = temp+  4;     // temp =  6400  wert = 51175   // runden mit 8/2 => 4
5
temp = temp >>8;     // temp =   25   wert = 51175   // / 256 -> insgesamnt/2048
6
wert = wert + temp;  // temp =   25   wert = 51200      
7
// Für genauere Zahlen einfach temp für Nachkommastellen nutzen
8
temp = wert & 255    // temp =    0   wert = 51200      
9
// Die Vorkommastellen stehen in Wert
10
wert = wert >>8;     // temp =    0  wert = 200      
11
wert = wert - 50;    // temp =    0  wert = 150
12
//Jetzt Ausgabe vorkamma ..
13
....
14
//Nun Ausgabe Nachkomma
15
temp = temp*10
16
Dezimale1= temp >>8
17
temp &= 255  
18
temp = temp*10
19
Dezimale2= temp >>8

von Maddin (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> uint32_t Degrees = ( receivebuffer * 2000UL ) / 2047;

Was bedeutet "UL"?

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:
> Karl heinz Buchegger schrieb:
>> uint32_t Degrees = ( receivebuffer * 2000UL ) / 2047;
>
> Was bedeutet "UL"?

unsigned long

http://www.mikrocontroller.net/articles/FAQ#Welche_Datentypen_haben_Konstante.3F
und
http://www.mikrocontroller.net/articles/FAQ#Datentypen_in_Operationen

Soll ich wirklich noch den Hinweis auf ein C-Buch bringen?

von Horst H. (horha)


Lesenswert?

Hallo,

wohl Unsigned Long 32-Bit Wert von 0..4,2 Milliarden.
Aber oben mein Codegeschnipsel kommt ohne dies aus.
Sieht nach mehr aus, aber der versteckte Code für die 32-Bit Division 
ist auch nicht zu verachten.

von Maddin (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Soll ich wirklich noch den Hinweis auf ein C-Buch bringen?

Nönö, aber diese Suffix-Schreibweise hab ich echt noch nie gesehen. Naja 
gut zu wissen, ech praktisch.

von Karl H. (kbuchegg)


Lesenswert?

Nimm dir zb irgendeinen Democode her, bei dem es sich um Uart handelt.

Wie zb die Uart Routinen aus dem Tutorial
1
/* 
2
  UART-Init: 
3
Berechnung des Wertes für das Baudratenregister 
4
aus Taktrate und gewünschter Baudrate
5
*/
6
 
7
#ifndef F_CPU
8
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
9
   F_CPU im Makefile definiert werden, eine nochmalige Definition
10
   hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
11
   #ifndef/#endif 
12
 
13
   Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio 
14
   verwendet wird und dort eine andere, nicht zur Hardware passende 
15
   Taktrate eingestellt ist: Dann wird die folgende Definition 
16
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) 
17
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
18
   noch nicht definiert: */
19
#warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
20
#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als unsigned long beachten 
21
                         // Ohne ergeben sich unten Fehler in der Berechnung
22
#endif
23
 
24
#define BAUD 9600UL      // Baudrate
25
 
26
// Berechnungen
27
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
28
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
29
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.
30
 
31
#if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
32
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
33
#endif

Schau dir an wie F_CPU bzw. BAUD definiert ist.

von Maddin (Gast)


Lesenswert?

Mal abgesehen davon dass ich keinen AVR programmieren sondern MSP, hab 
ich diese Schreibweise trotzdem noch nie gesehen (oder nie bewusst 
Gedanken drüber gemacht). Ich kam zwar ganz gut ohne aus, gefällt mir 
jetzt aber ganz gut und werde ich auch verwenden.

Danke dafür.

von eProfi (Gast)


Lesenswert?

> Der maximale Wert für A ist also 200 und belegt somit nur ein Byte.
> Bei der multiplikation mit 200 übersteigt der sich in diesem Fall
> ergebene Zwischenwert die 16Bit.

Häää?????
200*200=40000   passt in 16 Bits  (zumindest unsigned)

Das Ausgeben von ADC- oder sonstigen Werten hatten wir doch schon 1024 
mal:

Beitrag "Re: 16-Bit-Zahl ausgeben, nur wie?"
Beitrag "Re: 1023 auf 100% umformen"

Nimm 2048, ist einfacher und tut der Genauigkeit keinen Abbruch.

von Karl H. (kbuchegg)


Lesenswert?

eProfi schrieb:
>> Der maximale Wert für A ist also 200 und belegt somit nur ein Byte.
>> Bei der multiplikation mit 200 übersteigt der sich in diesem Fall
>> ergebene Zwischenwert die 16Bit.
>
> Häää?????
> 200*200=40000   passt in 16 Bits  (zumindest unsigned)

200 ist sein Ergebnis, welches maximal 200 sein kann.
Ausgansgpunkt der Rechnung ist ein ADC Wert, welcher bis 2047 hoch gehen 
kann.

von Matthias L. (Gast)


Lesenswert?

Wenn du die Stellen einzeln brauchst, dann gehts auch so:

Beitrag "Re: Problem mit ADC an mega128"

von Maddin (Gast)


Lesenswert?

eProfi schrieb:
> Häää?????
> 200*200=40000   passt in 16 Bits  (zumindest unsigned)
>
> Das Ausgeben von ADC- oder sonstigen Werten hatten wir doch schon 1024
> mal:

Nein. Habe Wert der maximal 11bit von 16bit belegt. Nimmt man den Wert 
mal 200 übersteigt er die 16Bit. Mit der Ausgabe hat das hier nichts zu 
tun. Sondern mit der Berechnung.

Dennoch nochmal vielen Dank allen, für die zahlreichen Links und 
Gedanken.

Gruß

Maddin

von Horst H. (horha)


Angehängte Dateien:

Lesenswert?

Hallo,

anbei ein Programm, das es mal im Simulator ( ATmega8 ) vorführen kann.
Es braucht nur 250 Takte für eine Umwandlung des Tsic306-Wertes in eine 
Zeichenkette.
Es wird kein UL32 oder ähnliches benötigt.Stattdessen Fixpoint U8.8 mit 
seperatem Vorzeichen.
Natürlich sind 3 Nachkommastellen albern, man kann ja auch weniger 
ausgeben lassen.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.