mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Unsigned long deklarieren?


Autor: Tscheburaschka (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich stehe gerade gewaltig auf dem Schlauch, benutze einen Atmega 32 mit 
C.
Ich möchte eine Variable deklarieren wo eine Zahl > 1000000 abgelegt 
wird, jetzt habe ich probiert so eine long Variable zu deklarieren:
uint32_t test;
oder auch so
unsigned long test;

Wenn ich die berechnung laufen lasse und das Ergebnis auf einem LCD 
ausgebe
sehe ich, dass der Compiler diese Variable als Int angelegt hat den die 
Zahl
läuft bis 32767 und springt in den negativen Bereich also -32767.
Woran liegt das?

Die Berechnung ist sehr simpel, ich lese einen ADC Wert also max 1024 
und multipliziere diesen mit 1000.

Ich weiß ist eine blöde Frage, aber könte mir einer auf die Sprünge 
helfen?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>läuft bis 32767 und springt in den negativen Bereich also -32767.
>Woran liegt das?

Zeig mal die Ausgaberoutine. Vermutlich liegt der Fehler dort.

Autor: Mi Mo (mike123)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

poste mal deinen Code.
Evtl. müsstest du einen Cast machen!? Kenne ja deinen code nicht!

also z.B. so:

unsigned long test;

test = 1000 * (unsigned long) ((ADC_High << 8)| ADC_Low);

Du musst dem Compiler schon bekannt machen, dass du das ganze in einem 
unsigned long speichern willst.

Autor: H.j.Seifert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
liegt garantiert an der Ausgabe.
Compiler?

Autor: Mi Mo (mike123)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich tippe auch auf die Ausgabe, aber wir sind hier ja net beim Lotto...

Autor: Tscheburaschka (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So Nachwuchs ist versorgt, da bin ich wieder.

Das ist meine Routine:

>#include <avr/interrupt.h>
>#include <avr/io.h>
>#include "usart.h"
>#include "lcd.h"
>#include <util/delay.h>
>#include <stdint.h>

>volatile int speed = 10001;
>uint16_t ReadChannel(uint8_t mux);


>int main (void)
>{

>  //Initialisierung des LCD Displays 4 Bit Mode
>  LCD_Init();

>  //Löschen des Displays
>  LCD_Clear();

>  //Globale Interrupts freischalten
>  sei();


>>  unsigned long test;
>  int vor,hinter,ergebnis;
>  uint16_t adcval;
>  uint16_t wert1;
>  uint16_t wert2;
>  uint16_t wert3;
>  uint8_t wert10;


>  do
>  {
>  adcval = ReadChannel(1); /* MUX-Bits auf 0b0000 -> Channel 0 */

>  test=adcval*1000;
>  ergebnis=test/1024;
>  vor=ergebnis/10;
>  hinter=ergebnis%10;


>  //Ausgabe eines Textes auf dem LCD Display
>  LCD_Print(0,0,"Temperatur %i.%i2C  ",vor,hinter);
>>  LCD_Print(1,0,"ADC-Wert %i          ",test);
>  LCD_Print(2,0,"                     ");
>       LCD_Print(3,0,"                     ");


>  }
>  while(1);
>}

Ich hoffe ihr könnt mir helfen.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
probiers mal mit
 test=adcval*1000UL;

Autor: Tscheburaschka (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@eProfi

ja sieh mal einer an, SUPER es geht, herzlichen Dank für die schnelle 
Hilfe.

Was heißt dieses UL?

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das ist ein häufig gemachter Trugschluß.
Der Compiler sieht, adcval ist 16-bit, 1000 ist auch 16-bit,
also multipliziert er 16x16->16-bit
und erweitert dann das Ergebnis auf 32 Bit.



Aber nebenbei, aus der Ferne erscheinen mir die nächsten Zeilen auch 
noch verbesserungswürdig:
>  ergebnis=test/1024;
>  vor=ergebnis/10;
>  hinter=ergebnis%10;
Du meinst wohl vorkomma und nachkomma, aber das geht anders.

Am statt *1000/1024 kannst Du gleich *64000 nehmen. Das folgende /65536 
sparst Du Dir, indem Du einfach auf das high-Word des Ergebnisses 
zugreifst (am besten mit einer Union):

#define lo 0 //je nach Endianess des Prozessors evtl. umgekehrt
#define hi 1
union{unsigned long L;unsigned int I[2];} bigadc;
bigadc.L=64000*adcval+32768; //erweitern und aufrunden
LCD_out(bigadc.I[hi]);

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was heißt dieses UL?
das heißt, er soll das 1000 als unsigned long interpretieren.

ginge genauso:

 test=adcval*(unsigned long)1000;
 test=(unsigned long)adcval*1000;
 test=(unsigned long)adcval*(unsigned long)1000;

aber  mit dem UL (eigentlich reicht auch ein L) geht's am kürzesten.

Hast Du das mit dem vor - nach schon herausgebracht?
Ich würde auf Folgendes tippen:
>  vor=ergebnis/100;
>  hinter=ergebnis-100*vor;

Autor: Tscheburaschka (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also es ist vielleicht nicht die schönste Lösung aber es funktioniert so 
wie
ich das gemacht habe.
Mit dem ADC lese ich einen Wert von 0 bis 5V ein, das ist mein 
Temperaturbereich von 0 bis 100 C°.
Mit der Rechnung wollte ich folgendes erreichen:
               adcval * 1000  <--(steht für 100 C°mit einer nachkomma 
Stelle)
Temperaturwert=-------------
                   1024       <--(Auflösung AD Wandler)

So jetzt habe ich den Temperaturwert mit einer Nachkommastelle als eine 
ganze
Zahl vorliegen.
Und dann trenne ich halt die Vor und die Nachkomastelle.


Was meinst du mit herausgebracht?

Deine andere Lösung verstehe ich nicht ganz.

Autor: eProfi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gut, dann erkläre ich es etwas ausführlicher:

#define LO 0 //je nach Endianess des Prozessors evtl. umgekehrt
#define HI 1
union{unsigned long L;unsigned int I[2];} bigadc;
bigadc.L=64000*adcval+32768; //erweitern und aufrunden
LCD_out(bigadc.I[HI]);


anstatt *1000/1024 kannnst Du auch *64000/65536 rechnen.

Das /65536 erledigst Du, indem Du die unteren 16 Bits abschneidest - mit 
anderen Worten, du verwendest nur die oberen 16 Bits des 
32bit-Ergebnisses.

Dazu verwende ich gerne die o.g. Union, damit kann man wahlweise auf die 
32Bit (.L) oder auf das high- (.I[HI]) oder low-Word (.I[LO]) zugreifen.

Vermutlich musst Du *64000L schreiben, sonst ist das Ergebnis wieder nur 
16Bit.

Das +32768 zum Runden entspricht einem +0,5 und anschließendes 
Abschneiden der Nachkommastellen.

>Also es ist vielleicht nicht die schönste Lösung aber es funktioniert
>so wie ich das gemacht habe.

Poste doch mal bitte deine Version.
Viel Erfolg

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.