Autor
|
Thema: Taster als Schalter via AVR (Gelesen 152230 mal)
|
Fabeulous
Gast
|
Okay warum einfach wenns auch schwer geht  Erstmal vielen dank so wie du das gemacht hast ist das natürlich etwas einfacher... Wnn ich nachher zuhause bin und Zeit habe werde ich mich da mal reinarbeiten und versuchen ob ich das hinbekomme  Danke!
|
|
|
Gespeichert
|
|
|
|
Fabeulous
Gast
|
So ich habe das dann mal so versucht wie du sagtest... den Rest habe ich mir von mikrocontroller.net zusammen gewurschtelt... Da ist zwar noch keine Entprellung und sowas drin aber ich hab erstmal versucht das Grundgerüst hinzubekommen... Hier mein Code:
.include "m8def.inc"
.def tast_alt  = r3 .def tast_aktuell  = r4 .def temp1   = r18 .def temp2   = r19 .def led_out  = r20
ldi  R16, 0b00111111 ;PORTC -> Ausgang out  DDRC, R16
ldi  R16, 0b00011111 ;PORTB -> Pull-Up Widerstände ein out  PORTB, R16
ldi  R16, 0b00001100 ;PORTD -> Ausgang und Eingang out  DDRD, R16
ldi  R16, 0b11000000 ;PORTD -> Pull-Up Widerstände ein out  PORTD, R16
ldi   tast_alt, 0b00000000
haupt:
ldi  R16, PIND  ; PIND -> R16 ldi  R17, PINC  ; PINC -> R17 swap  R17 ; aus 01234567 wird 01674523 or  r16, r17 ; 11111100(R16) und 00000011(R17) = 11111111(R16) mov tast_aktuell, r16 ; r16 in tast_aktuell sichern mov temp1, r16  ; r16 in temp1 sichern
eor tast_aktuell, tast_alt  ; xor von tast_aktuell und tast_alt | Ergebnis in tast_aktuell mov tast_alt, temp1   ; alten tasterzustand sichern breq haupt           ; wenn tast_alt und tast_aktuell sich NICHT unterscheiden springe zurück nach haupt
and temp1, tast_aktuell    ; temp1 hat nun an der stelle eine eins an welcher der Taster gedrückt wurde                     brne haupt          ; springe wenn and vergleich nicht gleich zurück nach haupt, sonst springe nicht
in  temp1, led_out    ; den Zustand der LED umdrehen    com temp1
????????out led_out, temp1????????    jmp haupt
Ziemlich zerflückt das ganze...hier das ganze nochmal als asm file
Na ja jetzt hänge ich bei dem teil in dem es um das ausgeben der taster signale an die LED's bzw. relais bzw. ULN2803 geht. Denn diese hängen ja wieder an zwei Ports...
Könnte ich das wieder elegant machen oder muss ich diemsal wirklich Bit für Bit mit befehlen wie sbic oder sbis durchegehen?! Danke für die vielen guten Tips!
|
|
« Letzte Änderung: August 14, 2007, 17:25:34 von Fabeulous »
|
Gespeichert
|
|
|
|
nuss
Stichsägenquäler

Karma: +0/-0
Offline
Geschlecht: 
Beiträge: 51

Casemodding braucht keinen Grund
|
War schon lange ned mehr hier im Forum aber habe gesehen, dass es um mega 8 geht *toll* Frage: warum proggt ihr nicht in C? Ist doch viel einfacher. Habe hier auch noch nen Programm zum entprellen von Tastern einmal in C und in ASM. Ich häng die einfach mal hier so an wenn das geht. Das ganze ist kombiniert mit nem Knightriderlauflicht. Viel Spaß! Habe auch noch andere Programme für den Mega8. zb.: ne LCD display ansteuerung
Anmerkung: die endung .jpg durch .asm bei dem file nummer1.jpg erstzen und durch die endung .c bei knightrider_c.jpg Hatte keine lust nen file hoster zu suchen
|
|
|
|
Fabeulous
Gast
|
So erstmal danke für das weitere Beispiel...
Und dann bruache ich dirngend nochmal eure Hilfe.. erstmal zu meiner letzten Frage nämlich wie ich nun das Register wieder an die LEDS ausgeben soll?! Und dann habe ich noch ein Problem undzwar leuchten von anfang an bei meiner Schaltung 3 LED's und wenn ich auf den Taster drücke flackern sie nur manchmal... ich habe den Code schon reduziert auf folgendes:
.include "m8def.inc"
.def alter_taster_status  = r16 .def aktueller_taster_status  = r17 .def temp1 = r18 .def temp2 = r19 .def temp3 = r20 .def temp4 = r21
ldi  r16, 0b00111111 ;PORTC -> Ausgang out  DDRC, r16
ldi  r16, 0b00011111 ;PORTB -> Pull-Up Widerstände ein out  PORTB, r16
ldi  r16, 0b00001100 ;PORTD -> Ausgang und Eingang out  DDRD, r16
ldi  r16, 0b11000000 ;PORTD -> Pull-Up Widerstände ein out  PORTD, r16
ldi  aktueller_taster_status, PIND  ; PIND -> R16 ldi  temp1, PINB  ; PINC -> R17 swap  temp1 ; aus 01234567 wird 01674523 or   aktueller_taster_status, temp1 ; 11111100(R16) und 00000011(R17) = 11111111(R16)
mov temp3, aktueller_taster_status mov temp4, aktueller_taster_status
    out PORTC, temp3 out PORTD, temp4
der Code soll eigentlich sowas wie das hier sein:
.include "m8def.inc"      ldi r16, 0xFF      out DDRB, r16   ; Alle Pins am Port B durch Ausgabe von 0xFF ins               ; Richtungsregister DDRB als Ausgang konfigurieren      ldi r16, 0x00      out DDRD, r16   ; Alle Pins am Port D durch Ausgabe von 0x00 ins               ; Richtungsregister DDRD als Eingang konfigurieren loop:      in r16, PIND   ; an Port D anliegende Werte (Taster) nach r16 einlesen      out PORTB, r16  ; Inhalt von r16 an Port B ausgeben      rjmp loop     ; Sprung zu "loop:" -> Endlosschleife was ich bei mikrocontroller.net gefunden habe... leider funktioniert das auch nciht und ich kann mir nicht erklären warum... Trotzdem vielen Dank
EDIT: So da läuft wohl einiges noch cnith glatt... Ich habe jetzt rausgefunden das das frische vom PINB eingelesene register so ausseiht: 0b01010110
aber ich verstehe nicht warum?!
|
|
« Letzte Änderung: August 16, 2007, 19:20:53 von Fabeulous »
|
Gespeichert
|
|
|
|
|
Fabeulous
Gast
|
Ja aber eigentlich dürfte das Register von PINB doch garnicht so aussehen wie es aussieht?! ich hab doch garkeine taste gedrückt und trotzdem sind da einsen in dem Register?!
|
|
|
Gespeichert
|
|
|
|
|
Fabeulous
Gast
|
okay das mit ldi wusste ich nciht weil ich das auf mikrocontroller.net so gelesen habe.. ne un der assembler gab grünes licht 
Ach und das mit dem swap befehl hatte ich schon gemerkt ich hatte nur keine lust das da ganz obe zu korrigieren... aber danke!
EDIT: Okay ich muss zugeben auf mikrocontroller.net stand das so auch nicht! Ich weis nicht wie ich darauf gekommen bin..
Ach und ich hab eine Möglichkeit gefunden wie ich das Register wieder zerstückelt an die Ausgangsregister ausgeben kann. undzwar mit einem and und einem or vergleich. Wie ich das jetzt insgesamt genau meine zeige ich später dann gibt es nochmal den gesamten code!
|
|
« Letzte Änderung: August 17, 2007, 17:24:30 von Fabeulous »
|
Gespeichert
|
|
|
|
Fabeulous
Gast
|
Sooo Jungs ich grabe mal meinen Thread wieder aus!  Undzwar warbeite ich immer noch an der selben Sache! ICh hatte di Letzten Monate nicht soviel Zeit aber nun will ich mich mal an die Software von meinem schätzchen machen! Mein aktueller Code sieht so aus:
.include "m8def.inc" .def temp1 = r16 .def temp2 = r17 .def tast_neu = r18 .def tast_alt = r19
ldi temp1, 0b00111111 ;PORTC -> Ausgang out DDRC, temp1
ldi temp1, 0b00011111 ;PORTB -> Pull-Up Widerstände ein out PORTB, temp1
ldi temp1, 0b00001100 ;PORTD -> Ausgang und Eingang out DDRD, temp1
ldi temp1, 0b11000000 ;PORTD -> Pull-Up Widerstände ein out PORTD, temp1
ldi tast_alt, 0b00000000
haupt:
in temp1, PIND ; PIND -> temp1 (11100000) in temp2, PINB ; PINB -> temp2 (00011111) or temp1, temp2 ; 11100000(temp1) und 00011111(temp2) = 11111111(temp1) mov tast_neu, temp1 ; temp1 in tast_aktuell sichern
eor tast_neu, tast_alt ; xor von tast_aktuell und tast_alt | Ergebnis in tast_aktuell mov tast_alt, temp1 ; alten tasterzustand sichern breq haupt ; wenn tast_alt und tast_aktuell sich NICHT unterscheiden springe zurück nach haupt
ldi temp1, $FF ; --> Warteschleife wait1; ;. ldi temp2, $FF ;. wait2 ;. dec temp2 ;. brne wait2 ;. dec temp1 ;. brne wait1 ;<-- Warteschleife
in temp1, PIND ;--> Neu einlesen in temp2, PINB ; or temp1, temp2 ;<-- Neu einlesen
and temp1, tast_neu
brne haupt ; springe wenn and vergleich nicht gleich zurück nach haupt, sonst springe nicht
;Hier kommt noch die Ausgabe hin;
jmp haupt
Nun bin ich mir aber noch bei ein paar sachen unklar: Einmal weis ich nicht ob das so alles funktioniert wie ich das da aufgeschrieben habe. Vlt. könnte da mal jemand einen flüchtigen Blick drauf werfen und mir sagen ob das grob gesehen so in Ordnung ist...
Und Letztendlich fehlt mir dann noch der Teil in dem dann die LED's bzw. Relais geschaltet werden. Also quasi die komplette Ausgabe! Ich muss mich da nochmal eindringlich mit beschäftigen oder hat jemand von euch so eine Idee? Das Problem dabei ist ja das die LED's an unterschiedlichen Ports hängen(siehe Anschluss"diagramm" unten).
Den Software Teil mit der Kommunikation per UART wurde ich dann danach angehen...
Dann nochmal eine ganz andere Sache. Ich habe überlegt anstatt per rs232 das ganze per USB anzuschließen wiel ich das ganze dann intern verkabeln könnte... Da gibt es doch diese tollen "AdapterChips"(mir fällt gerade kein anderes wort ein) Also ein Chip der PC Seitig über USB eine Com Schnittstelle emuliert. Ich weis das es sowas gibt. HAb acuh schonmal was gefunden aber das teil kostet 5 Euro. Das scheint mir ein bischen großzügig proportioniert auch im Funktionsumfang. Denn ich brauche ja kein USB 2.0 oder sowas... Na ja egal wäre cool wenn da vlt. einer eine Idee hat?!
So das war es erstmal mit den vielen Fragen!  Danke schonmal im vorraus!
Anhang: Ein und Ausgänge meines µC's:
PD0-> UART PD1-> UART PD2-> Ausgang PD3-> Ausgang PD4-> --- PD5-> Eingang PD6-> Eingang PD7-> Eingang
PC0-> Ausgang PC1-> Ausgang PC2-> Ausgang PC3-> Ausgang PC4-> Ausgang PC5-> Ausgang PC6-> Reset PC7-> ---
PB0-> Eingang PB1-> Eingang PB2-> Eingang PB3-> Eingang-> MOSI PB4-> Eingang-> MISO PB5-> --- -> SCK PB6-> Takt PB7-> Takt
|
|
|
Gespeichert
|
|
|
|
Fabeulous
Gast
|
Sorry für Doppelpost aber sonst bekommt das ja keiner mit!  Ich habe ein problem: UNdzwar wollte ich die Asugabe für jedes Bit einzeln machen. Weil es muss ja bei dem Bit bei dem der Taster gedrückt wurde der Wert am Ausgabe Port umgedreht werden. Das habe ich versucht mit einer Zählschliefe zu lösen. Leider kann man aber das "Zählregister" anscheinend nicht als INdex benutzen. Hat jemand eine Idee wie man das doch machen könnte?
ldi zaehler, 4 ;Startwert laden schleife_D: sbrc temp1, zaehler ; Wenn aktuelles Bit=0Â springe zur Sprungmarke weiter_D rjmp pruefen_D rjmp weiter_D
pruefen_D: sbis PORTD, zaehler ; Prüfe ob das aktuelle(index=zaehler) Bit am PORTD 1 ist rjmp an_D ; Wenn es 0 ist tu das(Einschalten) rjmp aus_D ; Wenn es 1 ist tu das(Ausschalten)
an_D: sbi PORTD, zaehler ; Einschalten :P rjmp weiter_D
aus_D: cbi PORTD, zaehler ; Ausschalten :P rjmp weiter_D
weiter_D: inc zaehler ; Index erhöhen cpi zaehler, 6 ; vergleich ob index schon gleich 6 wenn ja dann endet die Schleife hier! brne schleife_D Helft mir Bitte!
EDIT: So ich habe noch etwas weitergearbeitet: Undzwar habe ich meiner Meinung nach nun die UART Sende und Empfangsgeschichte fertig. Ich poste einmal den gesamten Code und hebe das betreffende dann Farbig hervor. Blau steht für Sendegeschichte und rot für Empfangsgeschichte:
.include "m8def.inc" .def temp1   = r16 .def temp2 = r17 .def tast_neu = r18 .def tast_alt = r19 .def zaehler = r20 .equ F_CPU = 8000000    ; Systemtakt in Hz .equ BAUD = 9600      ; Baudrate ; Berechnungen .equ UBRR_VAL  = ((F_CPU+BAUD*  /(BAUD*16)-1) ; clever runden .equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1)))   ; Reale Baudrate .equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000) ; Fehler in Promille .if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))    ; max. +/-10 Promille Fehler  .error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!" .endif ldi  temp1, 0b00111111 ;PORTC -> Ausgang out  DDRC, temp1 ldi  temp1, 0b00011111 ;PORTB -> Pull-Up Widerstände ein out  PORTB, temp1 ldi  temp1, 0b00001100 ;PORTD -> Ausgang und Eingang out  DDRD, temp1 ldi  temp1, 0b11000000 ;PORTD -> Pull-Up Widerstände ein out  PORTD, temp1 ldi   tast_alt, 0b00000000 sbi UCSRB,TXEN ; Sende"kanal" aktivieren sbi UCSRB, RXEN ; Empfangs"kanal" aktivieren haupt: sbic UCSRA, RXC ; Pruefen ob etwas empfangen wurde rjmp byte_empfangen ; Wenn etwas empfangen wurde springe zur Sprungmarke byte_empfangen in   temp1, PIND  ; PIND -> temp1 (11100000) in   temp2, PINB  ; PINB -> temp2 (00011111) or   temp1, temp2 ; 11100000(temp1) und 00011111(temp2) = 11111111(temp1) mov tast_neu, temp1 ; temp1 in tast_aktuell sichern eor tast_neu, tast_alt  ; xor von tast_aktuell und tast_alt | Ergebnis in tast_aktuell mov tast_alt, temp1   ; alten tasterzustand sichern breq haupt           ; wenn tast_alt und tast_aktuell sich NICHT unterscheiden springe zurück nach haupt ldi temp1, $FF ; --> Warteschleife wait1: ;. ldi temp2, $FF ;. wait2: ;. dec temp2 ;. brne wait2 ;. dec temp1 ;. brne wait1 ;<-- Warteschleife in temp1, PIND ;--> Neu einlesen in temp2, PINB ; or temp1, temp2 ;<-- Neu einlesen and temp1, tast_neu brne haupt         ; springe wenn and vergleich nicht gleich zurück nach haupt, sonst springe nicht byte_empfangen: in temp1, UDRausgabe: ldi zaehler, 4 ;Startwert laden
schleife_D: sbrc temp1, zaehler ; Wenn aktuelles Bit=0Â springe zur Sprungmarke weiter_D rjmp pruefen_D rjmp weiter_D
pruefen_D: sbis PORTD, zaehler ; Prüfe ob das aktuelle(index=zaehler) Bit am PORTD 1 ist rjmp an_D ; Wenn es 0 ist tu das(Einschalten) rjmp aus_D ; Wenn es 1 ist tu das(Ausschalten)
an_D: sbi PORTD, zaehler ; Einschalten  rjmp weiter_D aus_D: cbi PORTD, zaehler ; Ausschalten  rjmp weiter_D
weiter_D: inc zaehler ; Index erhöhen cpi zaehler, 6 ; vergleich ob index schon gleich 6 wenn ja dann endet die Schleife hier! brne schleife_D
ldi zaehler, 0 schleife_C: cpi zaehler, 4 breq weiter_C cpi zaehler, 5 breq weiter_C
sbrc temp1, zaehler rjmp pruefen_C rjmp weiter_C
pruefen_C: sbis PORTC, zaehler rjmp an_C rjmp aus_C
an_C: sbi PORTC, zaehler rjmp weiter_C
aus_C: cbi PORTC, zaehler rjmp weiter_C
weiter_C: inc zaehler cpi zaehler, 8 brne schleife_Cwarten_bis_gesendet: sbis UCSRA,UDRE ; Prüfen ob alle Daten egsendet wurden rjmp warten_bis_gesendet ; Wenn noch nicht alle Daten gesendet wurden springe zurück out UDR, temp1 ; Alle daten wurden gesendet also los sende nochmal    rjmp haupt Ach so und ich hebe nochmal das hervor was ich davor angesprochen habe. Also das grün markierte ist die Ausgabe die leider nicht funktionieren will weil der assembler als zweiten Parameter bei den skip befehlen eine Zahl anstatt ein Register erwartet... Ich habe shcon gesucht aber leider keinen Weg bzw. befehl gefunden wie man das anders lösen könnte! Habt ihr eine Idee? Danke für jede Hilfe!
|
|
« Letzte Änderung: November 7, 2007, 18:01:49 von Fabeulous »
|
Gespeichert
|
|
|
|
|
Reisi
Lötkolbenfreak

Karma: +2/-0
Offline
Beiträge: 190
|
Mein AVR Assembler ist zwar schon etwas eingerostet, aber seh ich das richtig, dass du die Tastenabfrage doch über Warteschleifen machst? Probier das ruhig aus, ist nicht umsonst eine der klassischen Anfängerübungen, aber bevor du die anderen Sachen angehst stell das lieber auf Interrupts um, ist auf Dauer viel problemloser.
Das gleiche gilt auch für die U(S)ART Schnittstelle, das sind Routinen, die du auch in Zukunft (ich geh mal davon aus, dass das keine einmalige Sache ist) immer wieder brauchen wirst.
Bzgl. USB: Es gibt auch die Möglichkeit, das direkt in Software zu implementieren (AVR-USB, Igor-USB)
|
|
|
Gespeichert
|
|
|
|
PoWl
Dremelfreund

Karma: +0/-0
Offline
Beiträge: 140
Atmel AVR Mikrocontroller
|
Hehe, du versuchst da Hochsprachenelemte in Assemblerschreibweise zu verwenden. So wie ich das sehe versuchst du in dem register zähler als Zeiger auf das zu bearbeitende Portbit zu verwenden. Das funktioniert natürlich nicht so.
Theoretisch muss man sich für jeden ein/ausschalte befehl einen eigenen teil programmieren, so dynamisch sind AVRs leider nicht.
Aber was spricht denn dagegen alle Bits gleichzeitig zu bearbeiten? Habe das auch so gemacht und den Source mal gepostet, kannst dich ja inspirieren lassen ;-) Geht mit ein bisschen überlegung mit den logikoperatoren.
mfg PoWl
|
|
« Letzte Änderung: November 8, 2007, 09:53:52 von PoWl »
|
Gespeichert
|
|
|
|
Fabeulous
Gast
|
Mein AVR Assembler ist zwar schon etwas eingerostet, aber seh ich das richtig, dass du die Tastenabfrage doch über Warteschleifen machst? Probier das ruhig aus, ist nicht umsonst eine der klassischen Anfängerübungen, aber bevor du die anderen Sachen angehst stell das lieber auf Interrupts um, ist auf Dauer viel problemloser. Würde es denn so auch funktionieren? Also ich würde mir das auch angucken mit den Interrupts aber wäre ganz cool erstmal ein resultat zu sehen...
Ich würde es lieber mit nem converter ic machen. Da ich mich noch nichtmal mit der Datenübertragung über rs232 auskenne würde ich das ungerne direkt mit USB machen... hat einer eine Idee für nen passenden IC?
Hehe, du versuchst da Hochsprachenelemte in Assemblerschreibweise zu verwenden. So wie ich das sehe versuchst du in dem register zähler als Zeiger auf das zu bearbeitende Portbit zu verwenden. Das funktioniert natürlich nicht so.
Theoretisch muss man sich für jeden ein/ausschalte befehl einen eigenen teil programmieren, so dynamisch sind AVRs leider nicht.
Aber was spricht denn dagegen alle Bits gleichzeitig zu bearbeiten? Habe das auch so gemacht und den Source mal gepostet, kannst dich ja inspirieren lassen ;-) Geht mit ein bisschen überlegung mit den logikoperatoren.
mfg PoWl
OKay das ist natürlich schade das das so nicht geht!  Na ja einzeln aufschrieben ist ja auch nciht schlimm hab nur gedacht das wäre so eleganter...
Das problem ist das ich ja ein Ausgaberegister auf zwei Ausgabeports verteilen muss und es darf ja nur das bit am ausgangsport invertiert werden von dem auch der taster gedrückt wurde. Da habe ich irgendwie noch keinen weg gefunden...
Ich schau mir deinen Code gleich mal an. Es ist nur oft schwer sich in den Code von anderen reinzudenken, selbst wenn Kommentare dabei sind... Aufjedenfall erstmal vielen dank ich hab schon gedacht ich wäre aufgeschmissen!
P.S: Sagt mal kann es sein das die Leute ausm mikrocontroller.net Forum totale Vollidioten sind?(http://www.mikrocontroller.net/topic/83084)
|
|
|
Gespeichert
|
|
|
|
PoWl
Dremelfreund

Karma: +0/-0
Offline
Beiträge: 140
Atmel AVR Mikrocontroller
|
Das Ausgaberegister auf 2 Ports verteilen dürfte kein Problem sein. Guck dir dazu die Schiebebefehle an, sowie swap und so zeug. Notfalls kannst du immernoch hinterher die einzelnen Bits in deinem Register abfragen und je nachdem ob das entsprechende Bit gesetzt ist oder nicht mit sbi oder cbi das Portbit schalten.
|
|
|
Gespeichert
|
|
|
|
|