Kleines Problem mit itoa

Im Unterforum Microcontroller - Beschreibung: Hardware - Software - Ideen - Projekte

Elektronik Forum Nicht eingeloggt       Einloggen       Registrieren




[Registrieren]      --     [FAQ]      --     [ Einen Link auf Ihrer Homepage zum Forum]      --     [ Themen kostenlos per RSS in ihre Homepage einbauen]      --     [Einloggen]

Suchen


Serverzeit: 25 11 2024  08:34:08      TV   VCR Aufnahme   TFT   CRT-Monitor   Netzteile   LED-FAQ   Osziloskop-Schirmbilder            


Elektronik- und Elektroforum Forum Index   >>   Microcontroller        Microcontroller : Hardware - Software - Ideen - Projekte

Gehe zu Seite ( 1 | 2 Nächste Seite )      


Autor
Kleines Problem mit itoa

    







BID = 851078

Offroad GTI

Urgestein



Beiträge: 12742
Wohnort: Cottbus
 

  


Hallo,

habe mal wieder ein kleines Problem mit einem C-Programm.

Es wird über den ADC des ATMEGA32 im 10Bit-Modus eine Spannung eingelesen. Dies funktioniert auch schon, und wird auch korrekt auf dem LCD ausgegeben.
Jetzt wollte ich den Wert des ADC-Registers in die entsprechende Spannung umrechnen, dies funktioniert seltsamerweise aber nicht.

Auf dem LCD erscheint immer nur eine ein- bzw. zweistellige Zahl.


Code :


#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>

#define F_CPU 1e6
#include <avr/delay.h>
#include "lcd-routines.h"

char adcWert[10];
char Spannung[10];

int main ()
{
//Initialisierung LCD
lcd_init();
set_cursor( 1, 1 );
lcd_string("ADC Wert:" );
set_cursor( 1, 2 );
lcd_string("Spannung:" );

sei();

//Initialisierung ADC
ADCSRA |= 1<<ADPS2;
ADMUX |= (1<<MUX0) | (1<<MUX1); //MUX auf ADC3
ADMUX |= 1<<REFS0; //AVCC als Referenz
ADCSRA |= 1<<ADIE;
ADCSRA |= 1<<ADEN;

//Erste Wandlung
ADCSRA |= 1<<ADSC;

while(1);
{
}
}

ISR(ADC_vect)
{
//H und L Bits des ADC-Registers zu einer 16Bit Zahl zusammenfassen
uint8_t LowBits=ADCL;
uint16_t ZehnBitWert=ADCH<<8|LowBits;

//Umrechnung des ADC-Werts in die entsprechende Spannung [mV]
uint32_t Umrechnung=(ZehnBitWert*5000)/1024;

//Zahlenwerte in Strings fürs LCD umwandeln
itoa(ZehnBitWert, adcWert, 10);
itoa(Umrechnung,Spannung,10);

//Werte auf LCD ausgeben
set_cursor( 10, 1 );
lcd_string( adcWert );
lcd_string( " Bit " );
set_cursor( 10, 2 );
lcd_string( Spannung );
lcd_string( "mV " );

//ADC-Wandlung vornehmen
ADCSRA |= 1<<ADSC;
}



Weiß jemand diesbezüglich einen Rat?



_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.

BID = 851080

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

 

  

Mal mit ultoa() versuchen?
Immerhin nutzt du ja für die Spannung in Millivolt einen unsigned long.


_________________

BID = 851088

Offroad GTI

Urgestein



Beiträge: 12742
Wohnort: Cottbus

Guter Hinweis, ultoa hatte ich aber auch schon versucht - ebenfalls erfolglos


Edit:
Die Variable Umrechnung wird pro ZehnBitWert um 5 erhöht und läuft bei >60 über und startet dann wieder bei 1.
Hilft das irgendwie weiter?




[ Diese Nachricht wurde geändert von: Offroad GTI am  6 Okt 2012 22:52 ]

BID = 851091

perl

Ehrenmitglied



Beiträge: 11110,1
Wohnort: Rheinbach


Zitat :
(ZehnBitWert*5000)/1024
Sollte da nicht 1023 stehen, damit du bei 5V auch 5000 angezeigt bekommst?

BID = 851118

Brizz

Stammposter



Beiträge: 386
Wohnort: Rheine


Der Fehler liegt hier:
uint32_t Umrechnung=(ZehnBitWert*5000)/1024;

Der Zehn Bit-Wert ist als 16-Bit-Wert deklariert. Der wird mit 5000 multipliziert, dabei geht das meiste verloren. Das „kaputte“ Produkt wird durch 1024 dividiert. Dann der ganz „kaputte“ Quotient in eine Vorzeichenlose 32-Bit-Zahl gewandelt.

Deklariere eine 32-Bit-Zahl und weise der 5000 zu. Führe damit die Multiplikation und danach die Division durch, dann erhälst Du das erwartete Ergebnis.

BID = 851141

Offroad GTI

Urgestein



Beiträge: 12742
Wohnort: Cottbus

Danke, genau da lag der Fehler.

Ich habe jetzt (einfach) ZehnBitWert auch als 32Bit Integer deklariert, und erhalte das gewünschte Ergebnis.

Hätte diese Variante
Zitat :
Deklariere eine 32-Bit-Zahl und weise der 5000 zu. Führe damit die Multiplikation und danach die Division durch
einen Vorteil?


@Perl: Ja, da sollte 1023 stehen, ist ebenfalls geändert.




_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.

BID = 851162

Brizz

Stammposter



Beiträge: 386
Wohnort: Rheine

@Offroad GTI

Die 5000 auf eine Variable zu schieben, hat keinen Vorteil. Es ging nur darum, dass die Multiplikation und auch die nachfolgende Division mit 32-Bit-Integern durchgeführt wird .

Der C-Compiler prüft immer die Operanden einer arithmetischen Funktion, und ruft letzlich die Funktionen auf, welche durch den Operanden mit den meisten Bit erforderlich ist. Es gibt für char, integer, long usw. auch unterschiedliche Algorithmen.

Es gilt die Hierachie:

char
integer
long integer
long long integer
float
double
long double

Am wenigsten Speicher würde das Programm wie folgt gebrauchen:



uint32_t Umrechnung = ZehnBitWert;
Umrechnung *= 5000;
Umrechnung /= 1024;

Dann kannst Du den ZehnBitWert auch als 16-Bit-Variabel lassen, weil die Konvertierung bei der Zuweisung auf Umrechnung stattfände.

BID = 851171

DonComi

Inventar



Beiträge: 8605
Wohnort: Amerika

Oder du castest:
uint32_t Umrechnung=(((uint32_t)(ZehnBitWert))*5000)/1023;


_________________

BID = 851193

Brizz

Stammposter



Beiträge: 386
Wohnort: Rheine

Es geht auch:

uint32_t Umrechnung=(ZehnBitWert*5000L)/1023;

BID = 851203

Offroad GTI

Urgestein



Beiträge: 12742
Wohnort: Cottbus

Danke noch mal euch beiden.


Zitat :
Am wenigsten Speicher würde das Programm wie folgt gebrauchen:
uint32_t Umrechnung = ZehnBitWert;
Umrechnung *= 5000;
Umrechnung /= 1024;
Dem ist aber nicht so. Diese Variante benötigt ein paar Byte (um genau zu sein 24) mehr Speicher, als die Variante mit ZehnBitWert als long int.

Diese Variante
Zitat :
uint32_t Umrechnung=(((uint32_t)(ZehnBitWert))*5000)/1023;
ist am sparsamsten (-4Byte)

Wohingegen diese
Zitat :
uint32_t Umrechnung=(ZehnBitWert*5000L)/1023;
geradezu verschwenderisch ist (+50Byte)


Diese Problematik kann somit als gelöst angesehen werden.



_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.

BID = 851204

perl

Ehrenmitglied



Beiträge: 11110,1
Wohnort: Rheinbach

Einfacher gehts natürlich, wenn man den Prozessor mit etwas erhöhter Spannung von 5,115V betreibt, oder einen entsprechenden Eingangsspannungsteiler verwendet.

Dann enspricht jedes Digit genau 5mV, man kommt problemlos mit 16 Bit aus, weil man nur mit 5 zu multiplizieren braucht *), und man kann sich die häßliche platz- und rechenzeitraubende Division schenken.

Als besonderes Schmankerl kann man dann auch geringe Überspannungen bis hin zu jenen 5,115V anzeigen.

*) P.S.:
Der Assembler Programmierer macht das mit zweimal linksschieben und einer addition.
Dürfte ungefähr 15 Takte dauern und vielleicht 10 Instruktionen brauchen.


[ Diese Nachricht wurde geändert von: perl am  7 Okt 2012 22:37 ]

BID = 851295

Offroad GTI

Urgestein



Beiträge: 12742
Wohnort: Cottbus


Zitat :
wenn man den Prozessor mit etwas erhöhter Spannung von 5,115V betreibt
Das wäre ja ganz schön verwegen

Man könnte auch eine 1,024V Refernezspannung erzeugen, und brächte gar nichts mehr rechnen. Hätte natürlich den Nachteil, dass ein präziser Spannungsteiler nebst Puffer-OPV benötigt wird.

Da aber eine Berechnung (mit Division und Umwandlung in ASCII) nur 20Byte (von 32k Gesamtspeicher) benötigt, werde ich es so lassen.




_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.

BID = 851298

perl

Ehrenmitglied



Beiträge: 11110,1
Wohnort: Rheinbach


Zitat :
Man könnte auch eine 1,024V Refernezspannung erzeugen, und brächte gar nichts mehr rechnen
Und der ADC zählt dann plötzlich bis 5000?
Wunderlich.


Zitat :
Das wäre ja ganz schön verwegen
Das ist nicht verwegen, denn man wird ohnehin eine Abgleichmöglichkeit schaffen müssen, weil die 5V Versorgung üblicherweise nicht sehr genau ist.
Die Alternative, erwähnte ich bereits: Einen Eingangsspannungsteiler verwenden, der dafür sorgt, dass von 5V nur 4,888V am Eingang des ADC erscheinen.

P.S.:
Zitat :
Da aber eine Berechnung (mit Division und Umwandlung in ASCII) nur 20Byte (von 32k Gesamtspeicher) benötigt

Zeig mir mal den zugehörigen Maschinencode!








[ Diese Nachricht wurde geändert von: perl am  8 Okt 2012 17:44 ]

BID = 851310

Offroad GTI

Urgestein



Beiträge: 12742
Wohnort: Cottbus


Zitat :
Und der ADC zählt dann plötzlich bis 5000?
Nein, so meinte ich das nicht. Er zählt natürlich weiterhin nur bis 1023.


Zitat :
Zeig mir mal den zugehörigen Maschinencode!
Was kann da denn rausgelesen werden?

Code :

:100000000C942A000C9447000C9447000C94470071

:100010000C9447000C9447000C9447000C94470044
:100020000C9447000C9447000C9447000C94470034
:100030000C9447000C9447000C9447000C94470024
:100040000C9465000C9447000C9447000C944700F6
:100050000C94470011241FBECFE5D8E0DEBFCDBF12
:1000600010E0A0E6B0E0EAE2F5E002C005900D92F3
:10007000A238B107D9F710E0A2E8B0E001C01D92A4
:10008000AE3BB107E1F70E9449000C9493020C9437
:1000900000000E946E0181E061E00E94B90180E6EB
:1000A00090E00E94D40181E062E00E94B9018AE6FA
:1000B00090E00E94D4017894329A87B1836087B926
:1000C0003E9A339A379A369AFFCF1F920F920FB605
:1000D0000F921124CF92DF92EF92FF920F931F9312
:1000E0002F933F934F935F936F937F938F939F9340
:1000F000AF93BF93CF93DF93EF93FF9324B135B1C9
:10010000932F80E0C22FD0E0C82BD92BBE0180E016
:1001100090E028E833E140E050E00E94E8012FEF52
:1001200033E040E050E00E9407028901F42EE52E02
:100130008CE8C82E80E0D82ECE01B6014AE050E00F
:100140000E942902C2E8D0E0B8018F2D9E2DAE0199
:100150002AE030E00E944A02B8018F2D9E2D40EA2D
:1001600050E02AE030E00E944A02B8018F2D9E2D17
:100170004AEA50E02AE030E00E944A02B8018F2D9E
:100180009E2D44EB50E02AE030E00E944A02B80184
:100190008F2D9E2D46E950E02AE030E00E944A0271
:1001A0008AE061E00E94B901C6010E94D40184E79F
:1001B00090E00E94D4018AE062E00E94B901CE0181
:1001C0000E94D4018CE790E00E94D401369AFF91FE
:1001D000EF91DF91CF91BF91AF919F918F917F91DF
:1001E0006F915F914F913F912F911F910F91FF90D0
:1001F000EF90DF90CF900F900FBE0F901F9018954B
:10020000C59A0000C5980895DF93CF930F92CDB79C
:10021000DEB7C498C098C198C298C398982F929599
:100220009F7090FDC09A91FDC19A92FDC29A93FD74
:10023000C39A89830E940001C098C198C298C3984C
:1002400089818F7080FDC09A81FDC19A82FDC29A1A
:1002500083FDC39A0E94000188E18A95F1F700C0EE
:100260000F90CF91DF910895DF93CF930F92CDB789
:10027000DEB7C49AC098C198C298C398982F929537
:100280009F7090FDC09A91FDC19A92FDC29A93FD14
:10029000C39A89830E940001C098C198C298C398EC
:1002A00089818F7080FDC09A81FDC19A82FDC29ABA
:1002B00083FDC39A0E94000188E18A95F1F700C08E
:1002C0000F90CF91DF91089581E00E94040181EEAB
:1002D00094E00197F1F700C000000895B89AB99A28
:1002E000BA9ABB9ABD9ABC9A85EA9EE00197F1F74B
:1002F00000C00000C09AC19AC298C398C4980E94D6
:10030000000181EE94E00197F1F700C000000E9427
:10031000000189EF90E00197F1F700C000000E9412
:10032000000189EF90E00197F1F700C00000C0984C
:10033000C19AC298C3980E94000189EF90E001978A
:10034000F1F700C0000088E20E9404018CE00E94E6
:10035000040186E00E9404010E946401089582E085
:100360000E94040181EE94E00197F1F700C00000C3
:100370000895623069F0633018F4613089F405C083
:10038000633049F0643061F409C0982F915808C077
:10039000982F915405C0982F9D5602C0982F9D52BA
:1003A000892F0E9404010895EF92FF92CF93DF936B
:1003B000E82EE7017E01F92EE70102C00E94340118
:1003C00089918823D9F7DF91CF91FF90EF9008951D
:1003D000629FD001739FF001829FE00DF11D649F29
:1003E000E00DF11D929FF00D839FF00D749FF00DB5
:1003F000659FF00D9927729FB00DE11DF91F639F56
:10040000B00DE11DF91FBD01CF0111240895A1E236
:100410001A2EAA1BBB1BFD010DC0AA1FBB1FEE1F7E
:10042000FF1FA217B307E407F50720F0A21BB30BC9
:10043000E40BF50B661F771F881F991F1A9469F745
:1004400060957095809590959B01AC01BD01CF01A1
:100450000895FB019F01E8944230C4F04532B4F4A2
:100460004A3029F497FB1EF4909581959F4F642F95
:1004700077270E947F02805D8A330CF0895D81932B
:10048000CB010097A1F716F45DE251931082C901E8
:100490000C946F02FA01CF93FF93EF932230CCF0CC
:1004A0002532BCF4C22F2C2F332744275527FF9326
:1004B000EF930E940702EF91FF91605D6A330CF0A9
:1004C000695D6193B901CA016050704080409040FD
:1004D00051F710828F919F91CF910C946F02DC01A4
:1004E000FC01672F71917723E1F7329704C07C916B
:1004F0006D9370836291AE17BF07C8F30895AA1B6E
:10050000BB1B51E107C0AA1FBB1FA617B70710F0FE
:10051000A61BB70B881F991F5A95A9F78095909530
:0A052000BC01CD010895F894FFCF4F
:10052A0041444320576572743A005370616E6E7588
:10053A006E673A002042697420202000206D562000
:02054A000000AF
:00000001FF



_________________
Theoretisch gibt es zwischen Theorie und Praxis keinen Unterschied. Praktisch gibt es ihn aber.

BID = 851314

perl

Ehrenmitglied



Beiträge: 11110,1
Wohnort: Rheinbach


Zitat :
Was kann da denn rausgelesen werden?
Na, die Maschinenbefehle.
Übersichtlicher als das obige, wahrscheinlich auch noch mit Prüfsummen aufgefüllte Binärformat, ist die Assembler-Darstellung.
Da das ja nur 20 Byte sind, wie du schreibst, sollte das ein sehr handliches Listing sein.

Wahrscheinlich wirst du mir aber nur ein paar Zubringerbefehle und Unterprogrammaufrufe präsentieren.
Die geschätzt 800 Bytes des zugehörigen Maschinenprogramms hat der Compiler wahrscheinlich woanders versteckt.



      Nächste Seite
Gehe zu Seite ( 1 | 2 Nächste Seite )
Zurück zur Seite 1 im Unterforum          Vorheriges Thema Nächstes Thema 


Zum Ersatzteileshop


Bezeichnungen von Produkten, Abbildungen und Logos , die in diesem Forum oder im Shop verwendet werden, sind Eigentum des entsprechenden Herstellers oder Besitzers. Diese dienen lediglich zur Identifikation!
Impressum       Datenschutz       Copyright © Baldur Brock Fernsehtechnik und Versand Ersatzteile in Heilbronn Deutschland       

gerechnet auf die letzten 30 Tage haben wir 20 Beiträge im Durchschnitt pro Tag       heute wurden bisher 5 Beiträge verfasst
© x sparkkelsputz        Besucher : 182393882   Heute : 1078    Gestern : 7548    Online : 599        25.11.2024    8:34
3 Besucher in den letzten 60 Sekunden        alle 20.00 Sekunden ein neuer Besucher ---- logout ----viewtopic ---- logout ----
xcvb ycvb
0.0501461029053