Hallo Leute, erst mal vielen Dank für die Hilfe die Ihr mir bis jetzt geboten habt. Ich habe es etwas schwer mit Assembler (Anfänger) und möchte eine kleine Sache lösen, weiss aber nicht wie ich genau dran gehen soll. Also falls jemand Zeit/Lust hat hier meine "einfache" Sache: Möchte einen MUX mit einem Mega8/16/32/8535 ansteuern und dafür benötige ich 3 Ausgänge des megaxx um die 3 Steuereingänge des MUX anzusteuern. Diese Ausgänge müssten sozusagen alle Zustände einer Wahrheitstabelle für eine 3bit-Zahl durchlaufen. Also als Beispiel: Ausgänge: 0 1 2 Zustand: 0 0 0 -> MUX Eingang 1 Zustand: 0 0 1 -> MUX Eingang 2 Zustand: 0 1 0 -> MUX Eingang 3 usw. Das Ganze muss in einer Schleife durchlaufen bis man es per Taster beendet/startet. Ich muss auch bedenken dass auch eine gewisse Zeit benötigt wird biss der MUX tatsächlich geschaltet wird und der Eingang gelesen wird. Ich habe 8 solcher MUX an 8 ADC-Eingänge des Mega angeschlossen, habe 3 Ausgänge parallel an alle MUX-Steuereingänge angeschlossen. Jetzt will ich diese ADCs einlesen, habe also 8x8=64 Eingänge.... Benutze AVR-Studio, PonyProg2000, die Hardware ist ein Board von Pollin mit eingesetztem mega8 (werde aber auf mega8535 oder mega16/32 umstellen). Die MUX sind 74hc4851 für Analogsignale, an den Eingängen sollen Thermofühler drankommen. Wie packt man sowas an? Hat jemand so einen Beispielcode ? Vielen Dank
Welchen Grund hast du, um dieses Programm ausgerechnet in Assembler zu schreiben? Platznot beim Programmcode oder Datenaufkommen kann es ja nicht sein, mit den von dir ausgesuchten Atmegas...
Hi An welchem Port sind die Multiplexer angeschlossen? @Stefan: Was soll die überflüssige Frage? MfG Spess
@ Spess Interessiert das dich wirklich oder willst du mir anmachen?
Hallo Dein Problem ist anscheinend nicht die ADC-Wandlung, sondern wie du das Multiplexen händeln willst. Teste mal den anhängenden Schnipsel, ich glaube du wirst ihn verstehen und dann kannst du es auch selbst. Das schalten des MUX geht mit einer maximalen Latenz von 125 nano-sec. Das sind 8 MHz. Also eigentlich unkritisch Problem ist das einschwingen des ADC nach Kanalwechsel. Ich hab das immer so gemacht, das ich zweimal gewandelt habe. Den ersten Wert habe ich garnicht erst ausgelesen, dann sofort eine neue Wandlung gestartet und den Wert verwendet. Besten Gruß .include "m16def.inc" .equ tabelle = 0x100 .def adc_ergebnis_low = r16 .def adc_ergebnis_high = r17 .def mux_zeiger = r18 .def adc_kanal = r19 .equ dein_port = portb init: ldi r16,low(ramend) out spl,r16 ldi r16,high(ramend) out sph,r16 ldi zl,low(tabelle) ldi zh,high(tabelle) clr mux_zeiger ;Zeiger für den MUX clr adc_kanal ;zeiger auf den ADC-Kanal, kannst ihn noch mit gain oder so verknüpfen ; ab hier eine_runde_fertig: out dein_port,mux_zeiger laufende_runde: call adc_wandlung in adc_ergebnis_low, adcl in adc_ergebnis_high, adch st z+,adc_ergebnis_low st z+,adc_ergebnis_high inc adc_kanal cpi adc_kanal,8 brne laufende_runde clr adc_kanal inc mux_zeiger cpi mux_zeiger,8 brne eine_runde_fertig clr mux_zeiger ldi zl,low(tabelle) ldi zh,high(tabelle) rjmp eine_runde_fertig adc_wandlung: ;deine ADC-Routine nop ret
Erstmal ein wenig ruhe hier. Wenn man gleich anfängt rumzu"flamen" schreck man anfänger eher ab. Und die Fragen beantwortet der Scheiß auch nicht. Was mir aufgefallen ist das du (Robert) je 8 Eingange an einen Ausgang geschaltet hast. Das könnte zu Problemen mit Fan-IN bzw. Fan-OUT führen. Aber das übersehen wir erstmal. Idealer setzt man sich am Anfang des Programms Konstanten.
1 | .equ MUX0 = 0 |
2 | .equ MUX1 = 1 |
3 | .equ MUX2 = 2 |
4 | .equ MUX3 = 3 |
5 | .equ MUX4 = 4 |
6 | .equ MUX5 = 5 |
7 | .equ MUX6 = 6 |
8 | .equ MUX7 = 7 |
9 | |
10 | .def work = r16 ;work ist immer mein Arbeitsregister |
Bei der Initialisierung definiert man die entsprechenden Ports erstmal als Ausgang. (Ich nehme mal einfach PC0, PC1 und PC2)
1 | ldi work,0b00000111 |
2 | out DDRC,work ;setze PC0-PC2 als Ausgang |
um dann hinterher die Mux umzuschalten (z.B. auf Mux 2) verwendet man:
1 | ldi work,mux2 |
2 | out PORTC,work ;setze PC0-PC2 auf auf mux2 |
Jetzt kommt evt noch eine kleine Warteschleife (je nach dem wie lang die Muxe zum umschalten brauchen) und danach führt man die ADC Messung durch. bis dann cu Hauke
Hallo, was mich mehr verwirrt: Temperaturfühler... Wie schnell ändern sich die Temparaturen im ungünstigsten Fall und wie schnell reagieren die Sensoren? Bei z.B. 5ms Timer-IRQ wären es 64*5 = 320ms für alle Wandler, also rund eine Messung/Sekunde nacj meinem Vorschlag. Wenn das reicht: IRQ - wenn Hilfsflag gelöscht: ADC lesen, MUX neu setzen, ADC neu starten, Hilfsflag setzen wenn Hilfsflag gesetzt: nur ADC neu starten, Hilfsflag löschen usw. Möglich ist hier auch free-running, es finden nach dem Umschalten mehrere Wandlungen statt, wenn der Takt nicht allzu langsam ist. Dann nur Flag behandeln und entweder MUX umschalten oder ADC lesen. Das Hauptprgramm kömmert sich um die Verarbeitung der Werte, wenn alle 10Bit genutzt werden, muß der Zugriff auf die Werte dort mit CLI/SEI atomar gehalten werden. Solche reöativ langsamen Sachen hänge ich meist in einen Timer-Interrupt, den ich wegen Uhrzeit und Tasten-Entprellen sowieso brauche. Gruß aus Berlin Michael
Hi
@Stefan
Nein, ich will DIR nicht anmachen. Aber wenn er es in Assembler machen
will, finde ich das in Ordnung. Dann lernt er wenigsten von der Pike auf
und stellt später keine dummen Fragen.
Eine Bemerkung zum obigen Programm:
>out dein_port,mux_zeiger
Damit wird der ganze Port überschrieben. Besser ist es, die Portbelegung
einzulesen, mit der Multiplexeradresse zu verknüpfen und dann erst den
Port beschreiben.
Beispiel: MUX-Adresse Pin 0,1,2
in r16,PortX ; Portbelegung einlesen
andi r16,0b11111000 ; Adressbits löschen
ldi r17,MUXAdresse
andi r17,0b00000111 ; nur Adressbits (zur Sicherheit)
or r16,r17 ; PortPins und Adressbits zusammensetzen
out PortX,r16 ; ausgeben
MfG Spess
Hallo Leute, erst mal an alle vielen Dank. Ich habe gestern Abend die Anfrage gestellt und weiter an meinem Problem gebastelt, heute hat es mich fast erschlagen welches Echo meine Frage hatte. Vielen Dank für die Hilfe. Ich muss jetzt erst mal alles verdauen... Also: Ich will/muss dass in Assembler machen da ich für das Studium Assembler benötige und so gleich 2 Fliegen mit einer Klappe..... Das Thermometer benötige ich um einen Rechner zu überwachen der in der Entwicklung ist und Themparaturprobleme hat. Wie "wb1" es richtig erkannt hat ist mein Problem wie steuere ich den MUX an, wie macht man sowas... An dieser Stelle danke an "wb1". Ich werde versuchen Deinen Code zu verstehen und anwenden. Danke auch an Haucke, die Ruhe hat mir gut getan und den Weg den Du mir angegeben hast ist für mich auch händelbar. Dank auch an Michael, nur Deine Ausführung ist mir zur Zeit etwas zu "hoch", ich muss da noch langsam vieles Wissen erarbeiten, werde mir aber langsam das beibringen um auch fachlichere Angaben zu verstehen. Wie immer ist auch "spess53" hilfsbereit und hat wie auch in der nahen Vergagenheit eine Hilfe angeboten. Danke Dir. Jetzt werde ich mich an die Arbeit machen und Euere Beiträge abarbeiten.... Mühsam geht es weiter..... Vielen Dank PS: Hallo "wb1", ist es Dir möglich den Code mit Kommentare zu "bespicken"? Es würde mir sehr helfen zu verstehen was genau da passiert und wie es gemeint ist. Nebenbei, ich muss/will 256 Werte/Kanal einlesen, daraus den Mittelwert errechnen der dann ausgegeben wird. Es muss doch von der Zeit möglich sein wenn ich den megaxxx mit 16MHz per ext. Quarz betreibe...oder ? Danke
Den Mittelwert aus 256 Werten erechnen ist relativ einfach. Es gibt eine Option (Ein Steuerungsflag) im ADC, welches bewirkt das die ermittelten Analogwerte linksbündig in die beiden ADC Register geschrieben werden. danach nimmt man nur noch den Inhalt von ADCH und adiert diesen auf eine 16 Bit Variable. Nach den 256 Duchgängen befindet sich der Mittelwert aus den Messungen dann in den oberen 8 Bit der 16 Bit Variable. bis dann cu Hauke
Hallo Robert Ich weiß, man sollte die Quelle kommentieren. Aber es gibt da einsn inneren Schweinehund, sich dagegen zu wehren ist schwer. Ein paar Kommentare hab ich eingefügt. Vieleicht helfen sie dir. Du mußt dich da durchbeißen und wenn man alles vorgekaut bekommt, lernt man es nicht. Du hast geschrieben, du hättest avr-studio. Füge die Quelle in dein projekt ein und simuliere sie. Führe die Simulation schrittweise aus. Ich glaube, dann wirst du es verstehen. In der Hauptschleife habe ich ein paar Anweisungen auskommentiert. Die hatte ich eingesetz, um deine Frage nach der Laufzeit bei 256 Wandlungen je Kanal zu ermitteln. Die Durchlaufzeit für die 64 Wandlungen ist abhängig vom Vorteiler des ADC. Bei dem gewählten Vorteiler ergibt sich für 64 Wandlungen inclusive der verworfenen ersten Wandlung bei einem Takt von 16 MHz eine Laufzeit von 3,4millisekunden. Bei 256 Wandlungen je Kanal und 64 Kanälen ergigt sich eine Laufzeit von knapp 0,9 sekunden. Die Mehrfachwandlung sowie die Addition der Werte habe ich weggelassen. Wenn du es machen willst, brauchst du in der Ergebnistabelle 3 Speicherzellen. Natürlich kannst du es machen, wie hauke beschrieben hat, dann reichen auch die Werte in der Tabelle. Aber du hast dann von Haus aus einen Wandlungsfehler von 20%, weil du ja nur 8bit statt 10 bit auswertest. Ach ja, mach immer einen Schritt nach dem anderen. Wenn du die Wandlung in der Hardware funktionsfähig hast, stelle die Software auf Mehrfachwandlung um. Wenn du von vornherein immer neue Ideen einbringst, ohne die Ausgangsidee realisiert zu haben, verzettelst du dich und schmeißt dann alles in die Ecke. Das wäre schade. Mach erst einmal die einfache Wandlung, dort wirst du schon auf Probleme treffen, zum Beispiel das die Meßwerte flattern. Dann mußt du Hardwareseitig etwas tun, um das Flattern (es ist natürlich, weils ja kein 0,5 also halbe bits gibt) so klein wie möglich zu halten. Wenn du das erreicht hast, mach deine Mehrfachwandlung. Besten Gruß aus Eberswalde .include "m16def.inc" .equ tabelle = 0x100 .def adc_ergebnis_low = r16 .def adc_ergebnis_high = r17 .def mux_zeiger = r18 .def adc_kanal = r19 .equ dein_port = portb init: ;setze den Stapelzeiger ldi r16,low(ramend) out spl,r16 ldi r16,high(ramend) out sph,r16 ;setze den Tabellenanfang ldi zl,low(tabelle) ldi zh,high(tabelle) ;setze das Richtungsregister bit0 bis 2 auf Ausgang ;das Datenrichtungsregister ist dein Port minus1 ldi mux_zeiger,0b00000111 out dein_port-1,mux_zeiger ;initialisiere den ADC ldi mux_zeiger,0b10000101 ;hier wird Vorteiler eingestellt out adcsra,mux_zeiger ;loesche die zeiger clr mux_zeiger clr adc_kanal Hauptschleife: ; clr r10 s1: call wandlung_64_eingaenge ; dec r10 ; brne s1 rjmp Hauptschleife wandlung_64_eingaenge: eine_runde_fertig: out dein_port,mux_zeiger laufende_runde: call adc_wandlung in adc_ergebnis_low, adcl in adc_ergebnis_high, adch st z+,adc_ergebnis_low st z+,adc_ergebnis_high inc adc_kanal cpi adc_kanal,8 brne laufende_runde clr adc_kanal inc mux_zeiger cpi mux_zeiger,8 brne eine_runde_fertig clr mux_zeiger ldi zl,low(tabelle) ldi zh,high(tabelle) ret adc_wandlung: ;erste Wandlung ist fehlerbehaftet, also verwerfen sbi adcsra,6 warte_fehlwandlung_fertig: sbic adcsra,6 rjmp warte_fehlwandlung_fertig sbi adcsra,6 warte_wandlung_fertig: sbic adcsra,6 rjmp warte_wandlung_fertig ret
Hallo Hauke, danke für Deine Hilfe. Ich benutze den Demo-Code aus dem Tutorial (ADC) und versuche den soweit umzustellen um ein wenig zu verstehen wie das funktioniert. Wenn ich es richtig verstanden habe dann muss ich gucken wie dieser Mittelwert errechnet wird anhand einer Option im ADC. OK, werde ich gucken und testen. Danke Dir & schöne Feiertage
Hallo "wb1", noch mal danke für Deine Zeilen, ja das stimmt, der Schweinehund, den kenne ich auch :-) Werde aber dennoch Deinen Code bearbeiten um zu verstehen wie das funktioniert, jetzt kommen die Feiertage, also ein wenig Zeit zum basteln. Bedanke mich bei Dir und wünsche noch ein frohes Fest. Vielen Dank PS: Bei Fragen weiß ich wo ich Hilfe erhalten kann.... Vielen Dank an alle !!
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.