hallo, ich will mit dem atmega8 2 analoge signale kontinuierlich umwandeln und das ergebnis im sram für weitere verarbeitung zur verfügung stellen. mache sowas zum ersten mal und scheitere schon an der initialisierung. mit einem kanal ist es klar. mit ADPS vorteiler einstellen mit ADEN generell einschalten in ADMUX kanal wählen mit ADFR free run wählen mit ADSC umwandlung starten aber wie soll ich das machen wenn ich zwei eingänge kontinuierlich abfragen will? gruß jens
Gleichzeitig beide Kanäle abzufragen ist nicht möglich. Die einfachste Lösung ist, bei jedem Auslesen des ADC-Wertes ADMUX neu zu schreiben. So bekommst du immer abwechselnd die Werte von beiden Eingängen.
@Jens: Der AVR hat nur einen ADC mit einem vorgeschalten 8-kanal-Multiplexer. So ist es nicht mgöich, mehrere Kanäle gleichzeitig zu messen. Dafür bräuchte man dann externe Lösungen...
na gut, das konnte ich mir denken, aber wie soll ich es realisieren, die eingänge hintereinander fortlaufend abzufragen, wenn ich doch immer nur einen eingang im admux setzen kann, soll ich die allg. einstellungen enable, vorteiler, free run... separat initialisieren und dann jeweils vor der abfrage nur admux auf den nächsten eingang umschreiben? mir fehlt etwas die vorstellungskraft. gruß jens
Seite 197 im Datenblatt "Changing Channel or Reference Selection" Solange eine Messung durchgeführt wird, kann man zwar den Kanal etc. wechseln, die Änderung wird aber erst aktiv, sobald die Messung beendet ist. Du wartest das Ende der Messung ab, und startest eine neue mit geänderten Einstellungen, nachdem du die ADC-Werte gespeichert hast. Das kannst du entweder als konstante Abfrage des ADIF-Bit oder in der Interrupt-Service-Soutine machen. Beim Auftreten des Interrupts wird im free-running-mode IMHO sofort die neue Messung gestartet. Sprich, wenn man die Einstellungen in der ISR ändert, dann wird noch eine Messung mit den alten Einstellungen durchgeführt. Das ist auch irgendwo im Datenblatt beschrieben...
kann ich das auch ohne interrupt lösen? habe das mit den interrupts noch nicht so geschnallt. wollte über polling abfragen, aber dann nützt mir ja das adif bit nichts, oder? gruß jens
Das einfachste ist eine Schleife: { ADC-Eingang setzen Messung starten Ende der Messung abwarten Werte sichern Parameter ändern (z.B. Feldindex und dergl.) } wiederholen
also wenn ich das richtig verstanden habe so in etwa: main: ldi r16, lo8(RAMEND) out SPL, r16 ldi r16, hi8(RAMEND) out SPH, r16 ;Initialisierung ADC ldi r17, 0b10000... ;ADC enable, vorteiler out ADCSRA, r17 ;---------------------------------------------------------------------ma inloop: wdr rjmp loop rjmp save rjmp mainloop ;--------------------------------------------------------------------- ;ersten eingang umwandeln und sichern loop: ldi r16, 0 ;auswahl chanel 0 out ADMUX, r16 sbi ADCSRA, ADSC ;wandlung starten warte1: sbis ADCSRA, ADIF ;abfrage ob umwandlung schon beendet rjmp warte1 in r18, ADCL ;die unteren 8bits in r18 speichern in r19, ADCH ;die oberen 2bits in r19 speichern ;zweiten eingang umwandeln und sichern ldi r16, 1 ;auswahl chanel 1 out ADMUX, r16 sbi ADCSRA, ADSC ;wandlung starten warte2: sbis ADCSRA, ADIF ;abfrage ob umwandlung schon beendet rjmp warte2 in r20, ADCL ;die unteren 8bits in r20 speichern in r21, ADCH ;die oberen 2bits in r21 speichern ret ;gesicherte werte in sram speichern save: ... ret wenn das so stimmt, wie bekomme ich dann die r18-r21 in den sram? geht das überhaupt so einfach? gruß jens
also wenn ich das richtig verstanden habe so in etwa:
1 | main: ldi r16, lo8(RAMEND) |
2 | out SPL, r16 |
3 | ldi r16, hi8(RAMEND) |
4 | out SPH, r16 |
5 | |
6 | ;Initialisierung ADC |
7 | ldi r17, 0b10000... ;ADC enable, vorteiler |
8 | out ADCSRA, r17 |
9 | |
10 | |
11 | ;--------------------------------------------------------------------------- |
12 | mainloop: wdr |
13 | rjmp loop |
14 | rjmp save |
15 | rjmp mainloop |
16 | ;--------------------------------------------------------------------------- |
17 | ;ersten eingang umwandeln und sichern |
18 | loop: ldi r16, 0 ;auswahl chanel 0 |
19 | out ADMUX, r16 |
20 | sbi ADCSRA, ADSC ;wandlung starten |
21 | warte1: sbis ADCSRA, ADIF ;abfrage ob umwandlung schon beendet ist |
22 | ADIF=1 |
23 | rjmp warte1 |
24 | in r18, ADCL ;die unteren 8bits in r18 speichern |
25 | in r19, ADCH ;die oberen 2bits in r19 speichern |
26 | |
27 | ;zweiten eingang umwandeln und sichern |
28 | ldi r16, 1 ;auswahl chanel 1 |
29 | out ADMUX, r16 |
30 | sbi ADCSRA, ADSC ;wandlung starten |
31 | warte2: sbis ADCSRA, ADIF ;abfrage ob umwandlung schon beendet ist |
32 | ADIF=1 |
33 | in r20, ADCL ;die unteren 8bits in r20 speichern |
34 | in r21, ADCH ;die oberen 2bits in r21 speichern |
35 | ret |
36 | ;gesicherte werte in sram speichern |
37 | save: |
38 | ... |
39 | ret |
wenn das so stimmt, wie bekomme ich dann die r18-r21 in den sram? geht das überhaupt so einfach? gruß jens
ich denke das sollte soweit hinkommen, aber warum zeigt mir der compiler in den zeilen mit dem adsc und adif bit dies an: constant value required gruß jens
> aber warum zeigt mir der compiler > in den zeilen mit dem adsc und adif bit dies an: > > > constant value required Ich denke mal, dass du hier zwei Programmiersprachen vermischt: > warte2: sbis ADCSRA, ADIF ;abfrage ob umwandlung schon > ;beendet > ;ist > ADIF=1 > in r20, ADCL ;die unteren 8bits in r20 speichern > in r21, ADCH ;die oberen 2bits in r21 speichern > ret ADIF=1 passt nicht zu ASM-Syntax. Das mag in C oder BASIC syntaktisch richtig sein, in ASM versuchst du damit, den Wert des Bezeichners 'adif' (das ist die Bitnummer, also eine Konstante, die in der Include-Datei festgeschrieben ist) zu verändern. Und das darf der Assembler (der kein Compiler ist!) nicht zulassen... ...
Achja, noch was vergessen... Ich interpretiere deinen Code so: - Du stellest in ADMUX die Messquelle (und Referenzquelle) ein, - du startest die Messung (Wandlung) - du wartest, bis das adif-Bit gesetzt ist - du liest die Werte aus... Also du schaltest dir Messquelle immer erst dann um, wenn du eigentlich schon gern das Ergebnis hättest. Ich würde das so machen: - Ausleseroutine in einen Timer-Interrupt oder den ADC-Complete- Interrupt legen. Darin in regelmäßigen Zeitabständen: - Wert einlesen und sichern - Messquelle für nächste Messung umschalten - Messung starten - fertig, andere Dinge tun, wie Tastenentprellung, Zeit hochzählen, LCD-Ausgabe usw. - zurück zur Mainloop. Das spart irgendwie Rechenzeit, da nicht auf das Ergebnis der Wandlung gewartet werden muss, sondern die Wandlung abläuft, während der AVR noch andere Dinge tut. Wenn du mit Sleep arbeitest, kannst du sogar die Wandlung automatisch starten lassen, indem du das Programm nach getaner Arbeit einfach in den Sleep-Mode schickst. Beim Mega8 geht das glaube sogar im Idle-Mode. Schau mal im Datenblatt unter SLEEP nach. ...
hallo, danke für schnelle antwort. das adif=1 gehört nur zum kommentar. da hat was nicht so hingehauen beim reinkopieren. sollte einfach nur heißen, dass die umwandlung beendet ist, wenn das adif bit gesetzt ist. (wie krieg ich das denn beim nächsten mal besser hin? (code) (/code) hat nicht geklappt) davon kann die fehlermeldung also nicht kommen. und das mit den interrupt klingt einleuchtend, ich hab bloß keinen schimmer wie das funzt. was in dieser interruptroutine drinstehen muss, ist mir klar, aber nicht wie ich diese einbinde. macht man das über die interruptvectoren? wie gesagt das mit den interrupts hab ich noch nicht so begriffen. gruß jens
Dann schau dir doch einfach mal die Programme (Quelltexte) auf meiner Seite an: www.hanneslux.de Am besten das Melodiegenerator-Projekt mit Tiny15, erste Variante, da ist genau erklärt, wie man ASM-Programme mit Interrupts schreibt. Auch das Projekt, was ich dir im obigen Link genannt habe, zeigt im Quelltext recht deutlich, wie das mit den Interrupts geht. Da ich kein Profi bin, ist das Niveau dieser Programme nicht besonders hoch (vom mathematischen Anspruch her gesehen), der Code müsste also nachvollziehbar und verständlich sein. Aber auch im Datenblatt des Mega8 unter Interrupt-Sources wird erklärt, wie das gemacht wird. Erwarte aber bitte nicht, dass ich dir das übersetze, ich habe selbst nie englisch gelernt, ich muss da auch gelegentlich das Wörterbuch befragen. In C oder BASIC scheint das mit den Interrupts vielleicht etwas kryptisch bzw etwas schwerer durchschaubar zu sein, in ASM ist aber sehr einfach und vor allem sehr transparent. ...
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.