- SF800 Solar Speicher Tutorial         
Seite 6 von 14 ErsteErste ... 45678 ... LetzteLetzte
Ergebnis 51 bis 60 von 136

Thema: Anfänger mit STK500 und Assembler

  1. #51
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Anzeige

    Powerstation Test
    robo_wolf,

    das sieht doch schon gut aus ! Meine Kommentare habe ich in den Quelltext geschrieben. Deine Fragen zum Timer habe ich auch dort beantwortet (siehe Anhang).


    Das EEPROM ist ein sehr praktischer Bestandteil der ATmegas. Ich benutze zum Lesen und Schreiben ziemlich genau die Prozeduren die im Datenblatt auf Seite 22 und 23 vorgestellt werden. Die funktionieren sehr zuverlässig.

    Ciao,

    mare_crisium
    Angehängte Dateien Angehängte Dateien

  2. #52
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    55
    Beiträge
    310
    Hallo mare_crisium,
    erst einmal wieder ein grosses DANKE.

    Den Fehler mit den nichtbeachteten Comparemodus habe ich gestern morgen auch endeckt.
    Der im Code stehende Wert von "155" kam durch das Probieren bzw. Fehlersuchen.
    Der eigentliche Wert von "-24999" ist aber, wie Du schon angemerkt hast, auch falsch und haette "24999" fuer den Comparemodus heissen muessen.
    Bei der Fehlersuche habe ich erst die Hardware ausgeschlossen, in dem ich ein reines Timerprogramm geschrieben hatte.
    Dabei ist mir dann der Fehler aufgefallen.

    Mit den veralteten Kommentaren hast Du vollkommen Recht. >>>Kopieren, >>>verbessern und dann doch >>>anders realisiert - dabei die Kommentare vergessen.

    Hierzu braeuchte ich noch ein wenig Hilfe:
    #####
    "Gute Idee, die Flankenbits gleich mundgerecht fürs Togglen auszulagern ! Du kannst das
    noch eleganter hinkriegen, indem Du die Tasten in umgekehrter Reihenfolge auswertest und
    das Flankenbit immer von rechts in rTastFlanken einschiebst (mit „lsl“-Anweisung). Ich würde
    den ganzen Vorgang direkt nach dem Aufruf von „NEXT0_TAST_ZST“ verschieben, dann erwischst
    Du die Flanke sofort nachdem sie erkannt wurde."
    #####
    meinst Du es so?:
    clc
    sbrc r16,3
    sec
    lsl rTastFlanken
    clc - loesche das CaryFlag "0"
    sbrc r16,3 - ist das Bit3 von r16(FlankenBit) nicht gesetzt Ueberspringe das >>>
    sec - setzen des CaryFlag "1"
    lsl rTastFlanken - schiebt dann, in Abhaengigkeit vom FlankenBit, das gesetzte bzw. nicht gesetzte CaryFlag ins Register rTastFlanken.
    xxxx xxxx ; xxxx xxx0 ; xxxx xx01 ; xxxx x011 ; xxxx 0111 ; xxx0 1111 ; xx01 1110 ; x011 1100 ; 0111 1001
    // Frage: Warum nicht "lsr"? - Dann kann die bisherige Reihenfolge bestehen bleiben.
    xxxx xxxx ; 0xxx xxxx ; 10xx xxxx ; 110x xxxx ; 1110 xxxx ; 1111 0xxx ; 0111 10xx ; 0011 110x ; 1001 1110

    Das mit den macro ist ne tolle Sache.
    Hatte ich auch noch nie verwendet. Und hier nun ein sinnvolles, praktisches Bsp.
    >>> wiederkehrende Prozesse sollte man ausgliedern <<<

    Habe noch einen weiteren Fehler gefunden. Auch der hat sich mir erst in der Praxis geboten.
    Nachdem ich ja das Problem mit dem Timer nicht gleich gefunden hatte, probierte ich unterschiedliche Einstellungen aus ( der Wert "155") z.B.
    Meine Programm hat nur sehr schlecht, das gemacht was es sollte.
    Das Druecken der Taste bewirkte zwar ein Einschalten und Ausschalten der LED ... aber nur wenn der ISR Abstand gross gewaehlt war
    und auch nicht immer...
    Mein Fehler ist, dass eine Flanke nur das FlankenBit auswerte. Dabei ausser Betracht lasse, wo diese herkommt.
    Bit 3 von "F" oder von "8"... boeser Denkfehler
    Eine Moeglichkeit ware nun zwei Register r0TastFlanken und r1TastFlanken mit der Auswertung von "F" und "8" anstatt von Bit 3 zu befuellen.
    Ueber eine weitere Moeglichkeit denke ich noch nach....
    ### Silvio ###

  3. #53
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    robo_wolf,

    Zitat Zitat von robo_wolf
    meinst Du es so?:
    Jup, genau so - bis auf den Fehler, den diesmal ich eingebaut habe : Mit der "lsl"-Anweisung wird immer eine Null von rechts in das Register eingeschoben. Wenn man das Carry-Flag von rechts einschieben will, muss man die "rol"-Anweisung nehmen! Sorry. Es muss also so heissen:
    Code:
    clc
    sbrc r16,3
    sec
    rol rTastFlanken
    Natürlich kannst Du die Flankenbits auch von links her einschieben ("ror"-Anweisung); nur ist das Flankenbyte dann nicht automatisch rechtsbündig, d.h. bis Bit0 besetzt. Es sei denn, Du hättest genau 8 Tasten verarbeitet.

    Zitat Zitat von robo_wolf
    Bit 3 von "F" oder von "8"... boeser Denkfehler
    Ich wollte Dir sowieso vorschlagen, einfach das Bit0 des Z-Wertes zum Steuern der LED zu verwenden. Das zeigt direkt den aktuellen Tastenzustand an. Das Flankenbit könntest Du verwenden, um zu entscheiden, ob die LED ihren Leuchtzustand ändern muss oder nicht. Sich nur auf die Flanke zu verlassen ist riskant. Wie Du ja festgestellt hast, kommt man da leicht aus dem Tritt.

    Ciao,

    mare_crisium

  4. #54
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    55
    Beiträge
    310
    Hallo mare_crisium,

    habe den Code umgeschrieben und einige Probleme damit gehabt.
    Thema macro:
    eigendlich hatte ich mir ein macro fuer das Sichern der Flanke nach Deinen Tipps gemacht...
    Aber bin dabei auf folgende Probleme gestossen:
    Zum Einen hatte ich das macro unter die ISR gesetzt und mich dann beim assemblieren gewundert, warum 2 Fehlermeldungen kamen.
    "unbekannte instruction oder macro.."
    ->>> macro muss vor dem Aufruf bekannt sein - habe es dann unter RESET abgelegt. -> Fehlermeldungen waren dann weg.
    Mein 2. Problem tauchte dann auf als das macro ins Unterprogramm verzweigen sollte -
    das Unterprogramm kam mit ret nicht mehr ins macro zurueck - dafuer aber leider zum RESET.
    Code:
    .macro _FLANKE_SICHERN
      clc
      cpi r16, 0x0F
      brne SET_CARY_FLAG
      rol rTastFlanken
    .endmacro ; 
    ;
    SET_CARY_FLAG:
      sec
    ret
    So habe ich dann doch sub´s verwendet.
    FRAGE??? Das macro muss also vor dem Aufruf bekannt sein?
    FRAGE??? Man kann im macro nicht verzweigen?
    Habe mal wieder ein Gang zurueck geschaltet und nur Taste0 und Taste1 behandelt.
    Ausserdem die ISR-Zeit deutlich eingekuerzt von 0,25 auf 0,05sec
    0,25 war sehr traege - da ja erst nach dem 4. Durchlauf die Flanken gestetzt werden, sind es in Summe ja 1sec.
    Das Auswerten der LOW_Flanke habe ich auch heraus gelassen - es soll ja nur bei HIGH eine Aenderung am LED_PORT geben.

    Code:
    ;***** STK500 Lernprogramm Nr.4e1 
    ;*** Aufgabe: die Taste an PinD0 schaltet die zugeordnete LED auf dem STK500 
    ;*** 1. Tastendruck: LEDs einschalten 
    ;*** 2. Tastendruck: LEDs ausschalten 
    ;*** eine Timerroutine liest den TastenStatus ein 
    ;*** zum Entprellen - muss die TimerRoutine 3mal hintereinander den gleichen Wert, 
    ;*** einlesen um einen Tastzustand zu erkennen
    ;*** die Flanken der Tastzustaende werden in rTastFlanken gesammelt und schalten die LEDs um
    ;*** Taste nicht gedrueckt >>> log 0  
    ;*** Taste gedrueckt       >>> log 1  
    ; 
    ; 
    .include "m8515def.inc" 
    .def Temp             = r16     ; Temporary Register 
    .def rTastFlanken     = r0     ; Zustandsvariable - beinhaltet eine 2Bit-Zahl zur Tastzustandserkennung 
    .def rLED_Update_SPRR = r21     ; Sperrt die Ausfuehrung von TastenTest wenn, keine neuer TIMER1_OVL voran gegangen    
    ; 
    .equ Timerwert   = 6249        ; Timerschritte bis zum Überlauf 0,05 sec
    ;
    .equ LED_PORT = PORTB           ; LEDs 
    .equ LED_DDR  = PORTB-1         ; DataDirectory fuer LEDs 
    ;
    .equ TAST_PORT= PORTD           ; Tasten 
    .equ TAST_DDR = PORTD-1         ; DataDirectory fuer TastenEingang 
    .equ TAST_PIN = PORTD-2         ; TastenEingang 
    ;                
    ; Pinzuordnung für div. Tasten 
    .equ TASTE0_PIN = 0 
    .equ TASTE1_PIN = 1 
    .equ TASTE2_PIN = 2             ; die Zuordnung der PINs muss ja nicht mit der TastenNr übereinstimmen! 
    .equ TASTE3_PIN = 3
    .equ TASTE4_PIN = 4
    .equ TASTE5_PIN = 5
    .equ TASTE6_PIN = 6
    .equ TASTE7_PIN = 7
    ;
    ; jetzt kommen die Register, die die Z-Werte der Tasten enthalten.. 
    .def rTASTE1_0_ZST = r15 ; enthält Zustand Taste1 im oberen Nibble und 0 im unteren Nibble
    .def rTASTE3_2_ZST = r14 ; enthält Zustand Taste3 im oberen Nibble und 2 im unteren Nibble 
    .def rTASTE5_4_ZST = r13 ; enthält Zustand Taste5 im oberen Nibble und 4 im unteren Nibble 
    .def rTASTE7_6_ZST = r12 ; enthält Zustand Taste7 im oberen Nibble und 6 im unteren Nibble 
    ; 
    ;   Vektortabelle 
    ; 
       rjmp RESET                 ;  1 - $000 RESET      External Pin, Power-on Reset, Brown-out, Reset and Watchdog Reset 
       reti                       ;  2 - $001 INT0       External Interrupt Request 0 
       reti                       ;  3 - $002 INT1       External Interrupt Request 1 
       reti                       ;  4 - $003 TIMER1 CAPT Timer/Counter1 Capture Event 
       rjmp TIMER1_COMPA_ISR      ;  5 - $004 TIMER1 COMPA Timer/Counter1 Compare Match A 
       reti                       ;  6 - $005 TIMER1 COMPB Timer/Counter1 Compare Match B 
       reti                       ;  7 - $006 TIMER1 OVF Timer/Counter1 Overflow 
       reti                       ;  8 - $007 TIMER0 OVF Timer/Counter0 Overflow 
       reti                       ;  9 - $008 SPI,       STC   Serial Transfer Complete 
       reti                       ; 10 - $009 USART,     RXC USART, Rx Complete 
       reti                       ; 11 - $00A USART,     UDRE USART Data Register Empty 
       reti                       ; 12 - $00B USART,     TXC USART, Tx Complete 
       reti                       ; 13 - $00C ANA_COMP   Analog Comparator 
       reti                       ; 14 - $00D INT2       External Interrupt Request 2 
       reti                       ; 15 - $00E TIMER0     COMP Timer/Counter0 Compare Match 
       reti                       ; 16 - $00F EE_RDY     EEPROM Ready 
       reti                       ; 17 - $010 SPM_RDY    Store Program memory Ready 
    ; 
    TBL_UEBERGANG_01: 
    .dw 0x0008  ; Tabellenlänge 
    ;                        T = 0               T = 1 
    .dw 0x0200  ;     Z=0 ->      Z=0,Flanke=0     /     Z=2,Flanke=0 
    .dw 0x0308  ;     Z=1 ->      Z=0,Flanke=1     /     Z=3,Flanke=0 
    .dw 0x0400  ;     Z=2 ->      Z=0,Flanke=0     /     Z=4,Flanke=0 
    .dw 0x0501  ;     Z=3 ->      Z=1,Flanke=0     /     Z=5,Flanke=0 
    .dw 0x0602  ;     Z=4 ->      Z=2,Flanke=0     /     Z=6,Flanke=0 
    .dw 0x0703  ;     Z=5 ->      Z=3,Flanke=0     /     Z=7,Flanke=0 
    .dw 0x0F04  ;     Z=6 ->      Z=4,Flanke=0     /     Z=F,Flanke=1 
    .dw 0x0705  ;     Z=7 ->      Z=5,Flanke=0     /     Z=7,Flanke=0 
    
    ;
    RESET: 
    ; 
       ldi r16, LOW(RAMEND)           ;Stack initialisieren 
       out SPL, r16 
       ldi r16, HIGH(RAMEND) 
       out SPH, r16 
    ; 
    ;   ldi temp,(1<<CS10)|(1<<WGM12)            ; Taktfrequenz Vorteiler 1 gewaehlt (fuer Simaulatortest)          
       ldi temp,(1<<CS10)|(1<<CS11)|(1<<WGM12)   ; Taktfrequenz mit Vorteiler 64 gewaehlt            
        out TCCR1B,temp 
    ; 
        ldi temp,HIGH(Timerwert) 
       out OCR1AH,temp 
        ldi temp,LOW(Timerwert) 
       out OCR1AL,temp 
    ; 
       ldi temp,(0<<COM1A1)|(0<<COM1A0) 
       out   TCCR1A,temp 
       ldi temp,(1<<OCIE1A)    ; Timer1 Overflow aktivieren 
       out TIMSK,temp          
    ; 
       clr Temp                ;Temp mit 0b00000000 bzw. 0x00 laden 
       out TAST_DDR, Temp      ;PORTD als Eingang 
       ser Temp                ;Temp mit 0b11111111 bzw. 0xFF laden 
       out TAST_PIN, temp      ;STK500 schaltet gegen GND - Taste gedreuckt (Pin==0) 
       out TAST_PORT, temp     ;PullUp an PortD einschalten 
       out LED_DDR,Temp        ;PORTB als Ausgang 
       out LED_PORT, temp      ;PORTB (LEDs) aus 
    ;    
    ; Tastenzustände aller Tasten auf Null setzen 
       clr r16               ; 
       mov rTASTE1_0_ZST,r16      ; Taste0 und Taste1 zurücksetzen 
       mov rTASTE5_4_ZST,r16      ; Taste2 und Taste3 zurücksetzen 
    ; 
       sei 
    ;????
    ; hier soll das Ruecksichern aus dem EEPROM erfolgen - ; lds temp, ????
    ; und                                                  ; out LED_PORT, temp
    ;!!!! 
    MAIN: 
       sbrc rLED_Update_SPRR,0   ; kein LED_Update, wenn Bit0 ==0 
       rcall LED_Update 
       rjmp MAIN 
    ; 
    LED_Update: 
    ;
    ; LED_PORT auslesen - mit TastenZustand verarbeiten - LED_PORT ausgeben
       push temp
       in temp, LED_PORT         ; LED_PORT einlesen
       eor temp, rTastFlanken    ; toggle das Bit im LED_PORT fuer das eine Flanke in rTastFlanken ansteht
       out LED_PORT,temp         ; LED_PORT augeben
    ;????
    ; hier soll noch ins EEPROM gesichert werden ; sts ????, temp
    ; LED_PORT sichern
    ;!!!!   
       cbr rLED_Update_SPRR,1    ; loesche Bit0, um LED_Update bis zur naechsten TIMER1_ISR zu sperren 
       clr rTastFlanken          ; setze rTastFlanken zum erneuten Beschreiben auf 0x00
       pop temp
    ret 
    ; 
    
    /*------------------------------------- 
    
    INTERRUPTDIENST TIMER1_COMPA_ISR 
    
    Die Interruptdienstprogramm TIMER1_COMPA_ISR wird vom Output-Match-Interrupt von 
    Timer1 ausgelöst. Es liest die aktuellen Messwerte der Tasten vom TAST_PIN ab und 
    berechnet für jede Taste den neuen Zustand (Z-Wert). 
    
    Eingansgrössen: 
       keine 
    
    Ausgangsgrössen: 
       keine 
    
    geänderte Register 
       keine 
    
    Anzahl Zyklen 
    
    */ 
    
    TIMER1_COMPA_ISR: 
       push r25 
       in r25,SREG 
       push r1      ; Register r1 - temporaeres Register fuer Unterprogramme
       push r20     ; Register r20 - temp. Bit fuer rTastFlanken(uebergibt Unterprogramm den Tastursprung)
       push r16 
       push r17 
       push r18 
       push r19     ; Register r19 - temporaeres Register fuer swap
       push zl 
       push zh 
    ;
       ldi zl,LOW(TBL_UEBERGANG_01)  ; zh:zl := Zeiger auf Übergangstabelle ... 
       ldi zh,HIGH(TBL_UEBERGANG_01) ; ...wird für NEXT0_TAST_ZST gebraucht 
    ;
    ; Betätigungszustand der Tasten einlesen und der Reihe nach verarbeiten 
       in r18,TAST_PIN         ; r18 := Messwerte aller Pins 
       com r18                 ; invertier r18
    ;
    ; Taste1 und Taste0 verarbeiten und in Register TASTE1_0_ZST 
    ;
    ; Taste1 verarbeiten (!!! Achtung oberes Nibble von rTASTE1_0_ZST 0b????xxxx)
       rcall CLEAR_REGISTER
       ldi r20, 2              ; tmp. Tastenursprung - fuer Bitbestimmung in rTastFlanken
       bst r18,TASTE1_PIN      ; überträgt den Messwert von TASTE1_PIN ins T-Flag von SREG 
    ; lade TASTE1_0_ZST in R1 und loesche MSB (oberes Nibble)
       mov r1, rTASTE1_0_ZST   ; temp Register fuer SET_XXX_NIBBLE - uebernimmt rTastx_y_ZST
       rcall GET_HIGH_NIBBLE   ; hole HIGH_NIBBLE nach r16
       rcall FLANKE_SICHERN    ;
       andi r16,0x07           ; loesche MSB (eigentlichliches LSB) und "Flankenbit"
       mov r19,r16             ; r16 := Z-Wert Taste1 
       rcall NEXT0_TAST_ZST    ; Folgezustand für Taste1 in r16 berechnen 
       rcall SET_HIGH_NIBBLE    ; bereite HIGH_NIBBLE fuer Ruecksichern vor
       mov rTASTE1_0_ZST,r16   ; neuen Z-Wert von Taste1 in TASTE1_0_ZST speichern 
    ;
    ; Taste0 verarbeiten (!!! Achtung unteres Nibble von rTASTE1_0_ZST 0bxxxx????)
       rcall CLEAR_REGISTER
       ldi r20, 1              ; tmp. Tastenursprung
       bst r18,TASTE0_PIN      ; überträgt den Messwert von TASTE0_PIN ins T-Flag von SREG 
    ; lade TASTE1_0_ZST in R1 und loesche MSB (oberes Nibble)
       mov r1, rTASTE1_0_ZST   ; temp Register fuer SET_XXX_NIBBLE
       rcall GET_LOW_NIBBLE    ; hole LOW_NIBBLE nach r16
       rcall FLANKE_SICHERN    ;
       andi r16,0x07           ; "Flankenbit" und MSB löschen 
       rcall NEXT0_TAST_ZST    ; Folgezustand für Taste0 in r16 berechnen 
       rcall SET_LOW_NIBBLE    ; bereite LOW_NIBBLE fuer Ruecksichern vor
       mov rTASTE1_0_ZST,r16   ; neuen Z-Wert von Taste0 in TASTE1_0_ZST speichern 
    ;
       sbr rLED_Update_SPRR,1  ; setze Status fuer LED_Update 
    ;
       pop zh 
       pop zl 
       pop r20
       pop r19
       pop r18 
       pop r17 
       pop r16 
       pop r1
       out SREG,r25 
       pop r25 
    reti 
    ;
    ; Vergleich ob im Flanke fuer gedrueckte Taste(0xF) erreicht wurde - 
    ; bei Erreichen wird eine 1 ;  bei nicht Erreichen eine 0 in rTASTFLANKEN mit Hilfe des CARY_FLAGs von links nach rechts rotiert
    ;
    CLEAR_REGISTER:
       clr r1				   ; Register r1 -  temporaeres Register fuer Unterprogramme
       clr r16				   ; Register r16 
       clr r19				   ; Register r19 - temporaeres Register fuer swap
       clr r20				   ; Register r20 - temporaeres Register fuer Unterprogramme
    ret
    ;
    GET_HIGH_NIBBLE:
       mov r16, r1
       swap r16                ; tausche MSB mit LSB
    ret
    ;
    GET_LOW_NIBBLE:
       mov r16,r1              ; r16 := Z-Wert Taste0
    ret
    ;
    ; Flanke sichern
    ; hatte es mit dem links schieben versucht, aber mit der zusaetzlichen Variablen r20 bin ich flexibler in der Tastenwahl
    ; FRAGE??? 
    ; meine Loesung funktioniert zwar - aber scheint umstaendlich
    ; wie kann ich es in einem Unterprogramm realisieren?
    ;
    ; setze Tast_FLAG wenn rTastx.. oder ..y_ZST 0b00001111 erreicht
    FLANKE_SICHERN:
      cpi r16, 0x0F
      breq SET_TAST_FLAG
    ret
    ;
    SET_TAST_FLAG:
      or rTastFlanken, r20
    ret
    ;
    SET_HIGH_NIBBLE:
       swap r16                ; tausche MSB mit LSB
    ; schiebe rTASTE1_0_ZST in R19 und loesche MSB fuer neues Z von Taste1
       mov r19, r1             ; hole rTASTx_y_ZST in r19
       andi r19,0x0F           ; loesche altes Z (MSB)
       or r16, r19             ; vereine MSB und LSB in rTASTE1_0_ZST
    ret
    ;
    SET_LOW_NIBBLE:
    ; schiebe rTASTEx_y_ZST in R19 und loesche LSB fuer neues Z von jeweiligen Taste
       andi r16,0x0F           ; loesche MSB fuer or
       mov r19, r1             ; hole rTASTx_y_ZST in r19
       andi r19,0xF0           ; loesche altes Z (LSB)
       or r16, r19             ; vereine MSB und LSB in rTASTE1_0_ZST
    ret
    ;
    /*------------------------------------- 
    
    PROZEDUR NEXT0_TAST_ZST 
    
    Die Prozedur NEXT0_TAST_ZST liest den Folgezustand der Tastenentprellung aus einer 
    Übergangstabelle aus. Die Adresse der Tabelle wird in zh:zl übergeben. Der aktuelle 
    Zustand (Z-Wert) wird in r16 übergeben. Der aktuelle Tastenzustand (betätigt/nicht 
    betätigt) ist im T-Flag von SREG gespeichert. Das Ergebnis wird in r16 zurückgegeben. 
    Die Tabelle, darf maximal 127 Einträge enthalten. Der erste Eintrag der Tabelle ist 
    die Länge der Tabelle und dient der Bereichsüberprüfung. 
    
    D.h. der Zeiger auf die Übergangstabelle muss zh:zl geladen werden BEVOR diese 
    Prozedur aufgerufen wird!! In diesem Beispiel, bei dem nur eine einzige Übergangstabelle 
    im Spiel ist, könnte man zh:zl auch innerhalb von NEXT0_TAST_ZST laden. Um die 
    Prozedur auch in Programmen verwenden zu können, in denen mehrere Zustandsautomaten 
    nebeneinanderherlaufen, ist es sinnvoll, den Zeiger vorher zu laden. Dann kann je 
    nach Aufgabe eine andere Tabelle verwendet werden. Kommt in meinen Programmen öfters 
    vor ;-). 
    
    Eingansgrössen: 
       r16      : enthält aktuellen Z-Wert der Taste 
       zh:zl   : enthält Zeiger auf die Übergangstabelle 
       SREG (T-Flag) : enthält den aktuellen Messwert der Taste 
          T = 0 : Taste nicht betätigt 
          T = 1 : Taste betätigt 
    
    Ausgangsgrössen: 
       r16      : enthält den neuen Z-Wert für die Taste 
       zh:zl   unverändert 
       SREG   unverändert 
    
    geänderte Register 
       r16 
    
    Anzahl Zyklen 
    
    */ 
    
    NEXT0_TAST_ZST: 
       push r17 
       in r17,SREG 
       push r17 
       push r18 
       push zl 
       push zh 
    
    ; Zeiger auf Anfang der Übergangstabelle berechnen 
       add zl,zl        ; zh:zl verdoppeln, weil einer Adresse im... 
       adc zh,zh        ; .. Programmspeicher immer zwei Bytes entsprechen 
       ; 
       ; 
    ; Information in Bit7 löschen; Tabelle darf nicht länger als 127 Einträge sein 
       andi r16,0x7F    ; 
    
    ; Tabellenlänge einlesen (0-ter Eintrag in der Tabelle) 
       lpm r17,z+       ;  r17 := TBL_LNG einlesen 
       ; 
       lpm r18,z+       ;  zweites Byte überlesen, wird nicht gebraucht 
    
    ; Bereichsprüfung ( r17 < TBL_LNG ) 
       cp r16,r17       ; Tabellenindex mit TBL_LNG vergleichen 
       brlt NXT0ZST_00  ; Sprung, wenn Tabellenindex iO (wenn r16 kleiner r17)
    
    ; Fehler: Tabellenindex ist zu gross 
       clr r16 ; Zustand auf Null setzen 
       rjmp NXT0ZST_EXIT ; fertig 
    
    NXT0ZST_00: 
    ; Tabellenindex im zulässigen Bereich 
       clr r17 ; 
       add zl,r16       ; Index zweimal zum Zeiger addieren, weil... 
       adc zh,r17       ; ... in der Tabelle... 
       add zl,r16       ; ... 2-Byte-Worte gespeichert sind. 
       adc zh,r17       ; zh:zl := Zeiger auf Tabelleneintrag    
       lpm r16,z+       ; r16 := Folgezustand für T=0 
       lpm r17,z        ; r17 := Folgezustand für T=1 
       brtc NXT0ZST_EXIT ; fertig, wenn T = 0 
    
    ; T = 1, d.h. Taste betätigt 
       mov r16,r17      ; zweiten Eintrag als Folgezustand verwenden 
    
    NXT0ZST_EXIT: 
    
       pop zh 
       pop zl 
       pop r18 
       pop r17 
       out SREG,r17 
       pop r17 
    ret 
    ;
    ### Silvio ###

  5. #55
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    robo_wolf,

    ja, beim Definieren und Benutzen der Macros gibt's Einiges zu beachten; das hätte ich ausführlicher erklären sollen. Alle Macros müssen vor der ersten Verwendung definiert sein. Die Definition darf sogar vor der CSEG- bzw. der ORG-Anweisung stehen. Ist eigentlich auch logisch, bei der Definition ist es ja noch nicht Teil des Quelltextes.

    Noch wichtiger ist, mit den Sprüngen und "ret"-Anweisung innerhalb Macros sehr vorsichtig umzugehen. Ich rate davon ab, Sprunganweisgungen zu verwenden, die aus dem Macro herausführen. Da verliert man zu schnell den Überblick. Reine "ret"-Anweisung in einem Macro führen im Allgemeinen direkt ins Nirwana, weil meist der Stack nicht richtig wiederhergestellt wird, oder gar keine Rückkehradresse auf dem Stack liegt.

    Vorschlag: Am Übersichtlichsten ist es, alle Macros ganz am Anfang des Quelltextes, noch vor der CSEG- oder ORG-Anweisung zu definieren. Dann weiss man immer, wo man nachgucken kann, wenn man mal wieder vergessen hat, was sie eigentlich bewirkten. Keine "ret"-Anweisungen in einem Macro ohne vorherige "call"- oder "rcall"-Anweisung in demselben Macro. Sprünge nur innerhalb des Macros zulassen.

    Damit sähe Dein Macro dann so aus:

    Code:
    .macro _FLANKE_SICHERN
      clc
      cpi r16, 0x0F
      brne PC+2
      sec
      rol rTastFlanken
    .endmacro ;
    Dabei verwende ich einen relativen Sprung: Die Anweisung "brne PC+1" bewirkt Folgendes: Wenn Gleichheit festgestellt wird, dann wird die Anweisung an der Adresse ausgeführt, auf die der PC (Program counter) gerade zeigt. Das ist die Anweisung direkt nach der "brne"-Anwesiung, also "sec". Wenn Ungleichheit festgestellt wird, dann springt das Programm zur Adresse PC+2, d.h. zur "rol"-Anweisung. Praktisch, gell ? Das geht übrigens auch rückwärts, also PC-X. Die Sprungdistanz ist begrenzt (-128 bis +127).

    Die "ret"-Anwweisung brauchst Du gar nicht. Das Macro verhält sich ja so, als ob Du ihren Quelltext mit "copy" und "paste" in den laufenden Quelltext eingefügt hättest.

    Probier's mal, damit solltes klappen. Die Kommentare zu Nr. 4e1 kommen später .

    Ciao,

    mare_crisium

    EDIT: Den Fehler (Sprungweite) im Macro korrigiert.

  6. #56
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    robo_wolf,

    na, es doch geht voran . Bevor wir neue "Features" in Angriff nehmen, ist es an der Zeit, sich noch einmal Überblick zu verschaffen, Überflüssiges bzw. Vermeidbares abzuschrauben und fertige Module in eine Bibliothek auszulagern (siehe Kommentare in angehängter pdf-Datei).

    Als Quelltext darf ich's nicht einfügen, weil's angeblich mehr als 20000 Zeichen hat . Leider musst Du den Text jetzt aus dem pdf herausfummeln.

    Ciao,

    mare_crisium

    EDIT: Die Fehler verbessert (hoffentlich alle !), die robo_wolf entdeckt hat.
    Angehängte Dateien Angehängte Dateien

  7. #57
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    55
    Beiträge
    310
    Hallo mare_crisium,
    vielen Dank fuer den neuen Lehrstoff. )
    Habe gleich ein paar Fragen dazu.
    Im MACRO _FLANKEN_SICHERN hast Du "@0" verwendet und als Parameter beschrieben.
    Code:
    .macro _FLANKEN_SICHERN
    bst r16,3
    bld rTAST_FLANKEN,(@0)
    .endmacro
    ..muss das "@0" in Klammern()?
    oder muss nur der zu uebergebene Parameter "LED_TASTE_x" beim macro-Aufruf
    _FLANKEN_SICHERN(LED_TASTE_x) in Klammern?
    Eins muss ich aber noch gleich loswerden:
    "Es ist schon eine sehr galante und uebersichtliche Loesung."

    Im Uebergang von Seite 4 auf 5 ist mir eine Ungereimtheit aufgefallen.
    Code:
    SET_LOW_NIBBLE:
       push r25
       in r25,SREG
       andi r16,0x0F ; oberes Nibble des Wertes in r16 (Quelle) löschen
       andi r19,0x0F ; unteres Nibble in r19 (Ziel) ebenfalls löschen
       or r19, r16   ; neuens oberes Nibble in r19 einfügen
       out SREG,r25
       pop r25
    ret
    muss es hier nicht so heissen?(eventuell ein Tippfehler?)
    Code:
    SET_LOW_NIBBLE:
       push r25
       in r25,SREG
       andi r16,0x0F ; oberes Nibble des Wertes in r16 (Quelle) löschen
       andi r19,0xF0 ; unteres Nibble in r19 (Ziel) ebenfalls löschen
       or r19, r16   ; neuens oberes Nibble in r19 einfügen
       out SREG,r25
       pop r25
    ret
    An meinen Kommentaren muss ich auf jeden Fall noch arbeiten.
    Im Nachhinein liest sich vieles nicht unbedingt verstaendlich - meine Kommentare beschreiben oft nur den eigentlichen Programmschritt.
    Das ist fuer mich momentan natuerlich relevant, da mir viele Befehle neu und nicht gelaeufig sind.
    Der Sinn der Befehlsfolge bleibt dann oft auf der Strecke... >>> Verbesserungspotential
    ### Silvio ###

  8. #58
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    robo_wolf,

    jup, hast recht mit Deinen Vermutungen: Die Prozedur SET_LOW_NIBBLE habe ich korrigiert, wie Du vorgeschlagen hast. Im Macro "FLANKEN_SICHERN" habe ich die Klammern gelöscht. Die korrigierte Version ist an meinem vorangehenden Posting angehängt.

    Wo hast Du denn die "galante Lösung" her? Was ein Buchstabe doch für einen hübschen Unterschied machen kann !

    An den Kommentaren zu arbeiten lohnt sich immer. Der Aufwand für's Kommentieren wird aber mit der Zeit geringer, weil Du Deinen persönlichen Programmierstil entwickeln wirst. Das führt dann dazu, dass Du für typische Aufgaben bestimmte Befehlsfolgen verwenden wirst, deren Funktion Du auf Anhieb wiedererkennst. Dadurch erübrigen sich manche Kommentare von selbst.

    Ciao,

    mare_crisium

  9. #59
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    02.11.2005
    Ort
    Bayern
    Alter
    55
    Beiträge
    310
    Hallo mare_crisium,
    in Deinem Posting vom 01.03. hast Du die Loesung mit dem Manipulieren des PC beim macro beschrieben.
    Beim Testen im Simulator bin ich leider nicht zum gewuenschten Erfolg gekommen.
    Code:
    .macro _FLANKE_SICHERN 
      clc 
      cpi r16, 0x0F 
      brne PC+1 
      sec 
      rol rTastFlanken 
    .endmacro ;
    PC+1 bewirkt doch nur einen Schritt weiter. In dem Fall des macro waere es "sec" bei Ungleichheit und bei Gleichheit ist es auch nur "sec". PC+2 waere dann "rol"-Anweisung und damit funktioniert es auch im Simulator.

    Du wolltest mich testen?
    ### Silvio ###

  10. #60
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.12.2005
    Beiträge
    535
    Zitat Zitat von robo_wolf
    Du wolltest mich testen?
    wenn ich's gewollt hätte, hättest Du mit 100 Punkten bestanden !

    Der Grund für meinen Fehler ist erstens, dass ich's nicht ausprobiert habe und zweitens meine Gewohnheit, PC immer so zu behandeln, als sei der aktuelle Befehl schon ausgeführt. Unter anderem deshalb benutze ich relative Sprünge nur noch in Macros. Mein Lieblingsfehler ist, zwischen Sprunganweisung und -ziel noch ein paar Anweisungen einzuflicken und nicht daran zu denken, die Sprungweite zu vergrösern. Diese Dinger sind nur mit allergrösster Vorsicht zu geniessen.

    Ciao,

    mare_crisium

Seite 6 von 14 ErsteErste ... 45678 ... LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress