www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik PIC 12F683: PWM erzeugen


Autor: Mark J. (mebuster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Tag zusammen,

ich habe das Problem, dass ins PR2-Register und ins CCPR1L-Register 
keine Werte reingeschrieben werden können (mit Simulator von MPLAB 
kontrolliert). Der Controller übernimmt die Default-Werte und gibt das 
PWM-Signal an GPIO2 auf 100%aus, was natürlich nicht erwünscht ist.


Hier ist der Code:
list    p=12F683
#include "P12F683.INC"
  
;  config word
__CONFIG  _CP_OFF & _WDT_OFF & _BOD_ON & _PWRTE_ON & _INTRC_OSC_CLKOUT & _MCLRE_ON & _CPD_OFF

ERRORLEVEL      -302

org    0x000  ; Startadresse des PICs 
    goto  INIT

;**************************************************************************
; configure interrupts
;**************************************************************************
org    0x004
CLRF  PIR1

retfie

;**************************************************************************
; PIC configuration
;**************************************************************************

INIT
; reset selects 4 MHz default
BSF     STATUS,RP0      ; Bank1
BSF     OSCCON, SCS     ; intosc is used
CLRF  OPTION_REG
BSF  OPTION_REG,INTEDG  ; interrupt on rising edge
BCF     STATUS,RP0      ; Bank0

; PWM vorbereiten
; 4MHz-Takt -> 1 MHz-Zyklustakt
; Vorteiler 1:1 und Timer2 einschalten
CLRF    T2CON           ; Vorteiler 1:1
BSF     T2CON,TMR2ON    ; Timer2 ein: B'00000010'

; GP2/CCP1 auf Ausgang stellen
BSF     STATUS,RP0      ; Bank1
CLRF  TRISIO      ; alles Ausgänge
BCF     STATUS,RP0      ; Bank 0

; PWM MODE mit CCP1 initialisieren
CLRF    CCP1CON         ; CCP1-Modus aus
BSF     CCP1CON,CCP1M3  ; CCP1-Modus PWM-Mode, active high
BSF     CCP1CON,CCP1M2  ;
    
BSF    INTCON,GIE    ; enable global interrupt

BSF    STATUS,RP0
BSF    PIE1,CCP1IE
BSF    PIE1,TMR2IE
BCF    STATUS,RP0


; Frequenz auf 32 kHz einstellen
; BCF     STATUS,RP0      ; Bank0
MOVLW  d'124'      ; 2.5 kHz  new
MOVWF   PR2  

movlw  d'62'      ; new
movfw  CCPR1L


; IO-Pins vorbereiten
CLRF    GPIO            ; Init GPIO
MOVLW   0x07            ; Set GP<2:0> to
MOVWF   CMCON0          ; digital I/O
BSF     STATUS,RP0      ; Bank1
CLRF    ANSEL           ; digital I/O
BCF     STATUS,RP0      ; Bank 0


;**************************************************************************
; main programme
;**************************************************************************
MAIN
BTFSC  PIR1,1
CALL 0x004  
; rufe Interruptroutine auf, wenn Flag bei Timerüberlauf gesetzt wird
goto MAIN

end

Hat hierbei jemand einen Tipp für mich, wie der Controller die 
übergebenen Werte annimmt?

Gruß, Mark

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

das Register PR2 befindet sich in Bank1. Ich habe das in deinem Code mal 
geändert. Prüfe auch die anderen Register nochmal, ich habe jetzt nicht 
Alles durchgesehen.
; Frequenz auf 32 kHz einstellen
BSF     STATUS,RP0      ; Bank1    <--- !
MOVLW  d'124'      ; 2.5 kHz  new
MOVWF   PR2  
BCF     STATUS,RP0      ; Bank0    <--- !

Autor: Hermann U. (Firma: !www.pcb-devboards.de) (gera82)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
HI.
Was möchtest du genau tun?
Das kann nicht sauber funktionieren:
MAIN
BTFSC  PIR1,1
CALL 0x004  
; rufe Interruptroutine auf, wenn Flag bei Timerüberlauf gesetzt wird
goto MAIN

das kann auch nicht gehen:
;**************************************************************************
; configure interrupts
;**************************************************************************
org    0x004
CLRF  PIR1

retfie

ändere so:
        org  4 

       bsc     INTCON,GIE

       MOVWF   W_TEMP
       SWAPF   STATUS,W
       CLRF    STATUS
       MOVWF   STATUS_TEMP
       MOVF    PCLATH, W
       MOVWF   PCLATH_TEMP
       CLRF    PCLATH


 // hier kannst du interrupt auswerten, z.b. BTFSC  PIR1,1


         
        MOVF    PCLATH_TEMP, W
        MOVWF   PCLATH
        SWAPF   STATUS_TEMP,W
        MOVWF   STATUS
        SWAPF   W_TEMP,F
        SWAPF   W_TEMP,W
                
        bsf     INTCON,GIE
     retfie

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gera82:
>Das kann nicht sauber funktionieren:

Da hast du absolut recht, das habe ich mir vorhin gar nicht angeschaut.

Dein Beispiel ist noch nicht 100pro richtig:
org  4 

       bsc     INTCON,GIE    ;wird vom PIC in HW erledigt, Zeile sollte
                             ;ganz entfernt werden
                             ;außerdem: Tippfehler, Befehl schreibt sich: bcf

       MOVWF   W_TEMP
       SWAPF   STATUS,W
       CLRF    STATUS
       MOVWF   STATUS_TEMP
       MOVF    PCLATH, W
       MOVWF   PCLATH_TEMP
       CLRF    PCLATH


 // hier kannst du interrupt auswerten, z.b. BTFSC  PIR1,1


         
        MOVF    PCLATH_TEMP, W
        MOVWF   PCLATH
        SWAPF   STATUS_TEMP,W
        MOVWF   STATUS
        SWAPF   W_TEMP,F
        SWAPF   W_TEMP,W
                
        bsf     INTCON,GIE   ;erledigt der PIC in HW, Zeile auch raus
     retfie


Grüße,
Edson

Autor: Mark J. (mebuster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnellen Antworten. Das fehlerhafte Register habe ich 
korrigiert. CCPR1L übernimmt im Simulator noch nicht den vorgegebenen 
Wert. Es steht auf dem Default-Wert 0x00. Ist da ein Denkfehler von 
meiner Seite? Es werden doch beide Register benötigt.

PR2 für den maximalen Zählerwert.
CCPR1L für den Verhältniswert.

Allgemein soll ein 50%-Verhältnis als Signal an den Ausgang gelegt 
werden.
Bei der Interruptroutine habe ich zunächst einfach schauen wollen, ob er 
da überhaupt hineinspringt und dabei das Flag / die Flags gelöscht.

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>CCPR1L übernimmt im Simulator noch nicht den vorgegebenen
>Wert.

Hast du berücksichtigt, dass dieses Register wiederum in Bank0 
anzusprechen ist?

Autor: Mark J. (mebuster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das hatte ich berücksichtigt.

Die Passage mit den angesprochenen Registern sieht nun wie folgt aus:
movlw  d'62'      ; new
movfw  CCPR1L

BSF     STATUS,RP0      ; Bank1
MOVLW  d'124'      ; 2.5 kHz  new
MOVWF   PR2  
BCF    STATUS,RP0    ; Bank0

Auf dem Oszilloskop gibt er mir ein dauerhaftes high aus.

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe hier mal die Anleitung aus dem Datenblatt mit ein paar 
Anmerkungen versehen:
11.3.7 SETUP FOR PWM OPERATION

The following steps should be taken when configuring
the CCP module for PWM operation:

1. Disable the PWM pin (CCP1) output drivers by
   setting the associated TRIS bit.

   ---> das machst du nicht, in deinem Code wird TRISIO zu Beginn gelöscht

2. Set the PWM period by loading the PR2 register.

3. Configure the CCP module for the PWM mode
   by loading the CCP1CON register with the
   appropriate values.

4. Set the PWM duty cycle by loading the CCPR1L
   register and DC1B bits of the CCP1CON register.

   ---> die Reihenfolge der letzten 3 Punkte stimmt in deinem Code nicht

5. Configure and start Timer2:
   • Clear the TMR2IF interrupt flag bit of the
     PIR1 register.
   • Set the Timer2 prescale value by loading the
     T2CKPS bits of the T2CON register.
   • Enable Timer2 by setting the TMR2ON bit of
     the T2CON register.

   ---> beachte, dass die Interrupt-Flags vor dem 'enable' gelöscht werden

6. Enable PWM output after a new PWM cycle has
   started:
   • Wait until Timer2 overflows (TMR2IF bit of
     the PIR1 register is set).
   • Enable the CCP1 pin output driver by
     clearing the associated TRIS bit.

   ---> Punkt6 wird in deinem Code gar nicht berücksichtigt

Autor: Mark J. (mebuster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Meister Eder schrieb:
> 1. Disable the PWM pin (CCP1) output drivers by
>    setting the associated TRIS bit.
> 
>    ---> das machst du nicht, in deinem Code wird TRISIO zu Beginn
> gelöscht

Heißt das, dass der Pin als Eingang definiert wird?

Dem Rest widme ich mich gegen Abend.

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Heißt das, dass der Pin als Eingang definiert wird?

Ja, bis zum zweiten Punkt unter 6), ab da ist es dann der PWM-Ausgang. 
Dadurch wird verhindert, dass der Ausgangstreiber während der 
Initialisierung den Pin beeinflusst.

Autor: Mark J. (mebuster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit den PWM-Anforderungen komme ich nun zum nachstehenden Code. Die 
Interruptroutine ist einfach gehalten. Die Abfrage des gesetzten Flags 
in der Main-Routine wird jedesmal abgefangen, sollte somit 
funktionieren.
Das Problem besteht immer noch: CCPR1L nimmt nicht den zugewiesenen Wert 
an. Woran könnte es liegen?
;**************************************************************************
; configure interrupts
;**************************************************************************
    org    0x004

    MOVWF   W_TEMP
    SWAPF   STATUS,W
    CLRF    STATUS
    MOVWF   STATUS_TEMP
    MOVF    PCLATH, W
    MOVWF   PCLATH_TEMP
    CLRF    PCLATH
    
;     // hier kannst du interrupt auswerten, z.b. BTFSC  PIR1,1

    BTFSC  PIR1,1
    CLRF  PIR1
           
    MOVF    PCLATH_TEMP, W
    MOVWF   PCLATH
    SWAPF   STATUS_TEMP,W
    MOVWF   STATUS
    SWAPF   W_TEMP,F
    SWAPF   W_TEMP,W
                    
    CLRF  TMR2
    retfie

;**************************************************************************
; PIC configuration
;**************************************************************************

INIT
; reset selects 4 MHz default
        BSF     STATUS,RP0      ; Bank1
        BSF     OSCCON, SCS     ; intosc is used
  CLRF  OPTION_REG
        BSF  OPTION_REG,INTEDG  ; interrupt on rising edge
  BCF     STATUS,RP0      ; Bank0

; GP2/CCP1 auf Eingang stellen
        BSF     STATUS,RP0      ; Bank1
  BSF  TRISIO,GP2
        BCF     STATUS,RP0      ; Bank0    

; PR2 festlegen
        BSF     STATUS,RP0      ; Bank1
  MOVLW  d'124'    ; 
  MOVWF   PR2  
  BCF  STATUS,RP0  ; Bank0

; PWM MODE mit CCP1 initialisieren
        CLRF    CCP1CON         ; CCP1-Modus aus
        BSF     CCP1CON,CCP1M3  ; CCP1-Modus PWM-Mode, active high
        BSF     CCP1CON,CCP1M2  ;

  BCF  CCP1CON,DC1B1
  BCF  CCP1CON,DC1B0
           
; Verhältnis einstellen
  movlw  d'62'      ; new
  movfw  CCPR1L

; PWM vorbereiten
; 4MHz-Takt -> 1 MHz-Zyklustakt
; Vorteiler 1:1 und Timer2 einschalten
  CLRF  PIR1
        CLRF    T2CON           ; Vorteiler 1:1
        BSF     T2CON,TMR2ON    ; Timer2 ein: B'00000010'

  CLRF  INTCON    
  BSF  INTCON,GIE    ; enable global interrupt

  BSF  STATUS,RP0    ; Bank1
  CLRF  PIE1
  BSF  PIE1,CCP1IE
  BSF  PIE1,TMR2IE
  BCF  STATUS,RP0    ; Bank0

; IO-Pins vorbereiten
        CLRF    GPIO            ; Init GPIO
        MOVLW   0x07            ; Set GP<2:0> to
        MOVWF   CMCON0          ; digital I/O
        BSF     STATUS,RP0      ; Bank1
        CLRF    ANSEL           ; digital I/O
        BCF     STATUS,RP0      ; Bank 0


; wait until timer2 overflows
TMR2OF
  BTFSS  PIR1,1
  GOTO  TMR2OF
  CLRF  PIR1

; PWM auf Ausgang nach Timer2-Durchlauf    
  BSF  STATUS,RP0    ; Bank1
  BSF  TRISIO,2
  BCF  STATUS,RP0    ; Bank0

;**************************************************************************
; main programme
;**************************************************************************
MAIN
BTFSC  PIR1,1
CALL 0x004  
; rufe Interruptroutine auf, wenn Flag bei Timerüberlauf gesetzt wird
goto MAIN

end

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>; Verhältnis einstellen
>  movlw  d'62'      ; new
>  movfw  CCPR1L

  movwf  CCPR1L


>BTFSC  PIR1,1
>CALL 0x004
>; rufe Interruptroutine auf, wenn Flag bei Timerüberlauf gesetzt wird

Was soll denn der Quatsch mit dem Call 0x004?
Das macht der PIC von alleine! Also weg damit.

Autor: Mark J. (mebuster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, in der Simulation hat der uC den Interrupt nicht ausgelöst. 
Deshalb hatte ich es im Code stehen lassen. Verschwindet natürlich 
jetzt.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du PEIE in INTCON auch noch setzt könnte
das sicher hilfreich sein.

Autor: Meister Eder (edson)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

um einen Pin als Ausgang zu benutzen, muss das entsprechende TRIS Bit 
logisch 0 sein.
; PWM auf Ausgang nach Timer2-Durchlauf    
  BSF  STATUS,RP0    ; Bank1
;  BSF  TRISIO,2   ;Pin ist Eingang
  BCF  TRISIO,2    ;Pin ist Ausgang
  BCF  STATUS,RP0    ; Bank0

Autor: Mark J. (mebuster)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das stimmt. Aber nun sind alle Fehler ausgemerzt und PWM funktioniert.
Vielen Dank an Holger, Meister Eder und Hermann, die mir helfen konnten.

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
Ich hoffe ich hab das richtige Forum erwischt.

Und zwar versuchen wir hier auch vergeblichst mit einem PIC12F683 ein 
PWM zu erzeugen.

Wir sind so zu sagen richtige Anfänger aber es ist ja noch nie ein Profi 
vom Himmel gefallen :)

So haben wir uns mal am Anfang ein Source Code aus dem Internet 
angeschaut und versucht in zu verwenden ( Wird weiter unten gezeigt ).
Unser einzigstes Problem ( so glauben wir ) liegt am definieren von GPIO 
zu PORTA und das definieren von TRISIO zu TRISA.

Entschuldigung wenn wir komplett daneben liegen.

Wir benutzen das 8-Pin MPBLAB ICD 2 Header wenn ihr damit was anfangen 
könnt!

Hier ein Bild:

Vorne: http://www.microchipdirect.com/images/devtools/ac162050.jpg

Von Hinten habe ich leider kein Orginales Bild gefunden.
Aber hinten ist nur der 8-Pin Sockel drauf.

Bild von dem Sockel:

http://rocky.digikey.com/weblib/On-Shore%20Technol...

Hier nun der Source Code:
; Listing der Version für 16F684

;**************************************************************
;*
;* Pinbelegung
;*      ----------------------------------                683 / 684
;*      GPIO:   0 < Taster up                           Pin 7 / 13
;*              1 < Taster down                         Pin 6 / 12
;*              2 > PWM-Ausgang (32 kHz) (12F683)       Pin 5
;*              3 < Reset (MCLR)                        Pin 4
;*              4 < Encoder B                           Pin 3
;*              5 < Encoder A                           Pin 2
;*
;*      PORTC:  5 > PWM-Ausgang (32 kHz) (16F684)               Pin 5
;*
;**************************************************************
;
; sprut (zero) Bredendiek 11/2008
;
; PWM-Poti
;
; 12F683 erzeugt mit einer PWM eine Gleichspannung
; gesteuert wird das durch:
;       2 Taster in 16 Stufen (4 Bit)
;       Rotary-Encoder in 32 Stufen (5 Bit)
;
; 12F683 erzeugt an GP2 ein 32 kHz-PWM-Signal
; PS=1; PR2=0x1F; resolution 5-Bit (32 Stufen)
;
;
; Prozessortakt:  4 MHz intern, Zyklustakt 1 MHz
;
; Test mit 16F684
;
;**************************************************************
; Includedatei einbinden

       list p=12f683
       #include <P12f683.INC>
;      list p=16f684
;      #include <P16f684.INC>

        ERRORLEVEL      -302            ;SUPPRESS BANK SELECTION MESSAGES

; kein Power on Timer, kein Watchdog, int-Oscillator, kein Brown out
        __CONFIG        _MCLRE_ON & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BOD_OFF


;**************************************************************
; Variablen
loops2          EQU     0x20            ; fuer waitms
dc              EQU     0x21            ; Taktverhaeltnis als 5-Bit Wert fuer CCPR1L
flags           EQU     0x22
dcold           EQU     0x23            ; alter dutycycle
neu             EQU     0x24            ; neue Encoder-Stellung
alt             EQU     0x25            ; alte Encoder-Stellung
temp            EQU     0x26            ; fuer Encoder
t1count         EQU     0x27

W_TEMP          EQU     0xF0
STATUS_TEMP     EQU     0xF1


; Definitionen
#define KeyUp           GPIO,0
#define KeyDown         GPIO,1
#define UpKeyFlag       flags,0
#define DownKeyFlag     flags,1

#define encoder         GPIO

; fuer 16F684
#define GPIO            PORTA
#define TRISIO          TRISA

;**************************************************************
;voreingestellte Default-Werte im EEPROM
        org     H'2100'         ; EEPROM
        de      0x0F            ; Adr 0 = 0x0F



;**************************************************************
        org     0               ; Anfang des Flash
        GOTO    init

        org     0x04            ; Int
Int
        MOVWF   W_TEMP          ; Copy W to TEMP register
        SWAPF   STATUS, W       ; Swap status to be saved into W
        CLRF    STATUS          ; bank 0, regardless of current bank, Clears IRP,RP1,RP0
        MOVWF   STATUS_TEMP     ; Save status to bank zero STATUS_TEMP register
       
        ; Timer1 loest mit 2 Hz Int aus
        BTFSS   PIR1, TMR1IF    ; ist es Timer1?
        GOTO    IntEnd          ; nein
        DECFSZ  t1count, f      ; Zeit rum?
        GOTO    IntT1End        ; nein
        MOVLW   D'10'
        MOVWF   t1count         ; 5 Sekunden einstellen
        MOVFW   dc
        xorwf   dcold, w        ; ist neu = alt?
        bz      IntT1End        ; ja: nichts tun
        ; neuen Wert im EEPROM speichern
        MOVFW   dc
        MOVWF   dcold
        CALL    EEWrite
IntT1End
        BCF     PIR1, TMR1IF    ; Flag loeschen

IntEnd
        SWAPF   STATUS_TEMP,W   ; Swap STATUS_TEMP register into W
                                ; (sets bank to original state)
        MOVWF   STATUS          ; Move W into Status register
        SWAPF   W_TEMP,F        ; Swap W_TEMP
        SWAPF   W_TEMP,W        ; Swap W_TEMP into W
        RETFIE


;**************************************************************
; Anfangsinitialisierung
init

; internen Takt 4MHz
        ; reset selects 4 MHz default
        BSF     STATUS,RP0      ; Bank1
        BSF     OSCCON, SCS     ; intosc is used
        BCF     STATUS,RP0      ; Bank0
        CLRF    flags


; PWM vorbereiten
; 4MHz-Takt -> 1 MHz-Zyklustakt
; Vorteiler 1:1 und Timer2 einschalten
        CLRF    T2CON           ; Vorteiler 1:1
        BSF     T2CON,TMR2ON    ; Timer2 ein

; Frequenz auf 32 kHz einstellen
        BSF     STATUS,RP0      ; Bank1
        MOVLW   0x1E            ;
        MOVWF   PR2             ; 32 kHz
        BCF     STATUS,RP0      ; Bank0

; Tastverhältnis auf alten Wert einstellen
        CLRW                    ; Adresse fuer EEPROM = 0
        CALL    EERead          ; alten Potiwert aus EEPROM lesen
        MOVWF   dc
        MOVWF   dcold
        MOVWF   CCPR1L          ; PWM auf alten Wert einstellen

; GP2/CCP1 auf Ausgang stellen
        BSF     STATUS,RP0      ; Bank1
        BCF     TRISIO, 2       ; GP2: output=0 12F683
        BCF     TRISC, 5        ; outout 16F684
        BCF     STATUS,RP0      ; Bank 0

; PWM MODE mit CCP1 initialisieren
        CLRF    CCP1CON         ; CCP1-Modus aus
        BSF     CCP1CON,CCP1M3  ; CCP1-Modus PWM-Mode, active high
        BSF     CCP1CON,CCP1M2  ;


; IO-Pins vorbereiten
        CLRF    GPIO            ; Init GPIO
        MOVLW   0x07            ; Set GP<2:0> to
        MOVWF   CMCON0          ; digital I/O
        BSF     STATUS,RP0      ; Bank1
        CLRF    ANSEL           ; digital I/O
        MOVLW   0x33            ; pull-up fuer GP0,1,4,5
        MOVWF   WPU
        BCF     OPTION_REG, 7   ; pull-up master
        BCF     STATUS,RP0      ; Bank 0


; Start-Encoderstand merken
        MOVFW   encoder         ; Port lesen
        MOVWF   alt             ; aktuelle encoder-Stellung nach alt
        MOVLW   B'00110000'     ; Schablone für die beiden Bits
        ANDWF   alt, f          ; nur die 2 Bits stehen lassen


; Timer 1 zum EEPROM-schreiben , testet alle 2 Sekunden auf Aenderung
; 1 MHz / 8 / 65536 = 1,9 Hz
        MOVLW   D'10'
        MOVWF   t1count         ; 5 Sekunden einstellen
        CLRF    TMR1L
        CLRF    TMR1H
        MOVLW   B'00110001'     ; Timer1 on, Vorteiler 8:1, interner Takt
        MOVWF   T1CON
        BSF     STATUS,RP0      ; Bank1
        CLRF    PIE1
        BSF     PIE1, TMR1IE    ; Int on
        BCF     STATUS,RP0      ; Bank0
        CLRF    INTCON
        BSF     INTCON, PEIE
        BSF     INTCON, GIE


;**********************************************************
; Hauptprogrammschleife
Main


; Tasten abfrage
UpKeyTest
        BTFSC   KeyUp
        GOTO    DownKeyTest
        CALL    wait1ms
        BTFSC   KeyUp
        GOTO    DownKeyTest
        INCF    dc,f
        INCF    dc,f
        BSF     UpKeyFlag
DownKeyTest
        BTFSC   KeyDown
        GOTO    Encoder
        CALL    wait1ms
        BTFSC   KeyDown
        GOTO    Encoder
        DECF    dc,f
        DECF    dc,f
        BSF     DownKeyFlag


; Encoder abfragen
Encoder
;       Schritt A       B
;               GP4     GP5
;       0       -       -
;       1       H       -
;       2       H       H
;       3       -       H
;       0       -       -
;       1       H       -
;       2       H       H
;       3       -       H

;       clrf    RotorFlags
        MOVFW   encoder                 ; Port lesen
        MOVWF   neu                     ; aktuelle encoder-Stellung nach new
        MOVLW   B'00110000'             ; Schablone für die beiden Bits
        ANDWF   neu, f                  ; nur die 2 Bits stehen lassen
        MOVFW   neu                     ; wurde der encoder bewegt?
        MOVWF   temp
        MOVFW   alt
        XORWF   temp, w                 ; ist neu = alt?
        BZ      Limits                  ; 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, 5
        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
        BTFSS   alt, 4
        GOTO    rechts
        BTFSS   alt, 5
        GOTO    links
rechts
        INCF    dc,f                    ; rechts:  increment counter
        GOTO    weiter
links
        DECF    dc,f                    ; links:  decrement counter
weiter
        MOVFW   neu
        MOVWF   alt                     ; neu für nächsten Vergleich als alt speichern


; pruefen ob dc zwischen 0 und 1F liegt
Limits
        BTFSC   dc, 7           ; negativ?
        CLRF    dc              ; dc = 0
        MOVLW   B'11100000'
        ANDWF   dc, w           ; > 0x1F ?
        BTFSC   STATUS, Z
        GOTO    LimitsEnd
        MOVLW   0x1F
        MOVWF   dc
LimitsEnd


; Wert an PWM übergeben
        MOVFW   dc
        MOVWF   CCPR1L 


; warten auf freie Tasten
Free
        CALL    wait1ms         ; unterdruecken von Tasterprellen
FreeUp
        BTFSS   UpKeyFlag
        GOTO    FreeDown
FreeUpL
        BTFSS   KeyUp  
        GOTO    FreeUpL
        CALL    wait1ms         ; unterdruecken von Tasterprellen
FreeUpL1
        BTFSS   KeyUp  
        GOTO    FreeUpL1
        BCF     UpKeyFlag

FreeDown
        BTFSS   DownKeyFlag
        GOTO    FreeEnd
FreeDownL
        BTFSS   KeyDown
        GOTO    FreeDownL
        CALL    wait1ms         ; unterdruecken von Tasterprellen
FreeDownL1
        BTFSS   KeyDown
        GOTO    FreeDownL1
        BCF     DownKeyFlag
FreeEnd


        GOTO    Main


;**************************************************************
; Warteschleife 1 ms für einen 4-MHz-PIC-Takt
wait1ms
        MOVLW   .110           ; Zeitkonstante für 1ms
        MOVWF   loops2
Wai2    NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        DECFSZ  loops2, F      ; 1 ms vorbei?
        GOTO    Wai2           ; nein, noch nicht
        RETURN


;**************************************************************
;  EEPROM-Routine für 12F683
;**************************************************************
; 12F683 hat 256 EEPROM-Zellen
; 1 000 000 Schreibzyklen sind garantiert       = 6 Tage lang mit 2 Hz Tasten druecken
;                                               = 60 Tage lang alle 5 Sekunden

; lesen der Zelle, deren Adresse in W steht, nach W
EERead
        BSF    STATUS, RP0     ; EEADR liegt in der Bank 1
        MOVWF  EEADR           ; schreibe die Adresse in EEADR
        BSF    EECON1, RD      ; EEPROM Leseprozeß starten
        MOVF   EEDAT, W        ; Die Daten der EEPROM Zelle nach W kopieren
        BCF    STATUS, RP0     ; Bank 0
        RETURN


; beschreiben des EEPROM; Adresse ist 0; Wert in w
EEWrite
        BSF     STATUS, RP0     ; der Bank 1
        CLRF    EEADR           ; Die Zelle 0x00 soll beschrieben werden
        MOVWF   EEDATA          ; w wollen wir schreiben
        BSF     EECON1, WREN    ; nun ist Schreiben erlaubt
; folgende Zeilen sind nicht noetig, wenn aus Int gerufen
;EEW_GIE
;       BCF     INTCON, GIE     ; verbieten aller Interrupts
;       BTFSC   INTCON,GIE      ; See AN576
;       GOTO    EEW_GIE
        ; Die folgenden 5 Zeilen müssen genau so im Code stehen!!!
        MOVLW   0x55            ;
        MOVWF   EECON2          ; schreibe 55h nach EECON2
        MOVLW   0xAA            ;
        MOVWF   EECON2          ; schreibe AAh nach EECON2
        BSF     EECON1, WR      ; starte den Schreibzyklus
;       BSF     INTCON, GIE     ; Interrupts wieder erlauben , falls noetig
        BCF     STATUS, RP0     ; Bank 0
        RETURN

;**************************************************************



        end

;**************************************************************

Hilfe wäre echt nett :)

mfg Dennis

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.