-
        

Ergebnis 1 bis 8 von 8

Thema: Tastenzähler mit PIC16F628A

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    26.01.2011
    Beiträge
    10

    Tastenzähler mit PIC16F628A

    Anzeige

    Hallo

    ich habe ein großes Problem, ich weiß nicht wie ich anfangen soll...
    Alsoo ich habe schon ein Programm geschrieben das wunderbar funktioniert.
    Sobald ich auf eine Tastatur drücke, führt der PIC einen Befehl aus und am Display erscheint eine meldung.

    nur jz. würde ich gerne mitzählen wie oft diese Taste Gedrückt wurde und anschließend am Display ausgeben? geht das?

    bitte um hilfe
    danke

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    938
    Hast du schon einen Timer-Interrupt laufen, der auch noch während der Zeitdauer minimal kurzer Tastendrücke mehrfach aufgerufen wird? Z.B. alle 1..10 Millisekunden? Wenn ja, prima; wenn nein, müsstest du eine soche Zeitbasis in deinem Programm einrichten.
    In der Interruptroutine (ISR) wird dann die Portleitung der Taste bei jedem Durchlauf einmal gelesen. Ist sie gerade aktiv, wird eine Variable key_count um eins erhöht, weiter nichts.
    Wenn die Portleitung bei einem späteren ISR-Durchlauf nicht mehr aktiv ist, wird der Tastvorgang als abgeschlossen betrachtet und es wird ausgewertet:
    - ON-Zeit kleiner z.B. 20ms ist nur Kontaktprellen und wird ignoriert, key_count wird gelöscht.
    - ON-Zeit 20..250ms wird als gültiger Tastendruck interpretiert, es wird eine Variable à la key_event mit einem Wert ungleich Null beschrieben und der Zähler key_count wieder gelöscht.
    key_event ist ein Signal an das pollende (Haupt-)Programm, daß ein gültiger Tastendruck erfolgte.
    Das Hauptprogramm prüft key_event <> 0, inkrementiert ggf. einen eigenen Ereigniszähler und löscht seinerseits das von der ISR gelieferte und nun verwertete Tastenevent key_event.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    26.01.2011
    Beiträge
    10
    dankeschön für die schnelle antwort

    das muss ich mir einmal durchdenken, bin ganz neu in diesem Sektor

    weist du vl. ein beispiel prog. wo ich mir das einmal anschauen könnte=?
    wie das genau funktioniert mit dem Timer und so?

    mfg mario

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    30.09.2006
    Ort
    Hamburg
    Alter
    35
    Beiträge
    988
    @RoboH...

    Das dürfte nicht genau genug sein wen du den Taster auf PB0 hast kannst damit nen Interupt auslösen
    Legastheniker on Bord !

    http://www.Grautier.com - Projektseite
    http://www.grautier.com/wiki/doku.php?id=bt-index - BT-BUS

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    26.01.2011
    Beiträge
    10
    hmm.....
    kann mir irgendwer einen Ansatzt für dieses Problem schicken??

    einen Programmcode in Assembler were interessant bzw. nur tipps.

    dankeee

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    938
    @theborg
    1..10ms Zeitauflösung, Finger-betätigte Taste, nicht genau genug ?
    Na, ich weiß nicht.
    Ein Taster an 'ner Interruptleitung muß auch wieder per HW oder Code entprellt werden. Und wenn grad' eine ISR aktiv ist, dauert's ja auch wieder, bis der Taster erkannt wird.
    Letztlich wird die PB0-Variante genauso gut funktionieren wie mein Vorschlag.

    @mario2104
    Ich werd zusehen, daß ich dir einen Extrakt eines meiner ASM-Programme liefern kann, wo ich so was realisiert habe.

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    26.01.2011
    Beiträge
    10
    @RoboHolIC
    dankee ur leiwand von dir

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    03.09.2009
    Ort
    Berlin (Mariendorf)
    Beiträge
    938
    Sooo, da bin ich wieder.
    Ich habe -wie angekündigt- einen Extrakt meines aktuellen Projekts (das einfach nicht fertig werden will) angefertigt. Da sind alle Konfigurationen, Variablen, meine Tastenauswertung in voller Länge und kleine Anregungen für die Verwendung drin, die dich interessieren könnten.
    Ich hab auch noch weitere Kommentare eingefügt, die dir zum Verständnis helfen sollen.

    Code:
         list            p=16f876a            ; list directive to define processor             !!!!!!! ÄNDERN !!!!!!!
         #include        <P16F876A.INC>       ; processor specific variable definitions        !!!!!!! ÄNDERN !!!!!!!
    
        __CONFIG _CP_OFF & _DEBUG_OFF & _WRT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC   !!!!!!! ODER HALT ANDERS !!!!!!!!
    
        ;*****************************************************************************
        ; '__CONFIG' directive is used to embed configuration data within .asm file.
        ; The labels following the directive are located in the respective .inc file.
        ; See respective data sheet for additional information on configuration word.
        ;*****************************************************************************
    
    
    ; STATUS bit definitions
    
         #define    _C      STATUS,0            ; für die Kurzschreibung von Bitprüfungen:  "BTFSS _C"
         #define    _Z      STATUS,2            ;
    
    
    
    
    ; Hardware signals definitions
    
         #define    AUX5    sta_ra,4            ; Taste
    
    
    ;***** KONSTANTEN
       ;Tastenauswertung
    K_NONE              EQU        0x00         ; nix
    K_FUZZI             EQU        0x01         ; unklar
    K_CLICK             EQU        0x02         ; kurz
    K_PRESS             EQU        0x03         ; lang
    
    
    
    ;***********
    flax               EQU        0x27          ; diverse Flags
    sta_ra             EQU        0x63          ; Binärstatus von Port A
    iscr               EQU        0x6B          ; scratch in der ISR
    mscr               EQU        0x6C          ; scratch in der main()
    key_cnt            EQU        0x6E          ; Anz. ISR-Zyklen "Taste ununterbrochen LOW" (=aktiv)
    key_evt            EQU        0x6F          ; erkanntes Tastenevent
    
    
    ;***** GLOBALE VARIABLEN  0x70..0x7F
    x70                EQU        0x70          ;
    x71                EQU        0x71          ;
    x72                EQU        0x72          ;
    x73                EQU        0x73          ;
    x74                EQU        0x74          ;
    x75                EQU        0x75          ;
    x76                EQU        0x76          ;
    x77                EQU        0x77          ;
    x78                EQU        0x78          ;
    x79                EQU        0x79          ;
    dlycnt             EQU        0x7A          ; Delay-Restzyklen zu je 1ms
    ticker             EQU        0x7B          ; virtuelle Unruh; immerzu in Bewegung
    temp_w             EQU        0x7C          ; variable used for context saving
    temp_status        EQU        0x7D          ; variable used for context saving
    temp_pclath        EQU        0x7E          ; variable used for context saving
    temp_fsr           EQU        0x7F          ; variable used for context saving			
    
    
    
    
    
    
    
    
    ;**********************************************************************
    ;**********************************************************************
            ORG       0x0000    ; Begin of 2k-Code Page #0   (1st)
                                ; processor reset vector
    ;**********************************************************************
    ;**********************************************************************
    
             nop                      ; nop required for icd
             goto    MAIN             ; go to beginning of program
             nop
             nop
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    ;**********************************************************************
    ;**********************************************************************
             ORG     0x0004   ; interrupt vector location        ***************** hierher wird bei ALLEN Interrupt Requests verzweigt ****************
    ;**********************************************************************
    ;**********************************************************************
    
    
    ;**********   Kontext sichern   **********
             movwf   temp_w           ; save off current W register contents
             movf    STATUS,w         ; move status register into W register
             movwf   temp_status      ; save off contents of STATUS register
             movf    PCLATH,w         ; move pclath register into w register
             movwf   temp_pclath      ; save off contents of PCLATH register
             movf    FSR,w            ;
             movwf   temp_fsr         ;
    
             ; Lead-In
             ;bcf     INTCON,GIE       ; globales IRQ-Disable  ;;; das geschieht schon automatisch bei der IRQ response
             bcf     STATUS,RP0       ;
             bcf     STATUS,RP1       ; Bank 0 als default
             bcf     PCLATH,4         ;
             bcf     PCLATH,3         ; Code Page #0
    
             ; Identifizierung der Quelle
             btfsc   INTCON,T0IF      ; der Timer0 ?
             goto    ISR_TMR0         ;
             btfsc   PIR2,CCP2IF      ; das CCP2-Modul ?                                        Dummy zur Strukturdarstellung
             goto    ISR_CCP2         ;
             btfsc   INTCON,INTF      ; externer INT ?                                          Dummy zur Strukturdarstellung
             goto    ISR_INT          ;
    
             goto    ISR_RESTORE      ; !!! Fangleine !!! (gegen ungewollt aktive IRQs)
    
    
    
          ; ab hier die Service-Routinen für die verschiedenen IRQ-Quellen
    
    ;**********   ISR für den Timer0-Interrupt
    ISR_TMR0
             ; IRQ-flag löschen und preload
             bcf     INTCON,T0IF      ; Timer0-IRQ
             movlw   d'8'             ; 256-(250-2!) = 8 für 1000,0 Hz @ 16,00MHz   !!! DIESEN WERT AUCH BEIM INIT IM HAUPTPROGRAMM SETZEN !!!
             movwf   TMR0             ; preload = verkürzter Anlauf zum nächsten Überlauf-IRQ
    
             ; Eingänge lesen
             movf    PORTA,w          ;
             movwf   sta_ra           ; Port A in Abbildvariable einlesen
    
    
    
    
    ISR_TMR0_1                                        ;      ***********  ein paar kleine Anregungen **************
             ; Millisekunden-Eieruhr
             movf    dlycnt,f         ; Z-Flag generieren
             btfss   STATUS,Z         ;
             decf    dlycnt,f         ; dekr., wenn nicht null (Z=0)
    
    
             ; Millisekunden-Ticker  (= virtuelle Unruh)
             incf    ticker,f         ;
    
    
    
           ;  ***************** und hier wird es interessant für dich *******************
    
    ISR_KEY
             ; Tastenauswertung
               ; Tastenstatus elektrisch
             btfsc   sta_ra,4         ; LOW-aktiv !
             goto    ISR_KEY_1        ; NICHT betätigt, also auswerten
             incf    key_cnt,f        ; betätigt, also hochzählen
             movlw   d'255'           ; Endanschlag
             subwf   key_cnt,w        ;
             btfsc   STATUS,Z         ; auf Gleichheit prüfen
             decf    key_cnt,f        ; Zählerstand deckeln
             goto    ISR_KEY_TAIL     ; und Schluss
    ISR_KEY_1
               ; Ereignis-Erkennung
             movlw   d'20'            ; Max-Wert für Prellen
             subwf   key_cnt,w        ; 
             btfss   STATUS,C         ; überschritten ?
             goto    ISR_KEY_END      ; NEIN, dann Schluss
             movlw   K_CLICK          ; JA!
             movwf   key_evt          ; reicht für ein CLICK
    
             movlw   d'150'           ; Max-Wert für CLICK
             subwf   key_cnt,w        ; 
             btfss   STATUS,C         ; überschritten ?
             goto    ISR_KEY_END      ; NEIN, dann Schluss
             movlw   K_FUZZI          ; JA!
             movwf   key_evt          ; reicht für ein FUZZI
    
             movlw   d'250'           ; Max-Wert für FUZZI
             subwf   key_cnt,w        ; 
             btfss   STATUS,C         ; überschritten ?
             goto    ISR_KEY_END      ; NEIN, dann Schluss
             movlw   K_PRESS          ; JA!
             movwf   key_evt          ; reicht für ein PRESS
    ISR_KEY_END
             clrf    key_cnt          ; Event oder Prellen detektiert, daher löschen
    ISR_KEY_TAIL
    
    
             goto    ISR_RESTORE      ;                                       Ende der Serviceroutine für den Timer0-Interrupt
    
    
    ;**********   ISR für den CCP2-Interrupt   **********  das hier nur noch beispielhaft; es gehört zur anfänglichen Verzweigung
    ISR_CCP2
             ; das wäre der CCP2-Interrupt - derzeit ohne Funktion
             bcf     PIR2,CCP2IF      ; auslösendes Flag löschen
               ;   !!!!!!!!!  hier dazwischen gehört dein eigener Code  !!!!!!!!!!!!!
             goto    ISR_RESTORE      ;
    
    
    
    ;**********   ISR für den externen INT-Eingang   **********  das hier nur noch beispielhaft; es gehört zur anfänglichen Verzweigung
    ISR_INT
             ; das wäre der externe INT-Eingang - derzeit ohne Funktion
             bcf     INTCON,INTF      ; auslösendes Flag löschen
               ;   !!!!!!!!!  hier dazwischen gehört dein eigener Code  !!!!!!!!!!!!!
             goto    ISR_RESTORE      ;
    
    
    
    ISR_RESTORE
             ; Kontext wiederherstellen
             movf    temp_fsr,w       ;
             movwf   FSR              ;
             movf    temp_pclath,w    ; retrieve copy of PCLATH register
             movwf   PCLATH           ; restore pre-isr PCLATH register contents
             movf    temp_status,w    ; retrieve copy of STATUS register
             movwf   STATUS           ; restore pre-isr STATUS register contents
             swapf   temp_w,f         ; Kniff, um W zu laden, ohne den Status zu verändern !
             swapf   temp_w,w         ; restore pre-isr W register contents
    
             retfie                   ; return from interrupt (impliziert ein "bsf INTCON,GIE")
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    ;**********************************************************************
    MAIN                    ;  Das Hauptprogramm
    ;**********************************************************************
    
    
             clrf    INTCON           ; alle Interruptquellen sperren, alle IRQs verwerfen
    
    
    
             ; Timer0 konfigurieren
             bsf     STATUS,RP0       ; Bank 1
             clrwdt                   ; WDT-Register und implizit Prescaler löschen, das gehört sich so!
             movlw   b'10000011'      ; int sys clk, 1:16, prescale assg. to TMR0
             movwf   OPTION_REG       ;
             bcf     STATUS,RP0       ; Bank 0
             movlw   d'8'             ; Presetwert vgl. Timer0-ISR
             movwf   TMR0             ;
    
    
    
    
    
    
             ; Startzustände herstellen
             movlw   d'0'             ;
             movwf   ticker           ;
             movwf   flax             ; acht Flag-Bits
    
             movlw   K_NONE           ;
             movwf   key_evt          ;
    
             bsf     STATUS,RP0       ; Bank 1
             clrf    PIE1             ;
             clrf    PIE2             ;
             bcf     STATUS,RP0       ; Bank 0
             clrf    PIR1             ;
             clrf    PIR2             ;
             clrf    INTCON           ; alle Quellen und IRQs disablen/rücksetzen
    
    
    
             ; Interrupts enablen bzw. in Gang setzen
             bsf     INTCON,T0IE      ; Timer 0 enable
             bsf     INTCON,PEIE      ; Gruppe der Peripherals 
             bsf     INTCON,GIE       ; globales Enable
    
    
    
    
    
    
    
    
    
    
               ;   !!!!!!!!!  hier dazwischen gehört dei eigener Code  !!!!!!!!!!!!!
    
    
    ; und hier endlich die Hauptprogrammschleife
    LOOOP 
    
             ; auf Event K_PRESS prüfen
             movlw   K_PRESS          ;
             subwf   key_evt,w        ;
             btfsc   STATUS,Z         ;
             incf    tastenzaehler    ;
    
    
             pagesel LOOOP            ;
             goto    LOOOP            ;
    
    
    
    
    
    
    ;**********************************************************************
             ; wartet stur, bis die ISR den Zähler dlycnt bis Null heruntergezählt hat
                                                                        *******  Das ist das Gegenstück zur dlycnf-Manipulation in der ISR ****************
                                                                        *******  auch wieder nur als Anregung zu verstehen                 ****************
    P0_IDLE
             movwf   dlycnt           ; Delayzeit wird im W-Register geliefert
    P0_IDLE_1
             movf    dlycnt,f         ; zero flag generieren
             btfss   STATUS,Z         ; bei Z=1 ausbrechen
             goto    P0_IDLE_1        ;
    
             return                   ;
    ;**********************************************************************
    
    
    
         
    
    
    ;**********************************************************************
             END                      ; directive 'end of program'
    ;**********************************************************************
    Hoffentlich habe ich dich nicht unterschätzt; langweilen will ich dich damit nicht. Ich nehme an, daß du mit MPLAB arbeitest, dann wirst du vieles schon kennen. Wenn du konkrete Fragen hast zu meinen Konstrukten - immer raus damit.
    Das minimale Grundgerüst für Interrupts findest du noch übersichtlicher in der MPLAB-Installation, ich glaube unter dem Namen p16f628atemp.asm. Aber da bist du vermutlich auch gestartet.

    Jetzt bist du dran, das gründlich durchzuarbeiten. Ist doch ne ganze Menge Code übrig geblieben. Allerdings hab ich mit flinker Schere geschnitten, da ist manche Franse dran, die noch weg müsste, vielleicht hab ich auch mal ins gute geschnitten - ich hab nicht getestet, ob's assemblierbar ist!

Berechtigungen

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