Hallo,
ich habe mich schon durch die Suche gewühlt aber bisher nichts
gefunden...
Ich habe folgendes, einfaches Problem: Ich möchte 2 ADC-Werte auslesen
und verarbeiten. Aber es lässt sich nur einer auslesen. Sobald ich beide
in der main lesen lasse ist der Wert 0... Ich denke mal es liegt an der
Konfiguration des ADC. Aber ich finde nicht den Fehler...
Der Code sieht so aus:
.include "tn13def.inc"
.def temp1 = r16
.def timer1 = r17
ldi temp1, LOW(RAMEND)
out SPL, temp1
;Hardware
sbi DDRB,0 ;FET
sbi DDRB,1 ;LED gelb (0-an)
sbi DDRB,3 ;LED rot (1-an)
cbi PORTB,0
sbi PORTB,1
cbi PORTB,3
init:
ldi temp1, 0b10000011 ; ADC enable / f=150kHz
out ADCSRA, temp1
ldi temp1, 0b00000000 ; Analog Komperator aus / Timer Compare Match
out ADCSRB, temp1
ldi temp1, 0b10000011 ; Analog Komperator aus
out ACSR, temp1
ldi temp1, 0b01000001 ; Int.1,1V ref ADLAR-0 ADC1
out ADMUX, temp1
ldi temp1, 0b00010100 ; Digital Input Disable
out DIDR0, temp1
main:
rcall tcheck
rcall ucheck
rjmp main
ucheck:
ldi temp1, 0b01000001 ; Int.1,1V ref ADLAR-0 ADC1
out ADMUX, temp1
sbi ADCSRA, ADSC ; ADC start
ucheck1:
sbis ADCSRA, ADIF
rjmp ucheck1
in YL, ADCL
in YH, ADCH
mov temp1, YH
clc
subi temp1, 0x10
brcs stop
ret
tcheck:
ldi temp1, 0b01100010 ; Int.1,1V ref ADLAR-1 ADC2
out ADMUX, temp1
sbi ADCSRA, ADSC ; ADC start
tcheck1:
sbis ADCSRA, ADIF
rjmp tcheck1
in YL, ADCL
in YH, ADCH
mov temp1, YH
clc
subi temp1, 0x46
brcs stop ; Utemp > 270mV (>60°)?
ret
stop:
sbi PORTB,1 ; LED aus
sbi PORTB,3 ; LED an
rjmp stop
sbis ADCSRA, ADIF
rjmp ucheck1
Nimm zum Checken ob der ADC fertig ist, das ADSC Bit.
Du setzt es um den ADC zu starten und wenn er fertig ist, setzt er es
zurück.
Das ADIF Flag müsstest du aktiv löschen, was du nicht tust.
Die Spannungen müssen über bestimmten Pegeln liegen
(Temperatursensoren).
Wenn die unterschritten sind, soll die rote LED angehen und Feierabend
sein.
sbis ADCSRA, ADIF
Ich hatte mal auf nem Mega8 4 ADC's hintereinander mit dem gelesen, da
hatte es geklappt... habs aber auch mal so probiert... klappt immer nich
nicht :(
erreichen?
Das High Byte kann maximal 3 werden. Oder hast du ADLAR gesetzt?
Warum machst du es dir und deinem Leser so schwer, rauszukriegen was du
gesetzt hast?
1
lditemp1,0b01000001;Int.1,1VrefADLAR-0ADC1
sowas wie ADLAR-0 oder ADLAR-1 gibt es nicht.
wo sieht man leichter was du im Register eingeschaltet hast?
Deine Version,
Sorry, wenn das Kommentar nicht so toll ist. Ich dachte, das reicht hin.
Ja das ADLAR ist da drin gesetzt. Und das clc hatte ich noch drin um
alles auszuschließen.
Sebastian F. schrieb:> Sorry, wenn das Kommentar nicht so toll ist. Ich dachte, das reicht hin.> Ja das ADLAR ist da drin gesetzt.
Nein ist es nicht.
In
1
lditemp1,0b01000001;Int.1,1VrefADLAR-0ADC1
ist ADLAR nicht gesetzt.
Daher nochmal der Appell:
Schreibs so
da ich mich mit der schreibung so ca. 0 auskenne, schreibe ich das so.
Bei dem tcheck ist ADLAR gesetzt, bei ucheck nicht. Das ist absicht.
Aber es ist auch egal, ob es gesetzt ist oder nicht. Die Spannung ist
auf jeden Fall höher als der Wert, der angegeben ist.
Sebastian F. schrieb:> da ich mich mit der schreibung so ca. 0 auskenne, schreibe ich das so.
Jetzt weißt du es, dass das besch...eiden ist und schwenkst um auf die
bessere Schreibweise.
> Bei dem tcheck ist ADLAR gesetzt, bei ucheck nicht. Das ist absicht.
Wie soll dann bitte im High Byte vom ADC jemals etwas größeres als 0x10
rauskommen?
> Aber es ist auch egal, ob es gesetzt ist oder nicht. Die Spannung ist> auf jeden Fall höher als der Wert, der angegeben ist.
Wenn ADLAR nicht gesetzt ist, kann das High_byte vom ADC nur die Werte
0, 1, 2, 3 haben. Andere Werte sind nicht möglich! Ohne ADLAR ist es
völlig ausgeschlossen, dass du im High Byte jemals 16 oder gar noch
größere Werte vorfinden wirst.
Sebastian F. schrieb:> mov temp1, YL> subi temp1, 0x15> brmi stop
Du willst hier BRLO benutzen und nicht BRMI
BRLO ist für vorzeichenlose Zahlen, BRMI für Vorzeichenbehaftete.
Die Notation vorzeichenbehaftete Zahlen ist aber hier unangebracht, wenn
du nur das Low-Byte einer Zahl betrachtest. Bit 7 hat hier nicht die
Funktion eines Vorzeichens.
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Vergleiche#Bedingte_Spr.C3.BCnge
Das nützt Dir nix, das N-Flag ist nur eine Kopie von Bit 7.
Schau in der Beschreibung des Befehlssatzes an, welcher Branch welche
Flags berücksichtigt.
Sebastian F. schrieb:> Ist das nicht egal, wenn durch das "subi" die entsprechenden Flags> gesetzt werden? Auch wenns unkoventionell ist frage ich ja einfach das> N-Flag ab.
Du rechnest eine Subtraktion.
Wenn dein ADC Wert 0x0192 also dezimal 402 ist, dann ist das Low-Byte
davon 0x92. Da in dieser Zahl das 7. Bit gesetzt ist, ist das für BRMI
eine negative Zahl. Selbst wenn du dann noch 0x10 davon abziehst, ist es
immer noch eine negative Zahl.
Nimm die richtigen Befehle für den richtigen Datentyp.
Du hast hier kein Vorzeichen! Also benutz auch nicht die Abfragen für
vorzeichenbehaftete Zahlen.
Du willst feststellen, ob es bei der Subtraktion einen Unterlauf gab.
Zuständig dafür ist BRLO oder BRCS
So, ich habe alles mal nach den Tipps geändert.
Aber leider ist es nach wie vor so, dass der erste ADC funktioniert aber
der zweite springt immer in die stop-Schleife.
Im Simulator funktioniert alles.
Habe ich vielleicht bei der Initialisierung einen Fehler?
ucheck:
ldi temp1, (0<<ADLAR) | (0<<MUX1) | (1<<MUX0)
out ADMUX, temp1
sbi ADCSRA, ADSC ; ADC start
ucheck1:
sbic ADCSRA, ADSC
rjmp ucheck1
in YL, ADCL
in YH, ADCH
mov temp1, YL
subi temp1, 0x15
brcc stop1
ret
tcheck:
rcall loop
ldi temp1, (1<<ADLAR) | (1<<MUX1) | (0<<MUX0)
out ADMUX, temp1
sbi ADCSRA, ADSC ; ADC start
tcheck1:
sbic ADCSRA, ADSC
rjmp tcheck1
in YL, ADCL
in YH, ADCH
mov temp1, YH
subi temp1, 0x46
brcs stop2
ret
stop1:
sbi PORTB,3 ; LED rot an
rjmp stop1
stop2:
cbi PORTB,1 ; LED gelb an
rjmp stop2
Schau mal hier:
Beitrag "Re: Spannungsmesserbau mit XMega128"
Da werden zwei ADCs des Tiny24 ausgelesen und deren Werte separat
aufgearbeitet und angezeigt.
Es schadet Dir vermutlich nicht, auch mal etwas auf den dortigen
Programmierstil zu achten.
...
Hi
> in YL, ADCL> in YH, ADCH> mov temp1, YL> subi temp1, 0x15> brcc stop1
Diese Abfrage ist nicht eindeutig. Der Fall, das YL<$15 ist tritt bei
10Bit, wenn ich mich nicht verrechnet habe, 88 mal auf. Ausserdem gibt
es Vergleichsbefehle (
Mach eine eindeutige Abfrage:
Das andre was ich tun würde.
Ich würde erst mal nicht 'stoppen' wenn der ADC Wert zu klein ist,
sondern beim Unterschreitung 1 LED ein bei Überchreiten des Grenzwerts
die LED wieder ausschalten.
Den 2. ADC würde ich zunächst mal links liegen lassen und mich nur auf 1
konzentrieren. Wenn irgendwie geht, dann die restlichen Pins vom Tiny
ebenfalls mit LED bestücken und mir den ADC Wert dort so gut es geht
ausgeben lassen. Ziel ist es, herauszufinden, ob vom ADC überhaupt
sinnvolle Werte kommen.
Im Moment stocherst du im Nebel, und da musst du Abhilfe schaffen, indem
du irgendwie an den Messwert rannkommst. Und zwar in echt und nicht im
Simulator.
Du hast das klassische Problem: zuviel auf einmal geschrieben, nichts
funktioniert und jetzt weißt du nicht wo du mit der Suche anfangen
sollst.
Alle anderen Pins sind belegt. Wie gesagt, den ADC1 kann ich problemlos
lesen/auswerten. Habe ja so umgeändert, dass bei nem Fehler eine der
LEDs angeht. Werde mal nen blink-Zähler für den 2.ADC reinbauen...
Das weiss ich, wenn ich in der main-Schleife das tcheck wegmache und
eine Spannung drauf gebe, mit dem Oszi kontrolliere, und beobachte was
passiert...
0V - kein Problem, geht wieder raus(Dauerloop). 25mV - springt in die
Stopschleife und die LED geht an. Wenn ich die tcheck- Schleife
dazunehme geht die andere LED an... also warum sollte die erste nicht
funktionieren?
Hi
>Warum $0115? Es gibt YL & YH. Beide maximal 255. Ich frage doch nur YH>ab, wo Bit 3-10 sind...
Meine Aussage bezieht sich auf dein 'ucheck'. Du springst nach 'stop'
wenn YL >=$15 ist. Und das passiert wenn der ADC Werte von
$0015...$00FF, $0115...01FF,$0215...02FF und $0215...02FF liefert.
MfG Spess
Wenn ADC1 > 22mV dann stop1
Wenn ADC2 < 300mV dann stop2
Ist es das was, Du willst ?
Außerdem, besteht die Möglichkeit, daß ADC1 gleich zu Beginn > 275mV ist
? Denn das könnte aufgrund der Auswertung einzig des LB nicht erkannt
werden.
Genau, das ist das was ich will.
ADC1 kann am Anfang nur 0V sein, da ich nichts angeschlossen habe. An
dem Port hängt über 10k ein 0,2 Ohm Widerstand auf Masse.
Sebastian F. schrieb:> Genau, das ist das was ich will.> ADC1 kann am Anfang nur 0V sein, da ich nichts angeschlossen habe. An> dem Port hängt über 10k ein 0,2 Ohm Widerstand auf Masse.
Du musst deine Teststategien verbessern.
Wie unterschiedest du den Fall davon, dass du einen Programmfehler hast
und der ADC aufgrund dieses Programmfehlers 0 liefert?
Schmeiss den Widerstand raus (und was du sonst noch drann hängen hast)
und bau mit einem Poti einen Spannungsteiler auf. Damit speist du eine
bestimmte Spannung in den ADC ein (Poti deshalb weil es dann beim
nächsten Programmlauf einigermassen reproduzierbar ist solange du nicht
am Poti drehst. Und das ist das Um und Auf in der ganzen Debuggerei:
Reproduzierbarkeit)
Dann legst du dir das High Byte vom ADC (wenn ADLAR ausgeschaltet ist),
bzw. die obersten beiden Bits vom High Byte (wenn ADLAR eingschaltet
ist) auf die beiden LED. Beim Durchdrehen des Potis (und damit verändern
der SPannung am ADC Eingang von 0 bis 1.1V) müssen die beiden LED die
Binärzahlen 0 bis 3 anzeigen. Und zwar korrelierend mit deiner Poti
Stellung. Erst dann hast du die Gewissheit, dass deine ADC
funktionieren. Ehe ich das nicht sehe, würde ich mich auf keinen Fall
auf irgendetwas festlegen wollen.
Wenn möglich würde ich sogar noch eine dritte LED dazunehmen (selbst
wenn das bedeutet, dass ich andere Hardware temporär abklemmen muss) und
natürlich dann die obersten 3 Bit jedes Ergebnisses. Die LED zeigen mir
dann 8 Stufen vom ADC an.
Du testest beide ADC unabhängig voneinander, damit du die vorhandenen
LED für 1 ADC einsetzen kannst.
Und erst dann, wenn ich mich davon überzeugt habe, dass die ADC
brauchbare Werte liefern, erst dann geht es daran, diese Werte in
irgendeiner Form auszuwerten.
Jupp, die Spannung passt.
Aber ich werde das jetzt so machen, wie Hr. Buchegger das vorschlägt:
Ich mache eine nue Platine mit entsprechend 2 Potis und der Rest
LED's...
Meld mich dann gleich wieder :)
> Problem: Ich füge es 1:1 in das Originalprogramm ein und nix geht :(
Dann würd' ich vorschlagen den Code so zu posten wie er geht und einmal
das Originalprogramm in letzter Fassung, wie's nicht geht.
Einen guten Montag morgen wünsche ich.
Ich füge der Einfachheit halber mal die Programme in Dateien ein.
Das Testprogramm läuft. Auch wenn ich die LED's hin und hersetzte.
Das Hauptprogramm springt immer in die Stop Routine...
Kleines update: Hatte am Freitag ein Testprogramm, das lief. Aber aus
versehen gelöscht. Jetzt funktioniert es doch nicht mehr... trotz dass
ich die ADC's wechsel wird irgendwie ein Mischmasch aus beiden
ausgegeben... ??? Die Bits werden angezeigt und hochgezählt. Und je nach
Poti, das ich drehe werden dann die LED's noch ein wenig heller...
Ich würd die Stop-Condition erstmal weglassen und eine Led setzen, um
den Status zu sehen. Ansonsten würd' ich nach Einschalten des Wandlers
entweder eine Dummy-Messung machen, oder ein Delay bis zur ersten
Messung setzen. Alternative ist immer zwei Wandlungen ausführen und
erste verwerfen.
> Kleines update: Hatte am Freitag ein Testprogramm, das lief. Aber aus> versehen gelöscht.
Was soll das heißen ? Daß die gepostete test.asm jetzt nicht als
funktionierend zu betrachten ist ? Deas ist schon alles etwas konfus.
Ein wenig mehr Zielgerichtetheit würde nicht schaden.
Ich bin wieder beim Testprogramm...
Das läuft, wenn ich eine Zählschleife & Doppelt lesen mache... Wenn
eines von beiden nicht ist, funktionierts auch nicht... OK,
Geschwindigkeit ist mir nicht wichtig.
Jetzt habe ich nichts geändert, ausser meine Zahlen abzuziehen... und es
passt nicht. Die LED, die angesprochen wird bei den jewailigen Poti
leuchtet... aber bei 20mV. Nicht die eine bei 20mV und die andere bei
300mV...
Wo ist da der Fehler???
Wird das jetzt Programmieren durch Raten ? Du solltest gezielt aufbauen,
sonst wird das nix.
Darf ich mir jetzt eine der zwei Versionen aussuchen ? :D
Bei test.asm verwendest Du zweimal ADCH zum Vergleich, das "Konzept" war
vorher ein anderes, bei test2.asm sollte Led2 sofort bei Poti = 0V
angehen. Diese Led ist ja für jeden Wert unterhalb 0x46 an und geht erst
ab diesem Wert aus.
Steht übrigens nirgends im DB, daß die Werte aus dem ADC geholt werden
müssen, wenn man sie nicht benötigt.
Das Problem vorhin bestand daraus daß beim ersten Start des ADC das
Setzen des ADSC Bits den AD Converter initialisiert, so im DB des Tiny13
nachzulesen. Wenn man dann dieses Ergebnis dann hernimmt und sofort in
eine Endlosschleife rennt, braucht man sich über die Nichtfunktion nicht
zu wundern.
An Deiner Stelle würde ich erst mal mehr die Basics üben, Tutorials
durcharbeiten, DB lesen, usw., etwas zu dem ich angesichts der gezeigten
Programmiererei ernsthaft raten würde.
Das ist kein programmieren durch raten. Das Test.asm funktioniert. Das
Test2.asm funktioniert nicht.
Ich hatte ganz am Anfang (1.Post) mal gefragt, ob ich beim
initialisieren vielleicht einen Fehler habe. Aber anstatt von einem
einfachen Tipp wurde ja gleich auf allem anderen rumgehackt. Ich bin
kein Programmierer..
Das ADSC-Bit setzte ich nicht, ich lese es aus - was mir hier geraten
wurde...
> Das ADSC-Bit setzte ich nicht,
Und wie soll der ADC arbeiten, wenn Du ihn nicht (durch Setzen des
ADSC-Bits) startest???
> ich lese es aus
Das hat nur Sinn, wenn Du es zuvor gesetzt hast.
> - was mir hier geraten> wurde...
Ja, Dir wurde geraten, statt des Interrupt-Pending-Flags des ADC das
ADSC-Flag auszulesen, da dies einfacher ist. Und dieser Rat ist richtig,
da Du den ADC ja nicht mittels Interrupt betreiben möchtest.
- Du setzt das ADSC-Bit per Programm
- Der ADC beginnt zu "rattern" (arbeitet seinen Zyklus ab)
- Wenn der ADC fertig ist, löscht er das ADSC-Bit und setzt das ADIF-Bit
Das ADIF-Bit sorgt in Verbindung mit dem ADIE-Bit für das Auslösen eines
Interrupts, da Du diese Betriebsart nicht nutzt, musst Du Dich darum
nicht kümmern.
So, nun zu Deinem Code.
Nehmen wir z.B. diese Sequenz:
Du setzt also Messquelle, Referenzquelle und Formatierung (ADMUX). Ich
habe es jetzt nicht überprüft, gehe aber davon aus, dass es richtig ist.
Dann setzt Du ADSC in ADCSRA, worauf der ADC die Arbeit aufnimmt. Das
ADSC-Bit bleibt solange gesetzt, bis der ADC fertig ist, dann löscht der
ADC dieses Bit per Hardware.
Nun fragst Du das ADSC-Bit ab:
sbis adcsra,adsc (Skip, if Bit in I/O is set, also überspringe den
folgenden Befehl, wenn das Bit gesetzt ist)
Das Bit ist natürlich (noch) gesetzt, denn der ADC ist ja noch nicht
fertig. Also hüpft das Programm über den Rücksprung (Schleife)
drüberweg, liest den noch nicht vorhandenen Messwert aus und geht zur
Tagesordnung über.
Haste nun gemerkt, dass Deine Bedingung logisch falsch ist? Anstatt zu
warten, bis der ADC fertig ist, springst Du weiter, solange er noch
beschäftigt ist. Und da Du bereits über alle Berge bist, wenn der ADC
irgendwann mal fertig wird, wirst Du es nie bemerken (dass er fertig
ist).
In ucheck2 ist natürlich derselbe Fehler. Den Rest habe ich nicht
genauer untersucht, da ich mich mit Deinem Konzept nicht anfreunden
kann. Ich programmiere anders. Und ich bin (von der Ausbildung her) auch
kein Programmierer, ich mache das auch nur als Hobby.
Viel Erfolg.
MfG
@kluchscheisser, Respekt, das entging mir, das falsche sbis hätte ich
sehen müssen ;-)
@snake080, das war nicht böse von mir gemeint, ich vermisste nur eine
gewisse Kontinuität in Deinen Programmierbemühungen :D
> Nun isser eingeschnappt...
Würd' eher sagen, die Schaltung geht jetzt, und damit entfällt aus Sicht
des TO's jegliche weitere Kommunikationsnotwendigkeit. Jedenfalls
solange bis das nächste Problem ansteht...
Hi, bei beiden falsch getippt. :)
Ich konnte nicht weiter probieren, da ich einen Anruf bekommen habe,
dass meine Steine für die Garage da sind. Ergo - Früh Feierabend &
Urlaub. Am Freitag bin ich wieder dran. Das mit dem checken von dem
"sbis" war schon ein super Tipp. Aber irgendwas hatte noch nicht ganz
geklappt.
Erst mal Danke an euch, die mir helfen!!!