PIC-Lernbeispiel: Rotary-Encoder auswerten: Teil 2


zurück zu Lernbeispiele , PIC-Prozessoren , Elektronik , Homepage



Rotary-Encoder, Teil 2

Wir haben ja schon  ausprobiert, wie man einen Rotary-Encoder mit einem PIC einsetzen kann. Die bisherige Lösung ist aber weder flexibel noch optimal. Ich möchte deshalb das Rotary-Encoder-Beispiel etwas optimieren, um die Vorteile eine Microcontrollers etwas besser herauszustellen.

Uralt-PICs (wie der 16F84) waren auf externe Bauelemente zur Takterzeugung angewiesen. Modernere PICs haben einen integrierten Taktgenerator, der für viele Anwendungen ausreicht. Der 16F628 besitzt einen internen 4-MHz-Oszillator. Den möchte ich verwenden, um den externen Resonator einzusparen.

Die Ausgabe eines vom Encoder gesteuerten Zählerstandes am PortB mag nicht für alle Anwendungen geeignet sein. Alternativ könnte man immer genau eine von 8 LEDs aufleuchten lassen, und durch Drehen des Encoders die leuchtende LED nach links oder rechts "verschieben". Wir können mit einem PIC beides realisieren. Man muss dem PIC aber mitteilen, welche der beiden Anzeigevarianten man gern hätte. Dies teilt man dem PIC mit Hilfe eines zusätzlichen Input-Pins mit. Ich verwende dafür das Pin RA2. Ist es mit Vdd verbunden, dann erfolgt Ausgabe des 8-Bit-Zählwertes am PortB wie bisher auch. Wird aber das Pin RA2 mit Vss verbunden, dann wird immer genau eine LED leuchten, die durch Drehen des Encoders ausgewählt werden kann.

Vielleicht will man es aber lieber so haben, dass alle LEDs leuchten, bis auf eine? Das wäre dann also eine inverse Anzeige am PortB. Auch hier sehe ich beide Möglichkeiten vor, und schalte mit dem Pin RA3 um. Liegt Pin RA3 auf Vss, dann erfolgt die Anzeige wie bisher auch. Liegt RA3 aber auf Vdd, dann erfolgt die Anzeige invers.

Einige Encoder rasten mechanisch nur in jeder zweiten Drehstellung. Das hat zur Folge, dass meine bisherige Schaltung zwischen zwei Raststellung immer den Zählstand immer um 2 erhöht oder verringert. Die "leuchtende LED" würde z.B. immer gleich um 2 Positionen verschoben werden. Um auch solche Encoder an der selben Schaltung betreiben zu können, müsste die Software angepasst werden. Ich mach die Software einfach flexibel. Sie kann beide Encoder-Arten korrekt bedienen. Man muss ihr nur mit dem Pin RA4 mitteilen, was für ein Encoder angeschlossen ist. Ein Vdd-Pegel an RA4 bedeutet, das ein normaler Encoder verwendet wird. Dagegen bedeutet Vss-Pegel an RA4, das ein Encoder eingesetzt wird, der nur jeweils in der zweiten Stellung einrastet.
(Hinweis: bei RA2=High und RA4=Low erfolgt die Anzeige des Zählerstandes nur 7-bittig anstatt mit 8 Bits. Die LED an RB7 bleibt dann unbenutzt.)

Pin
Vss-Pegel (Low)
Vdd-Pegel (High)
RA2
Anzeige: 1 von 8 LEDs
Anzeige: 8-Bit-Zählerstand
RA3
normale Ausgabe
inverse Ausgabe
RA4
doppelschrittiger Encoder
normaler Encoder



Schaltung
Das ist nun die modifizierte Schaltung der flexiblen Schaltung. Der externe Resonator ist entfallen, und auch auf einen Resttaster habe ich verzichtet.

Die Betriebsart wird nun durch Drahtbrücken oder Jumper an den Pins RA2 bis RA4 ausgewählt.

Die Schaltung ist nun flexibler und einfacher.

Für den Aufbau eignet sich eine 18-Pin-Testplatine oder eine 18-Pin-Minitestplatine mit angesteckter LED-Platine.

clicken zum Vergrößern


Programmablauf


Programmlisting

        list p=16f628
;**************************************************************
;*      Pinbelegung
;*      ----------------------------------      
;*      PORTA:  0 < rotary encoder - B Pin4
;*              1 < rotary encoder - A Pin5
;*              2 < H=zaehlen      L=schieben
;*              3 < H=invers       L=normal
;*              4 < H=einschrittig L=zweischrittig
;*              5 -
;*              6 -
;*              7 -
;*
;*      PORTB:  0 > LED
;*              1 > LED
;*              2 > LED
;*              3 > LED
;*              4 > LED
;*              5 > LED
;*              6 > LED
;*              7 > LED
;*      
;**************************************************************
;
;sprut (zero) Bredendiek 01/2003 .. 12/2008
;
; Rotary-Encoder mit LED Zeile
;
; Prozessor 16F628
;
; Prozessor-Takt 4 MHz intern
;
; Rotary Encoder am PortA 0 & 1
; LED-Zeile am PortB
;
;**************************************************************
; Includedatei für den 16F628 einbinden

        #include <P16f628.INC>

        ERRORLEVEL      -302            ; SUPPRESS BANK SELECTION MESSAGES


; Configuration festlegen:
; Power on Timer, kein Watchdog, interner 4-MHz-Oscillator, kein Brown out, kein LV-programming
        __CONFIG        _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BODEN_OFF & _LVP_OFF

; Constanten festlegen
#define encoder PORTA
#define LED     PORTB

; Variable festlegen
temp    equ     0x20                    ; Arbeitsregister
counter equ     0x21                    ; Zählstand
alt     equ     0x22                    ; alte Rotor-Position
neu     equ     0x23                    ; aktuelle Rotorposition
puffer  equ     0x24                    ; Arbeitsregister

;**************************************************************
; Programmanfang

        org     0
        goto    init


;**************************************************************
; Tabelle zur Wandlung von Binär in 1-aus-8-Code
; look up table
lut
        addwf PCL, f
        retlw B'00000001' ; 0
        retlw B'00000010' ; 1
        retlw B'00000100' ; 2
        retlw B'00001000' ; 3
        retlw B'00010000' ; 4
        retlw B'00100000' ; 5
        retlw B'01000000' ; 6
        retlw B'10000000' ; 7

;**************************************************************
; Initialisierung *********************************************

init
        bsf     STATUS, RP0             ; Bank 1
        clrf    OPTION_REG
        movlw   B'00000000'             ; PortB alle outputs
        movwf   TRISB
        bcf     STATUS, RP0             ; Bank 0
        clrf    PORTB                   ; LEDs aus
        clrf    INTCON                  ; Interupt disable


; 16F628 alle Comparatoreingänge auf Digital umschalten
        BSF     CMCON, CM0
        BSF     CMCON, CM1
        BSF     CMCON, CM2

        clrf    counter
        movfw   encoder
        movwf   alt                     ; aktuelle encoder-Stellung lesen
        movlw   B'00000011'
        andwf   alt, f                  ; nur 2 LSB stehen lassen

;Hauptprogrammschleife
loop
        call    read_encoder            ; Rotary Encoder abfragen
        movfw   counter                 ; das Zaehlergebnis nach w

        btfsc   PORTA, 4                ; ein- oder zwei-schrittig?
        goto    einschritt              ; springen zu einschrittig
        ; Division des Zaehlerstandes durch 2
        movwf   puffer
        bcf     STATUS, C
        rrf     puffer, w               
einschritt

        btfsc   PORTA, 2                ; zaehlen oder schieben?
        goto    binaer                  ; springen zur Anzeige des 8-Bit-Zaehlergebnisses
        ; Anzeige einer von 8 LEDs
        andlw   B'00000111'             ; auf 0..7 begrenzen
        call    lut                     ; led-position holen
binaer

        btfss   PORTA, 3                ; normal oder invers?
        goto    normal                  ; springen mormalen Anzeige
        ; invertieren der Anzeige
        movwf   puffer
        comf    puffer, w               
normal
        movwf   LED                     ; Zählerstand anzeigen
        goto    loop


;**************************************************************
; Test des Encoders auf Verdrehung ****************************

read_encoder
        movfw   encoder
        movwf   neu                     ; aktuelle encoder-Stellung nach new
        movlw   B'00000011'     
        andwf   neu, f                  ; nur 2 LSB stehen lassen
        movfw   neu                     ; wurde der encoder bewegt?
        movwf   temp
        movfw   alt
        xorwf   temp, w                 ; ist neu = alt?
        bz      ende                    ; ja: nicht verdreht, also nichts tun
                                        ; nein: encoder verdreht, aber in welche Richtung?
                                        ; drehen wir mal Bit0 des alten werts zum Vergleich
                                        ;  nach links
        bcf     alt, 1
        clrc                            ; Carry-Flag löschen
        rlf     alt, f                  ; alten Encoder-Stand um 1 Stelle nach links drehen
        movfw   neu
        xorwf   alt, f                  ; falls xorf >1 ergibt, dann war es eine Rechtsdrehung
        bz      links                   ; links:  decrement counter
        decf    alt, f
        bz      links                   ; links:  decrement counter
rechts
        incf    counter, f              ; rechts:  increment counter
        goto    weiter
links
        decf    counter, f              ; links:  decrement counter
weiter
        movfw   neu
        movwf   alt                     ; neu für nächsten Vergleich als alt speichern
ende
        return

        end


zurück zu Lernbeispiele , PIC-Prozessoren , Elektronik , Homepage
Autor: sprut
erstellt: 02.12.2008
letzte Änderung: 04.12.2008