Hallo,
erstmal danke ich euch das ihr euch die Zeit nehmt mir zu Helfen.
Ich habe mir das Programm aus dem Tutorial genommen um den ADC vom
Atmega zu benutzen. Meine Taktfrequenz beträgt 12MHz, und ich kriege
alles einwandfrei auf dem Hyperterminal, also mit einer Spannung von
3,8V (mit der mein µC betrieben wird) kriege ich eine Zahl von 1023.
Das Programm sieht folgendermaßen aus:
sbic ADCSRA, ADSC ; wenn der ADC fertig ist, wird dieses Bit gelöscht
47
rjmp wait_adc
48
49
; ADC einlesen:
50
in adlow, ADCL ; immer zuerst LOW Byte lesen
51
in adhigh, ADCH ; danach das mittlerweile gesperrte High Byte
52
53
; alle 256 ADC-Werte addieren
54
add temp2, adlow ; addieren
55
adc temp3, adhigh ; addieren über Carry
56
adc temp4, temp1 ; addieren über Carry, temp1 enthält 0
57
dec temp5 ; Schleifenzähler MINUS 1
58
brne sample_adc ; wenn noch keine 256 ADC Werte -> nächsten Wert einlesen
59
60
; Aus den 256 Werten den Mittelwert berechnen
61
; Bei 256 Werten ist das ganz einfach: Das niederwertigste Byte
62
; (im Register temp2) fällt einfach weg
63
;
64
; allerdings wird der Wert noch gerundet
65
cpi temp2,128 ; "Kommastelle" kleiner als 128 ?
66
brlo no_round ; ist kleiner ==> Sprung
67
68
; Aufrunden
69
subi temp3, low(-1) ; addieren von 1
70
sbci temp4, high(-1) ; addieren des Carry
71
72
no_round:
73
; Ergebnis nach adlow und adhigh kopieren
74
; damit die temp Register frei werden
75
mov adlow, temp3
76
mov adhigh, temp4
77
78
;in ASCII umwandeln
79
outp:
80
ldi temp5, -1 + '0'
81
_a6ser:
82
inc temp5
83
subi adlow, low(10000) ; -10,000
84
sbci adhigh, high(10000)
85
brcc _a6ser
86
87
ldi temp6, 10 + '0'
88
_a7ser:
89
dec temp6
90
subi adlow, low(-1000) ; +1000
91
sbci adhigh, high(-1000)
92
brcs _a7ser
93
94
ldi temp7, -1 + '0'
95
_a8ser:
96
inc temp7
97
subi adlow, low(100) ; -100
98
sbci adhigh, high(100)
99
brcc _a8ser
100
101
ldi temp8, 10 + '0'
102
_a9ser:
103
dec temp8
104
subi adlow, -10 ; +10
105
brcs _a9ser
106
subi adlow,-'0'
107
108
;an UART Senden
109
mov temp1, temp5 ; Zehntausender Stelle
110
rcall transmit
111
mov temp1, temp6 ; Tausender Stelle
112
rcall transmit
113
mov temp1, temp7 ; Hunderter Stelle
114
rcall transmit
115
mov temp1, temp8 ; Zehner Stelle
116
rcall transmit
117
mov temp1, adlow ; Einer Stelle
118
rcall transmit
119
ldi temp1, 13 ; CR
120
rcall transmit
121
ldi temp1, 10 ; LF
122
rcall transmit
123
124
rjmp Main
125
126
transmit:
127
sbis UCSRA,UDRE ; Warten, bis UDR bereit ist ...
128
rjmp transmit
129
out UDR, temp1 ; und Zeichen ausgeben
130
ret
Meine Frage lautet nun, wie ich das Programm so umschreiben könnte, dass
ich 3 Spannungen an 3 verschiedenen Ports messen und ausgeben kann.
Theoretisch könnte ich mir am Anfang einfach weitere Register definieren
und die Schleife, in der der Wert des ADC berechnet wird einfach 3 mal
ausführen mit verschiedenen "temp-s". Wie viele Register stehen mir zur
Verfügung? Oder kennt wer einen eleganteren Weg dies zu realisieren?
Wäre sehr dankbar für hilfreiche Tipps. Danke im vorhinein.
@ Aladin Mujovic (djas020)
>Meine Frage lautet nun, wie ich das Programm so umschreiben könnte, dass>ich 3 Spannungen an 3 verschiedenen Ports messen und ausgeben kann.
Naja, dazu musst du die MUX im ADC auf einen anderen Kanal schalten und
dann ganz normal wie jetzt auch messen.
MFG
Falk
Das ist also das hier:
ldi temp1, (1<<REFS0) ; Kanal 0, interne Referenzspannung 5V
out ADMUX, temp1
ldi temp1, (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)
out ADCSRA, temp1
ok, dann schreibe ich das halt 3 mal und nenne es temp1,temp2,temp3 -
aber wenn ich dann die berechnung durchführe, wie weiss ich welcher
kanal vom adc in welchem register ist?
@ Aladin Mujovic (djas020)
>ok, dann schreibe ich das halt 3 mal und nenne es temp1,temp2,temp3 ->aber wenn ich dann die berechnung durchführe, wie weiss ich welcher>kanal vom adc in welchem register ist?
???
Es gibt nur ein Register für die ADC-Daten.
MfG
Falk
Wenn ich jetzt den MUX 3 mal anspreche, wie weiss ich wo ich mich grade
befinde, das ich die daten dann in die vordefinierten plätze also wie
gesagt temp1,temp2,temp3 reinkopieren kann und nachher ausgeben?
@ Aladin Mujovic (djas020)
>Wenn ich jetzt den MUX 3 mal anspreche, wie weiss ich wo ich mich grade>befinde, das ich die daten dann in die vordefinierten plätze also wie>gesagt temp1,temp2,temp3 reinkopieren kann und nachher ausgeben?
???
Kann es sein, dass du das Programm einfach nur k_O_piert hast, ohne es
ein Stückchen zu k_A_pieren?
Das Prinzip ist doch immer das gleiche.
ADC MUX programmieren
AD-Wandlung vornehmen
Messwert in ASCII wandeln und zum PC senden
Wo ist das Problem?
Wenn dein Programm jweil die MUX setzt, "weiss" es doch, welchem Kanal
die Daten entsprechen.
Du musst also dein Programm, was jetztgerade durchläuft, sinnvoll in
Unterprogramme aufteilen.
MFg
Falk
@ Aladin Mujovic (djas020)
>du verstehst meine frage nicht..
Das liegt vielleicht auch daran, dass du dich falsch ausdrückst.
>ich meine wieviele rxx stehen mir zur verfügung? von r16 bis?
Ahhhh, wieviele Register die CPU hat? Steht im Datenblatt.
>32 gibt es insgesamt oder?
Ja. r0..r31.
MFG
Falk
P.S. Kleiner Tip. R16..R31 sind die "besseren" Register, weil nur mit
diesen alle Befehle funktionieren. ldi und einige andere gehen NICHT mit
r0..r15.
das genau ist ja jetzt das problem, ich brauche für jeden spannungswert
8 registerplätze, es stehen mir zwar 32 zur verfügung, würde sich von
der zahl her ausgehen..nur kann ich für meine befehle nur die register
r16 bis r31 benutzen..
@ Aladin Mujovic (djas020)
>das genau ist ja jetzt das problem, ich brauche für jeden spannungswert>8 registerplätze, es stehen mir zwar 32 zur verfügung, würde sich von>der zahl her ausgehen..nur kann ich für meine befehle nur die register>r16 bis r31 benutzen..
Das sollte doch wohl reichen, oder? Die Lösung deines "Problems" lautet
SRAM.
AVR-Tutorial: SRAMAVR-Tutorial: Speicher
MfG
Falk
>das genau ist ja jetzt das problem, ich brauche für jeden spannungswert>8 registerplätze, es stehen mir zwar 32 zur verfügung, würde sich von>der zahl her ausgehen..nur kann ich für meine befehle nur die register>r16 bis r31 benutzen..
Wenn du die volle Auflösung (10 bit) benötigst, brauchst du nur 2
Register pro Spannungswert. Nach der Verarbeitung speichert man die
Werte im RAM.
MW
könnt ihr euch bitte das programm anschauen, was ich eingefügt habe..
ich weiss nicht wie das reichen kann, weil ich brauche ja für eine
berechnung
.def temp1 = r16
.def temp2 = r17
.def temp3 = r18
.def temp4 = r19
.def adlow = r20
.def adhigh = r21
.def temp5 = r22
.def temp6 = r23
.def temp7 = r24
.def temp8 = r25
10 Register
Wenn ich diese berechnung jetzt 3 mal wiederhole, auf 3 verschiedenen
kanälen, brauche ich dann 30.
aber r0 bis r15 unterstützen befehle wie ldi nicht, die die ich brauche
(glaube ich). oder?
Ich kann nur noch mal auf Falks Hinweis verweisen: Der Mega8 hat 1 KiB
SRAM, da kannste gaaaanz viele Werte speichern. Eine Operation kann
immer nur maximal zwei Werte betreffen. Wenn Du 10-Bit-Werte hast (also
2 Bytes pro Wert), dann brauchst Du wahrscheinlich für keine Operation
mehr als 4 oder 5 Register! Und mit ein bisschen Hin-und-herschieberei
sogar noch weniger...
Also wenn Du die (ADC- oder Ergebnis-) Werte unbedingt für längere Zeit
speichern must, dann nehme SRAM wie oben schon angeklungen.
Wenn nicht, dann hole doch immer nur einen ADC-Wert, berechne den, mache
irgendwas mit dem Ergebnis, dann hole den nächsten (in die selben
register), berechne den wieder, mache wieder was mit dem Ergebnis, hole
den nächsten .... usw.
@ Aladin Mujovic (djas020)
>10 Register>Wenn ich diese berechnung jetzt 3 mal wiederhole, auf 3 verschiedenen>kanälen, brauche ich dann 30.
HALLLOOOOOOO!!!!
Hast du die Artikel mal gelesen? Und verstanden? Und hast du dich mal
ein wenig mit den Grundlagen der Programmierung beschäftigt?
In den CPU Registern hält nam nur die Daten, die man für die im Moment
auszuführende Operation benötigt. Alles andere liegt Variablen im RAM.
Und wenn du dreimal die Funktion aufrufen willst, braucht du nicht 30
Register, sonder nur 10, weil ja die Berechnung NACHEINANDER erfolgt.
MFG
Falk
ok.. tut mir leid das ich mich wenig damit auskenne.
was soll ich deiner meinung nach machen?
ich definiere anfangs die 10 register. spreche den kanal im mux an,
mache die berechnung, gebe den wert aus. springe auf den nächsten
kanal,berechnung,ausgabe, springe auf den dritten, berechnung ->
ausgabe.
passt?
@ Aladin Mujovic (djas020)
>was soll ich deiner meinung nach machen?
Das habe ich mehrfach geschrieben. LESEN!
>ich definiere anfangs die 10 register. spreche den kanal im mux an,>mache die berechnung, gebe den wert aus. springe auf den nächsten>kanal,berechnung,ausgabe, springe auf den dritten, berechnung ->>ausgabe.>passt?
So in etwa.
MFG
Falk