C Temperaturmessung mit ATMega32

spider-man

Neues Mitglied
24. Feb. 2012
7
0
0
Sprachen
Hallo,
ich bin neu hier und habe mich angemeldet, da ich seit Tagen ein Problem mit der Temperaturmessung beim ATMega32 habe und einfach nicht weiterkomme. Ich verwende einen Sensor vom Typ AD22100, welcher am Port PA5 des ATMega32 angeschlossen ist. Das als Anhang beigefügte Beispiel steht ähnlich in einem Buch, ist aber eigentlich für den ATMega8 gedacht. Es wird leider nur ein irrsinniger Wert für die Temperatur angezeigt. Ich vermute, dass irgendetwas mit dem Einlesen des Ports nicht passt. Vielleicht kann mir jemand weiterhelfen - wäre super nett. Es liegt wahrscheinlich mal wieder nur an einer Kleinigkeit. Vielleicht hat auch jemand ein einfacheres funktionierendes Beispiel parat.
Danke.
spider-man
 

Anhänge

  • Programmcode.txt
    824 Bytes · Aufrufe: 82
Hallo und willkommen im AVR-PRAXiS Forum!

Wenn du bei Programmanfang eine Testausgabe mit festgelegtem Wert machst, wird dieser richtig ausgegeben? Wenn ja, dann funktioniert number_output.

Du summiertst acht ADC Messungen, um einen Mittelwert zu bilden. Danach müsstest du das summierte Ergebnis durch 8 Teilen (drei mal nach rechts shiften),
das machst du nicht.

Wielleicht ist das ja schon der Fehler.

Falls nicht, die Berechnung ADC_result*slope/1000-offset macht eventuell noch Probleme.

Die ADC Initialisierung habe ich mir noch nicht angesehen.

Gruß,
Dirk
 
Temperaturmessung mit dem ATMega32

Hallo Dirk,
erstmal vielen Dank für die schnelle Antwort. Leider bin ich noch ein Anfänger in der AVR-Programmierung.
Eine Drehzahlerfassung mit Steuerung habe ich schon hinbekommen, aber diese verflixte Temperaturmessung will nicht klappen.
Ich habe jetzt, wie Du vorgeschlagen hast, den eingelesenen Wert mal direkt ausgegeben. Es wird 5,0 °C angezeigt (stimmt natürlich nicht - 21°C wären korrekt), allerdings werden diese auch ohne Anschluss des Sensors angezeigt.
Daher muss ich etwas gezielter fregen. Welcher Eingang des ATMega32 wird denn genau mit dem Befehl

ADMUX = 0x05;

eingelesen? Wie übersetzt man die 0x05?
Ich hasse Literatur mit Beispielen, die nicht funktionieren, wenn man sie 1:1 umsetzt.
Hast Du vielleicht ein einfacheres Programm für die Temperaturerfassung parat? Den Sensor kann ich ja notfalls gegen einen anderen austauschen.

Gruß
Marco



Hallo und willkommen im AVR-PRAXiS Forum!

Wenn du bei Programmanfang eine Testausgabe mit festgelegtem Wert machst, wird dieser richtig ausgegeben? Wenn ja, dann funktioniert number_output.

Du summiertst acht ADC Messungen, um einen Mittelwert zu bilden. Danach müsstest du das summierte Ergebnis durch 8 Teilen (drei mal nach rechts shiften),
das machst du nicht.

Wielleicht ist das ja schon der Fehler.

Falls nicht, die Berechnung ADC_result*slope/1000-offset macht eventuell noch Probleme.

Die ADC Initialisierung habe ich mir noch nicht angesehen.

Gruß,
Dirk
 
Hi Marco,

willkommen im Forum :flowers:

HaWelcher Eingang des ATMega32 wird denn genau mit dem Befehl

ADMUX = 0x05;

eingelesen? Wie übersetzt man die 0x05?
Ich hasse Literatur mit Beispielen, die nicht funktionieren, wenn man sie 1:1 umsetzt.
sieh dir mal das große Datenblatt vom Mega32 (von Atmel) an. Da steht das sehr ausführlich in einer Tabelle beschrieben.
0x05 heißt in dem Register das als Referenz die Spannung am Aref-Pin verwendet werden solol und das der ADC-Pin 5 als Eingang verwendet wird.
Ich kann das Datenblatt jedem nur wärmstens empfehlen. Es erleichtert das Verständnis der internen Abläufe ganz ungemein.

Bei deinem Wert müßtest du also am Aref die gewünschte Referenzspannung für den ADC anschließen. Einfacher geht es mit zB 0x45 da dann AVcc (5V) als Referenz verwendet wird. Dann brauchst du nur nen 100nF-Keramik am ARef und kannst dir den 5V Anschluß sparen. Oder du nimmst 0xC5, dann benutzt du die interne 2,56V Referenzspannung (auch nen 100nF am Aref-Pin. Den brauchst du IMMER).

Gruß
Dino
 
Hi Marco,

ich bin zwar nicht Dirk aber ich versuch dir dennoch zu helfen :)

Also für sowas immer in das Datenblatt schauen ...


Dort suchst du dann nach dem Register ADMUX und findest du dann im wesentlichen diese zwei Tabellen :
admux.png
mux.png

In der Zweiten Tabelle siehst du dann, wenn der Mux4 - Mux0 auf 0 steht ist ADC0 ausgewählt, wenn nur Mux1 auf 1 ist dann eben ADC1 ...

So .. Ich schreibe die Register normal nie in Hex werten hin, da diese einfach nur unschlüssig sind und man erst umrechnen muss ...

Deine 0x05 bedeutet binäir nichts anderes als 0b00000101 so das heißt also ADC5 ist ausgewählt ...(hier sollte auch dein Temperatur fühler angeschlossen sein) ;)
Bei mir sieht das ganze normal so aus

ADMUX = (1<<MUX0) | (1<<MUX2) das ergibt genau das selbe wie deine 0x05 nur man weiß gleich welche Register gesetzt sind :)


Wenn wir schon dabei sind hast du die Referenz Spannung richtig eingestellt ?..
refs0.png

Es ist schwer für mich zu sagen was deine Output funktion da alles schönes macht (da zwar ein Include Pfad angegeben ist aber ich diese zumindest nicht habe ;)...

Poste doch bitte einfach mal dein gesamtes Projekt sowie den Schaltplan, dann ist es einfacher dir zu helfen :).


€dit jaja war der dino wieder mal schneller ...

Gruß,
Manuel
 
Temperaturmessung mit dem ATMega32

Hallo Dino und Manuel,

jetzt habe ich zumindest mal den richtigen Eingang gefunden :)
Der richtige Temperaturwert wird allerdings noch nicht angezeigt - der T-Sensor ist jedoch nicht defekt, da ich schon einen zweiten getestet habe. Es wird ein irrsinnig hoher Wert (4294962200.0) angezeigt.
Ich habe mal den Schaltplan und das Programm + Includes beigefügt.
Vielleicht weiss einer von Euch, woran es liegt.
Einstweilen vielen Dank.

Viele Grüße
Marco
 

Anhänge

  • Temperaturmessung.jpg
    Temperaturmessung.jpg
    207,3 KB · Aufrufe: 21
  • P2.txt
    1,4 KB · Aufrufe: 18
  • Includes.zip
    11,1 KB · Aufrufe: 18
Hi,

du solltest mal den AVcc mit +5V versorgen (so wie den Vcc) sonst fehlt dem ADC und dem Zeugs da dran die Betriebsspannung. Ohne Saft arbeitet sich so schlecht ;)

Außerdem ... 100nF parallel zum GND und Vcc (10 + 11) 100nF Keramik parallel zu AVcc und GND (30 + 31) und einen 100nF Keramik vom ARef zum GND (32 + 31). Außerdem nen 10-22µF Elko parallel zu GND und Vcc (10 + 11) (für längere Stromspitzen). Dem Reset würde ich auch noch der Stabilität wegen nen 22kOhm nach Vcc gönnen und nen 47-100nF nach GND.

EDIT: Außerdem sieh dir mal das Datenblatt des AD22100 an ...
Anhang anzeigen AD22100_-_Voltage Output Temperature Sensor with Signal Conditioning.pdf
Bei "Figure 2. Application Circuit" ist nen 1k und nen 100nF drin um die Ausgangsspannung des Sensors für den ADC zu beruhigen. Das fehlt bei dir auch noch.

Gruß
Dino
 
Hi,

äähmm ja ich bin verwirrt ^^ zuvor war es ne Uartausgabe jetzt auf nem LCD ? *gg*

okey ..

was mich zudem verwirrt ..

Code:
        for(unsigned int i=0;i<1;i++)
        {    ADCSRA |= (1<<ADSC);            // single conversion
              while ( ADCSRA & (1<<ADSC) );       // wait for ADC ready
            ADC_result += ADCW;            // add up conversions
        }

also du machst eine for schleife die sich einmal dreht ?!?

wenn du das aus einem Buch hast ... hast du das da so 1 zu 1 abgetippt ?
Weil .. ich vermute, dass durch den slope ein Faktor gebildet wird der dann ohne viel rechnerrei direkt ein Temperatur wert ergibt (ohne float Rechnung). Wenn du in der Wertaufnahme das nun von z.b. 8 Messungen auf eine Reduzierst kommt da natürlich nur noch müll raus ..

also die erste Frage ist der Code genauso im Buch ?

Denn ...

Dein ADC kann maximal 0 - 1023 liefern.
die Berechnung in der LCD Übergabe ist ...

Also wenn wir von einer Referenz ausgehen wie dino meinte 5 V hast du 5V / 1024 = 4,88mV / Digit.
Dein Sensor hat bei 150°C 4,75V was ich gesehen habe. somit kann von deinem Temperatursensor maximal ein wert von ~973 Digit rauskommen.

Code:
 ADC_result*slope/1000-offset

Code:
 973 * 2715 / 1000 - 6111

dann bekomme ich -3469 raus ... (naja ich glaub das ist nicht das was wir wollten ...)

Wenn du jedoch 8 Messungen addierst ... sieht das ganze dann so aus

Code:
 (973 * 8) *2715 / 1000 - 6111

dann kommen wir auf 15022 (was irgendwie schon verdammt nah an die 150° ran kommt ?!? ;)


als gegenprobe machen wir noch schnell den wert bei -50°C ~ 0,25V
0,25 V = 51digit

Code:
 (51 * 8) *2715 / 1000 - 6111

dann kommen wir auf -4998 (ja ich denke das kommt auch sehr nahe an deine -50°C :) also das Rechenwerk Funktioniert da ganz gut...

okey es ist überall noch ein faktor von 100 drin aber :) das kann auch sein dass es deine LCD Routine direkt rechnet / ummodelt... also öhm ja :)

dann ganz neben bei .. das ist jetzt zwar ne sehr allgemeine Basic aber ich denke das sollte man nicht vernachlässigen :) (hilft zwar nicht für dieses Problem aber allgemein ..)

Gewöhne dir an wenn du zähler Variablen machst (wie z.b. hier dein i, das auch nur so groß zu machen wie es sein muss .. du hast hier ein Integer ausgewählt -> 16 Bit bei dieser CPU ... erstens ist es "Speicher" fressend .. klar kann man sagen "das ist doch nur einmal in ner lokalen Variable ... aber aus einmal wird ne gewohnheit und .. joar ;) also nur als gut gemeinter allgemeiner rat =)


Also VREF anschließen wie dino gesagt hat, dann noch die 8 in die Forschleife und dann nochmal schauen was das ganze so sagt :)

Gruß,
Manuel
 
...
ADMUX = (1<<MUX0) | (1<<MUX3) das ergibt genau das selbe wie deine 0x05 nur man weiß gleich welche Register gesetzt sind...
sind das nicht 9? (2^3+2^0)
Sollte da nicht stehen: ADMUX=5, oder besser ADMUX= (5<<MUX0)
mit n=(Referenzspannungsmode) dann:
ADMUX=(n<<REFS0)|(5<<MUX0)
(kannst natürlich auch jedes bit einzeln aufführen, aber bitte nicht vertun...:p)
 
hehe

du hast natürlich Recht dass dies 9 gibt =)

hatte mich vertippt und wollte den Mux2 schreiben :)

Code:
 ADMUX = (1<<MUX0) | (1<<MUX2) ;

wobei es nur um die allgemeine Schreibweiße ging :) und nicht einfach für Copy & Paste gedacht war :).

Dein ADMUX = 5 ist das selbe wie ADMUX = 0x05 ^^ ob du ne Dezimale 5 oder ne Hex 5 da reinkloppst bleibt es immer eine 0b0000101.

Mit ADMUX= (5<<MUX0) würdest du in dem fall zwar auch eine 0b0000101 hinbekommen wobei das hier eher zufall ist .. bzw es einfach unsinnig wäre so *gg* (auser man will seinen Nachbarn verwirren der das lesen möchte ^^). Weil überleg mal was du hier machst ^^ du schiebst eine 5 um 0 stellen *gg* da ist der Pracktische Nährwert eher gering ^^).

Denn ...

Code:
 ADMUX = (1<<MUX0) | (1<<MUX2);
bewirkt folgendes

wenn man es aufteilt schieben wir im Teil eins (1<<MUX0) eine 1 um "MUX0" Stellen nach Links.. im iomxx.h file des jeweiligen Prozessors steht nun
Code:
/* ADMUX */
#define REFS1   7
#define REFS0   6
#define ADLAR   5
#define MUX4    4
#define MUX3    3
#define MUX2    2
#define MUX1    1
#define MUX0    0

Was also vom preprozessor auf (1<<0) umgewandelt wird. Also wir schieben eine 1 um 0 stellen nach links und verodern das mit dem ergebnis von (1<<MUX2), was (1<<2) ist und somit eine 1 um 2 nach links schiebt. Somit ergibt es 0b00000101 und das wäre genau das was wir wollen :).

Wenn man nun noch REFS0 möchte schreibt man einfach

Code:
 ADMUX = (1<<MUX0) | (1<<MUX2) | (1<<REFS0);

und keine Angst ! Das ganze braucht 0 mehr Speicher als wenn man direkt die 0x45 reinschreibt ...
hier der Beweis :)
schift.png
diese Schiebeopperation oben wird rein vom Preprozessor des Compilers erledigt und dient der Übersicht :).(es ist zwar etwas mehr schreibarbeit, jedoch wenn man sich das angewöhnt hat geht es sehr schnell und .. vorallem wenn man dann mal in nem halben jahr das ganze wieder anschaut ist es wesentlich leichter das ganze nochmal zu editieren / nachzuvollziehen ...

Gruß,
Manuel
 
die 5 ist die fünfte Zeile aus Deiner Tabelle (wenn man bei 0 beginnt). Dasselbe mit der REFS-Tabelle. Klar bring 5 0mal nach links schieben nicht wirklich was - genauso, wie weenn du 'ne 1 0mal schiebst. Der Knackpunkt is, daß man die Bitposition im Byte nicht explizit angeben muß, deswegen ja die Equations (.equ, oder wie das auch immer bei Euch heißt). Muß dann natürlich alles in einem Byte stattfinden. Was denkst Du, warum viele dieser Konfigurationsbits in der Form "... BITn..BIT0..." in den I/O-Registern angeordnet sind?
 
Hallo,
erstmal vielen Dank Ihr beiden. Es scheint jetzt soweit zu funktionieren, auch wenn es 2°C noch zuviel anzeigt, aber vielleicht korrigiert sich das noch, wenn ich den Widerstand und den Kondensator an den Sensor noch anschließe. Die anderen Kondensatoren werde ich mir auch nächste Woche gleich besorgen. AVCC war schon angeschlossen, hatte nur auf dem Schaltplan gefehlt. Das mit der Schleife war mein Fehler -> musste natürlich i<8 heissen (hatte da vorher etwas rumprobiert).
Jetzt ist eigentlich nur noch das Problem mit den 3 Bits nach rechts verschieben. Gibt es hier einen einfachen Befehl, den ich einfach bei der LCD-Ausgabe mit ergänzen kann?

lcd_set_cursor(2, 2); dtostrf ((ADC_result*slope/1000-offset), 4, 1, t2); lcd_write (t2);

Gruß
Marco
 
LotadaC ^^ du hast (teils)schon recht .. genau deswegen sind sie so angeordnet :)

Aber wenn ich 2 Bits setzen will dann ein (5<<MUX0) zu machen ist einfach am Ziel total vorbei *gg*...

genau weil man es den leuten Einfach machen will sind die #defines so aufgebaut damit ich (1<<Mux0) |(1<<Mux1) |(1<<Mux2) |(1<<Mux3) |(1<<Mux4) machen kann. Klar kannst du beim ADC auch = 5 machen, in dem falle ist es schön, dass es dann auf Kanal 5 geht :) (Mach aber mal etwas mit ner Uart oder sonstigen Registern ..).

Zudem gibt unter Programmierern auch einen Programmierstil ;) und ein Sourcecode in dem Register direkt beschrieben sind tragen nicht umbedingt der Lesbarkeit zu =).

Was einfach ein total unschöner Programmierstil ist ist sowas wenn man einfach alles mischt ..

Code:
DDRA = 0b00101111;
DDRC = (1<<PA4) | (1<<PA5) | (1<<PA7);
DDRD = 0xFF;
Gut manche stehen eventuell darauf, von denen möchte ich aber bitte kein Programm als Beispiel sehen :).

Denn was ist eindeutiger zu sagen was man in ner Zeile macht ...
Bsp. 1
Code:
ADMUX = 0x45;
-> okey ich schau mal ins Datenblatt was der Typ von mir wollte
Bsp. 2
Code:
ADMUX = 0x01000101;
-> okey der typ hats mir leichter gemacht ich kann das Bitmuster auf das Register legen und seh was er macht
Bsp. 3
Code:
ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX2) ;
-> oh ja also er setzt zwei Mux register und ein Refs0, da ich schon mal mit nem Atmel gearbeitet hab weiß ich, dass es die Referenz sein muss und ein Mux Kanal.

Auch wenn beim ADC z.b. die 5 = Kanal 5 gibt ... mit ner 0x45 weißt immer noch nicht wass mit der 0x40 gemeint ist ...
man sollte in einem Programm eine Schreibweise haben, was machst jetzt wenn noch ne Uart und nen Timer dazu kommen dann wird das ganze etwas bunt .. ?!?

Wenns total unsauber machen willst machst es am bessten noch so
Code:
ADMUX = (1<<REFS0);
ADMUX |= 5;

und wieso ich sage unsauber ist ganz einfach ...
Code:
ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX2) ;
ergibt in ASM
Code:
544:       ADMUX = (1<<MUX0) | (1<<MUX2) | (1<<REFS0);
+00000204:   E485        LDI       R24,0x45       Load immediate
+00000205:   B987        OUT       0x07,R24       Out to I/O location

schöne 2 Instruktionen ...

so Jetzt das wo ich so frech behauptet habe dass es Unsauber ist ...
Code:
547:      ADMUX = (1<<REFS0);
+00000206:   E480        LDI       R24,0x40       Load immediate
+00000207:   B987        OUT       0x07,R24       Out to I/O location
548:      ADMUX |= 5;
+00000208:   B187        IN        R24,0x07       In from I/O location
+00000209:   6085        ORI       R24,0x05       Logical OR with immediate
+0000020A:   B987        OUT       0x07,R24       Out to I/O location
Ja und das selbst bei nem maximalen Optimizer kommst du zack auf 5 Instruktionen ...

Erstens ist diese Schreibweiße total unleserlich (ich mein okey wenn du nen Programm von einer A5 Seite größe hast mag das nicht so entscheidend sein ...) Aber wenn du Programme mit mehreren Hundert Zeilen schreibst und diese eventuell mal wieder anschauen musst bzw Kunden geben möchtest ... naja Kurz gesagt .. das ganze sollte etwas programmierstil haben ...

So das ganze war nun etwas viel Offtopic aber gehört doch irgendwie zum Thema dazu :)
Gruß,
Manuel
 
Hallo,
Jetzt ist eigentlich nur noch das Problem mit den 3 Bits nach rechts verschieben. Gibt es hier einen einfachen Befehl, den ich einfach bei der LCD-Ausgabe mit ergänzen kann?

lcd_set_cursor(2, 2); dtostrf ((ADC_result*slope/1000-offset), 4, 1, t2); lcd_write (t2);

Gruß
Marco

Hey Marco,

nein Stop,

das mit nach Rechts schieben musst du doch nicht mehr machen :),
Das was Dirk meinte mit seinem ersten Post war mal ins blaue geraten obs dann besser wird, weil du eben deine Messung * 8 genommen hast aber im ersten moment nicht 100% ersichtlich war, dass es in dem Rechenwerk mit deinem (adc*slope / 1000 -6111) korrigiert wird.

Also für die LCD Ausgabe musst du das nicht mehr 3 mal nach rechts schieben (Schau dir hierzu nochmal mein Rechenbeispiel in einem der vorheren Posts an wo ich auf die 150°C und die -50°C eingegangen war ...).

Aber wenn du irgendwas schieben möchtest ... es geht in C sehr einfach ..

Code:
Ergebnis = (ZuschiebendeVariable>>anzahlanstellen)

bzw
wenn du sie dauerhaft geschoben haben willst
Code:
ZuschiebendeVariable >>= anzahlanstellen

einfaches Beispiel

du hast ne Zahl ich schreib sie mal direkt in binäir.

0b00001000 // was Dez. eine 8 ist ..
schiebst du das ganze nun 3 mal nach rechts hast du
0b00000001 // was Dez. dann eben 1 ist und schon hast du / 8 geteilt.

Die Schiebeopperationen nimmt man ganz einfach weil es für deinen Controller viel leichter ist zu Schieben als irgendwas zu teilen ... Jedoch machen mittlerweile die neueren Compiler dies automatisch als Schiebeopperation.
 
Hallo zusammen,

wau ... das wird ja richtig ne "Grundsatzdiskussion" über sauberes programmieren ...
Denn was ist eindeutiger zu sagen was man in ner Zeile macht ...
Bsp. 1
Code:
ADMUX = 0x45;
-> okey ich schau mal ins Datenblatt was der Typ von mir wollte
Bsp. 2
Code:
ADMUX = 0x01000101;
-> okey der typ hats mir leichter gemacht ich kann das Bitmuster auf das Register legen und seh was er macht
Bsp. 3
Code:
ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX2) ;
-> oh ja also er setzt zwei Mux register und ein Refs0, da ich schon mal mit nem Atmel gearbeitet hab weiß ich, dass es die Referenz sein muss und ein Mux Kanal
Ich schreibe es je nach Anwendungsfall mal so und mal so. Es hängt immer davon ab was mit dem Wert bewirkt werden soll. Ohne entsprechende Bemerkungen im Quelltext nutzt einem aber auch die beste Schreibweise mit "Mux0, ..." nix weil man dann trotzdem an manchen Stellen recht schnell im Wald steht. Darum steht bei mir normalerweise immer der Registeraufbau als Bemerkung über der Definitionszeile. Vernünftige Bemerkungen und Dokumentationen im Quelltext gehören einfach dazu.

Gruß
Dino
 
...genau weil man es den leuten Einfach machen will sind die #defines so aufgebaut damit ich (1<<Mux0) |(1<<Mux1) |(1<<Mux2) |(1<<Mux3) |(1<<Mux4) machen kann. Klar kannst du beim ADC auch = 5 machen, in dem falle ist es schön, dass es dann auf Kanal 5 geht :) (Mach aber mal etwas mit ner Uart oder sonstigen Registern ..)...
Ich mache das nicht, weil 5=ADC5 ist, sondern weil es Mode 5, also die 6te Zeile in der Tabelle ist.
Hmm.. UART0, ok... (ich hab hier grad das DB des 88er in der Hand, beim 8er sollte es ja ähnlich sein:
UDR0 - da machts keinen Sinn
UCSR0A und UCSR0B ebenso
UCSR0C - hier gibts die Bits UMSEL01 und UMSEL00 for den Operation Mode, dazu die Tabelle mit Mode 0=async, 1=sync, 2=reserved, 3=MSPIM. Wenn Du Dir also Deinen Mode rausgesucht hast, kannst Du Dir den als Preprozessor-Konstante definieren (.equ), und im späteren Programm verwenden:
Code:
LDI tempregister, (DeinMode<<UMSEL00)   ' ggf + weitere zu setzende Bits (|)
OUT UCSR0C, tempregister
Dasselbe dann beim Parity Mode (UPMN0)
Vorsicht ist bei der Anzahl der Datenbits gegeben - UCSZ02 befindet sich in UCSR0B - allerdings wird das lediglich bei 9 Databits benötigt, also eher selten. Genau genommen braucht man hier eh nie viel machen, da meist die defaultwerte des Registers passen.
UBRR0H/L - da man hier üblicherweise eh erst den Wert ausrechnet, kann der auch als ganzes in die Register eingetragen werden (wobei man das Ausrechnen bei vorgegebener Rate und Prozessertakt und so auch den Preprozessor machen lassen kann - mehr oder weniger gut)
...Zudem gibt unter Programmierern auch einen Programmierstil ;) und ein Sourcecode in dem Register direkt beschrieben sind tragen nicht umbedingt der Lesbarkeit zu =)....
Mache ich doch gar nicht. Ich fasse nur sinnig (!) zusammen. Warum soll "Bit MUX2 und Bit MUX0 und vielleicht noch weitere Bits (zusammen) gesetzt" einfacher zu lesen sein, als "alle Bits für MultiplexerMode5 und vielleicht noch weitere Bits/Modes (zusammen) gesetzt"? Insbesondere, wenn die Modes als Preprozessor-Variable... aber das hatten wir ja schon
...Bsp. 3
Code:
ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX2) ;
-> oh ja also er setzt zwei Mux register und ein Refs0, da ich schon mal mit nem Atmel gearbeitet hab weiß ich, dass es die Referenz sein muss und ein Mux Kanal....
Ist ja bei mir dasselbe, nur daß ich nicht mehr in der Tabelle suchen muß, sondern gleich die Zeilennummer hab
...Auch wenn beim ADC z.b. die 5 = Kanal 5 gibt ... mit ner 0x45 weißt immer noch nicht wass mit der 0x40 gemeint ist ...
man sollte in einem Programm eine Schreibweise haben, was machst jetzt wenn noch ne Uart und nen Timer dazu kommen dann wird das ganze etwas bunt .. ?!?...
eine 0x45 brauchste nicht zu shiften, so lange Tabellen gibts mMn nicht. Letztendlich sehe ich das auch eher so wie Dino, wobei ich das Zusammenfassen von zusammengehörenden Bits (Tabellen im DB) schon als "eine Schreibweise" empfinde. Letztendlich ist das genau dasselbe, wie das (Preprozessor-) shiften von Einzelbits. Ob ich sonst Hex-, Dezimal- oder Bitschreibweise verwende, kommt auch darauf an, was dieser Wert bedeutet. Da ich als Nichtinformatiker nicht in Hex- bzw Bitwelten aufgewachsen bin, rechne ich mit dezimalen Zahlen, wenn aber zB an einem Port gleichzeitig mehrere Pins den Zustand ändern sollen (hi/lo/pullup/offen), ist mir das Aufzählen und Shiften der einzelnen Bits auch zu umständlich. (Ich drucke mir als Haptiker meine Programme teilweise auch manchmal aus - da werden die Zeilenumbrüche bei 8 einzeln geshifteten Portbits auch nicht leserlicher.
...Wenns total unsauber machen willst machst es am bessten noch so
Code:
ADMUX = (1<<REFS0);
ADMUX |= 5;
Das ist C, gell? (auch wenn's in Bascom sicher ein ähnliches "Read Modify Write" ergeben würde.) Warum willst Du sowas machen? In Assembler halst Du das doch auch erst dem Preprozessor auf, und schiebst es dann ins Zielregister.

...und wieso ich sage unsauber ist ganz einfach ...
Code:
ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX2) ;
ergibt in ASM
Code:
544:       ADMUX = (1<<MUX0) | (1<<MUX2) | (1<<REFS0);
+00000204:   E485        LDI       R24,0x45       Load immediate
+00000205:   B987        OUT       0x07,R24       Out to I/O location

schöne 2 Instruktionen ......
Hmm... MUX0 und MUX2 gesetzt sind Mode 5. Bei mir wären das letztendlich exakt dieselben Zeilen, da der Preprozessor logischerweise auf dieselben Werte kommen sollte. Richtig ordentlich sollte es sein, wenn Du alle Möglichkeiten des MUX als Preprozessor-Variable definierst, und dann zB "(ADC5<<MUX0)|(AREF<<REFS0)" als immediate lädst. Aber das wäre letztendlich auch nur eine Erweiterung meiner Schreibweise.
Den Rest muß ich sicher nicht mehr kommentieren - das ist ein typisches Hochsprachenproblem...
 
naja um dem Offtopic mal hier ein ende zu setzen ^^,

(ADC5<<MUX0) <- da ADC5 (genauso wie AREF) kein standard in nem io file ist wäre es quatsch ein solches zu definieren ?!? ^^

Es mag für dich als Basecom/ASM User eventuell unlogisch klingen .. aber nur weil ich eine Sprache nicht verstehe meckere ich doch nicht an allem rum und mache es schlecht bzw wende es noch falsch an?!? ^^ Natürlich ist es C, nach dem das Topic "C: Temperaturmessung mit ATMega32" heißt und der Topic Opener ein C Programm gepostet hat und somit vermutlich C Hilfe will ... hilft es ihm in C ;)

Also bitte nicht falsch verstehen, aber hier in dem Post hat keine Grundsatzdiskussion zu suchen .. es geht hier in dem Post um eine Problematik in C und nicht um ASM oder Basic ... und wie es scheint konnten wir Marco ja helfen in dem die Temperatur auch auf dem Display angezeigt wird.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)