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


von Mark J. (mebuster)


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:
1
list    p=12F683
2
#include "P12F683.INC"
3
  
4
;  config word
5
__CONFIG  _CP_OFF & _WDT_OFF & _BOD_ON & _PWRTE_ON & _INTRC_OSC_CLKOUT & _MCLRE_ON & _CPD_OFF
6
7
ERRORLEVEL      -302
8
9
org    0x000  ; Startadresse des PICs 
10
    goto  INIT
11
12
;**************************************************************************
13
; configure interrupts
14
;**************************************************************************
15
org    0x004
16
CLRF  PIR1
17
18
retfie
19
20
;**************************************************************************
21
; PIC configuration
22
;**************************************************************************
23
24
INIT
25
; reset selects 4 MHz default
26
BSF     STATUS,RP0      ; Bank1
27
BSF     OSCCON, SCS     ; intosc is used
28
CLRF  OPTION_REG
29
BSF  OPTION_REG,INTEDG  ; interrupt on rising edge
30
BCF     STATUS,RP0      ; Bank0
31
32
; PWM vorbereiten
33
; 4MHz-Takt -> 1 MHz-Zyklustakt
34
; Vorteiler 1:1 und Timer2 einschalten
35
CLRF    T2CON           ; Vorteiler 1:1
36
BSF     T2CON,TMR2ON    ; Timer2 ein: B'00000010'
37
38
; GP2/CCP1 auf Ausgang stellen
39
BSF     STATUS,RP0      ; Bank1
40
CLRF  TRISIO      ; alles Ausgänge
41
BCF     STATUS,RP0      ; Bank 0
42
43
; PWM MODE mit CCP1 initialisieren
44
CLRF    CCP1CON         ; CCP1-Modus aus
45
BSF     CCP1CON,CCP1M3  ; CCP1-Modus PWM-Mode, active high
46
BSF     CCP1CON,CCP1M2  ;
47
    
48
BSF    INTCON,GIE    ; enable global interrupt
49
50
BSF    STATUS,RP0
51
BSF    PIE1,CCP1IE
52
BSF    PIE1,TMR2IE
53
BCF    STATUS,RP0
54
55
56
; Frequenz auf 32 kHz einstellen
57
; BCF     STATUS,RP0      ; Bank0
58
MOVLW  d'124'      ; 2.5 kHz  new
59
MOVWF   PR2  
60
61
movlw  d'62'      ; new
62
movfw  CCPR1L
63
64
65
; IO-Pins vorbereiten
66
CLRF    GPIO            ; Init GPIO
67
MOVLW   0x07            ; Set GP<2:0> to
68
MOVWF   CMCON0          ; digital I/O
69
BSF     STATUS,RP0      ; Bank1
70
CLRF    ANSEL           ; digital I/O
71
BCF     STATUS,RP0      ; Bank 0
72
73
74
;**************************************************************************
75
; main programme
76
;**************************************************************************
77
MAIN
78
BTFSC  PIR1,1
79
CALL 0x004  
80
; rufe Interruptroutine auf, wenn Flag bei Timerüberlauf gesetzt wird
81
goto MAIN
82
83
end

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

Gruß, Mark

von Meister E. (edson)


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.
1
; Frequenz auf 32 kHz einstellen
2
BSF     STATUS,RP0      ; Bank1    <--- !
3
MOVLW  d'124'      ; 2.5 kHz  new
4
MOVWF   PR2  
5
BCF     STATUS,RP0      ; Bank0    <--- !

von Hermann U. (Firma: www.pcb-devboards.de) (gera82)


Lesenswert?

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

das kann auch nicht gehen:
1
;**************************************************************************
2
; configure interrupts
3
;**************************************************************************
4
org    0x004
5
CLRF  PIR1
6
7
retfie

ändere so:
1
        org  4 
2
3
       bsc     INTCON,GIE
4
5
       MOVWF   W_TEMP
6
       SWAPF   STATUS,W
7
       CLRF    STATUS
8
       MOVWF   STATUS_TEMP
9
       MOVF    PCLATH, W
10
       MOVWF   PCLATH_TEMP
11
       CLRF    PCLATH
12
13
14
 // hier kannst du interrupt auswerten, z.b. BTFSC  PIR1,1
15
16
17
         
18
        MOVF    PCLATH_TEMP, W
19
        MOVWF   PCLATH
20
        SWAPF   STATUS_TEMP,W
21
        MOVWF   STATUS
22
        SWAPF   W_TEMP,F
23
        SWAPF   W_TEMP,W
24
                
25
        bsf     INTCON,GIE
26
     retfie

von Meister E. (edson)


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:
1
org  4 
2
3
       bsc     INTCON,GIE    ;wird vom PIC in HW erledigt, Zeile sollte
4
                             ;ganz entfernt werden
5
                             ;außerdem: Tippfehler, Befehl schreibt sich: bcf
6
7
       MOVWF   W_TEMP
8
       SWAPF   STATUS,W
9
       CLRF    STATUS
10
       MOVWF   STATUS_TEMP
11
       MOVF    PCLATH, W
12
       MOVWF   PCLATH_TEMP
13
       CLRF    PCLATH
14
15
16
 // hier kannst du interrupt auswerten, z.b. BTFSC  PIR1,1
17
18
19
         
20
        MOVF    PCLATH_TEMP, W
21
        MOVWF   PCLATH
22
        SWAPF   STATUS_TEMP,W
23
        MOVWF   STATUS
24
        SWAPF   W_TEMP,F
25
        SWAPF   W_TEMP,W
26
                
27
        bsf     INTCON,GIE   ;erledigt der PIC in HW, Zeile auch raus
28
     retfie

Grüße,
Edson

von Mark J. (mebuster)


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.

von Meister E. (edson)


Lesenswert?

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

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

von Mark J. (mebuster)


Lesenswert?

Das hatte ich berücksichtigt.

Die Passage mit den angesprochenen Registern sieht nun wie folgt aus:
1
movlw  d'62'      ; new
2
movfw  CCPR1L
3
4
BSF     STATUS,RP0      ; Bank1
5
MOVLW  d'124'      ; 2.5 kHz  new
6
MOVWF   PR2  
7
BCF    STATUS,RP0    ; Bank0

Auf dem Oszilloskop gibt er mir ein dauerhaftes high aus.

von Meister E. (edson)


Lesenswert?

Ich habe hier mal die Anleitung aus dem Datenblatt mit ein paar 
Anmerkungen versehen:
1
11.3.7 SETUP FOR PWM OPERATION
2
3
The following steps should be taken when configuring
4
the CCP module for PWM operation:
5
6
1. Disable the PWM pin (CCP1) output drivers by
7
   setting the associated TRIS bit.
8
9
   ---> das machst du nicht, in deinem Code wird TRISIO zu Beginn gelöscht
10
11
2. Set the PWM period by loading the PR2 register.
12
13
3. Configure the CCP module for the PWM mode
14
   by loading the CCP1CON register with the
15
   appropriate values.
16
17
4. Set the PWM duty cycle by loading the CCPR1L
18
   register and DC1B bits of the CCP1CON register.
19
20
   ---> die Reihenfolge der letzten 3 Punkte stimmt in deinem Code nicht
21
22
5. Configure and start Timer2:
23
   • Clear the TMR2IF interrupt flag bit of the
24
     PIR1 register.
25
   • Set the Timer2 prescale value by loading the
26
     T2CKPS bits of the T2CON register.
27
   • Enable Timer2 by setting the TMR2ON bit of
28
     the T2CON register.
29
30
   ---> beachte, dass die Interrupt-Flags vor dem 'enable' gelöscht werden
31
32
6. Enable PWM output after a new PWM cycle has
33
   started:
34
   • Wait until Timer2 overflows (TMR2IF bit of
35
     the PIR1 register is set).
36
   • Enable the CCP1 pin output driver by
37
     clearing the associated TRIS bit.
38
39
   ---> Punkt6 wird in deinem Code gar nicht berücksichtigt

von Mark J. (mebuster)


Lesenswert?

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

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

Dem Rest widme ich mich gegen Abend.

von Meister E. (edson)


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.

von Mark J. (mebuster)


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?
1
;**************************************************************************
2
; configure interrupts
3
;**************************************************************************
4
    org    0x004
5
6
    MOVWF   W_TEMP
7
    SWAPF   STATUS,W
8
    CLRF    STATUS
9
    MOVWF   STATUS_TEMP
10
    MOVF    PCLATH, W
11
    MOVWF   PCLATH_TEMP
12
    CLRF    PCLATH
13
    
14
;     // hier kannst du interrupt auswerten, z.b. BTFSC  PIR1,1
15
16
    BTFSC  PIR1,1
17
    CLRF  PIR1
18
           
19
    MOVF    PCLATH_TEMP, W
20
    MOVWF   PCLATH
21
    SWAPF   STATUS_TEMP,W
22
    MOVWF   STATUS
23
    SWAPF   W_TEMP,F
24
    SWAPF   W_TEMP,W
25
                    
26
    CLRF  TMR2
27
    retfie
28
29
;**************************************************************************
30
; PIC configuration
31
;**************************************************************************
32
33
INIT
34
; reset selects 4 MHz default
35
        BSF     STATUS,RP0      ; Bank1
36
        BSF     OSCCON, SCS     ; intosc is used
37
  CLRF  OPTION_REG
38
        BSF  OPTION_REG,INTEDG  ; interrupt on rising edge
39
  BCF     STATUS,RP0      ; Bank0
40
41
; GP2/CCP1 auf Eingang stellen
42
        BSF     STATUS,RP0      ; Bank1
43
  BSF  TRISIO,GP2
44
        BCF     STATUS,RP0      ; Bank0    
45
46
; PR2 festlegen
47
        BSF     STATUS,RP0      ; Bank1
48
  MOVLW  d'124'    ; 
49
  MOVWF   PR2  
50
  BCF  STATUS,RP0  ; Bank0
51
52
; PWM MODE mit CCP1 initialisieren
53
        CLRF    CCP1CON         ; CCP1-Modus aus
54
        BSF     CCP1CON,CCP1M3  ; CCP1-Modus PWM-Mode, active high
55
        BSF     CCP1CON,CCP1M2  ;
56
57
  BCF  CCP1CON,DC1B1
58
  BCF  CCP1CON,DC1B0
59
           
60
; Verhältnis einstellen
61
  movlw  d'62'      ; new
62
  movfw  CCPR1L
63
64
; PWM vorbereiten
65
; 4MHz-Takt -> 1 MHz-Zyklustakt
66
; Vorteiler 1:1 und Timer2 einschalten
67
  CLRF  PIR1
68
        CLRF    T2CON           ; Vorteiler 1:1
69
        BSF     T2CON,TMR2ON    ; Timer2 ein: B'00000010'
70
71
  CLRF  INTCON    
72
  BSF  INTCON,GIE    ; enable global interrupt
73
74
  BSF  STATUS,RP0    ; Bank1
75
  CLRF  PIE1
76
  BSF  PIE1,CCP1IE
77
  BSF  PIE1,TMR2IE
78
  BCF  STATUS,RP0    ; Bank0
79
80
; IO-Pins vorbereiten
81
        CLRF    GPIO            ; Init GPIO
82
        MOVLW   0x07            ; Set GP<2:0> to
83
        MOVWF   CMCON0          ; digital I/O
84
        BSF     STATUS,RP0      ; Bank1
85
        CLRF    ANSEL           ; digital I/O
86
        BCF     STATUS,RP0      ; Bank 0
87
88
89
; wait until timer2 overflows
90
TMR2OF
91
  BTFSS  PIR1,1
92
  GOTO  TMR2OF
93
  CLRF  PIR1
94
95
; PWM auf Ausgang nach Timer2-Durchlauf    
96
  BSF  STATUS,RP0    ; Bank1
97
  BSF  TRISIO,2
98
  BCF  STATUS,RP0    ; Bank0
99
100
;**************************************************************************
101
; main programme
102
;**************************************************************************
103
MAIN
104
BTFSC  PIR1,1
105
CALL 0x004  
106
; rufe Interruptroutine auf, wenn Flag bei Timerüberlauf gesetzt wird
107
goto MAIN
108
109
end

von holger (Gast)


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.

von Mark J. (mebuster)


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.

von holger (Gast)


Lesenswert?

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

von Meister E. (edson)


Lesenswert?

Hallo,

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

von Mark J. (mebuster)


Lesenswert?

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

von Dennis (Gast)


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%20Technology/Web%20Photo/BU060Z-178-HT.jpg

Hier nun der Source Code:
1
; Listing der Version für 16F684
2
3
;**************************************************************
4
;*
5
;* Pinbelegung
6
;*      ----------------------------------                683 / 684
7
;*      GPIO:   0 < Taster up                           Pin 7 / 13
8
;*              1 < Taster down                         Pin 6 / 12
9
;*              2 > PWM-Ausgang (32 kHz) (12F683)       Pin 5
10
;*              3 < Reset (MCLR)                        Pin 4
11
;*              4 < Encoder B                           Pin 3
12
;*              5 < Encoder A                           Pin 2
13
;*
14
;*      PORTC:  5 > PWM-Ausgang (32 kHz) (16F684)               Pin 5
15
;*
16
;**************************************************************
17
;
18
; sprut (zero) Bredendiek 11/2008
19
;
20
; PWM-Poti
21
;
22
; 12F683 erzeugt mit einer PWM eine Gleichspannung
23
; gesteuert wird das durch:
24
;       2 Taster in 16 Stufen (4 Bit)
25
;       Rotary-Encoder in 32 Stufen (5 Bit)
26
;
27
; 12F683 erzeugt an GP2 ein 32 kHz-PWM-Signal
28
; PS=1; PR2=0x1F; resolution 5-Bit (32 Stufen)
29
;
30
;
31
; Prozessortakt:  4 MHz intern, Zyklustakt 1 MHz
32
;
33
; Test mit 16F684
34
;
35
;**************************************************************
36
; Includedatei einbinden
37
38
       list p=12f683
39
       #include <P12f683.INC>
40
;      list p=16f684
41
;      #include <P16f684.INC>
42
43
        ERRORLEVEL      -302            ;SUPPRESS BANK SELECTION MESSAGES
44
45
; kein Power on Timer, kein Watchdog, int-Oscillator, kein Brown out
46
        __CONFIG        _MCLRE_ON & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BOD_OFF
47
48
49
;**************************************************************
50
; Variablen
51
loops2          EQU     0x20            ; fuer waitms
52
dc              EQU     0x21            ; Taktverhaeltnis als 5-Bit Wert fuer CCPR1L
53
flags           EQU     0x22
54
dcold           EQU     0x23            ; alter dutycycle
55
neu             EQU     0x24            ; neue Encoder-Stellung
56
alt             EQU     0x25            ; alte Encoder-Stellung
57
temp            EQU     0x26            ; fuer Encoder
58
t1count         EQU     0x27
59
60
W_TEMP          EQU     0xF0
61
STATUS_TEMP     EQU     0xF1
62
63
64
; Definitionen
65
#define KeyUp           GPIO,0
66
#define KeyDown         GPIO,1
67
#define UpKeyFlag       flags,0
68
#define DownKeyFlag     flags,1
69
70
#define encoder         GPIO
71
72
; fuer 16F684
73
#define GPIO            PORTA
74
#define TRISIO          TRISA
75
76
;**************************************************************
77
;voreingestellte Default-Werte im EEPROM
78
        org     H'2100'         ; EEPROM
79
        de      0x0F            ; Adr 0 = 0x0F
80
81
82
83
;**************************************************************
84
        org     0               ; Anfang des Flash
85
        GOTO    init
86
87
        org     0x04            ; Int
88
Int
89
        MOVWF   W_TEMP          ; Copy W to TEMP register
90
        SWAPF   STATUS, W       ; Swap status to be saved into W
91
        CLRF    STATUS          ; bank 0, regardless of current bank, Clears IRP,RP1,RP0
92
        MOVWF   STATUS_TEMP     ; Save status to bank zero STATUS_TEMP register
93
       
94
        ; Timer1 loest mit 2 Hz Int aus
95
        BTFSS   PIR1, TMR1IF    ; ist es Timer1?
96
        GOTO    IntEnd          ; nein
97
        DECFSZ  t1count, f      ; Zeit rum?
98
        GOTO    IntT1End        ; nein
99
        MOVLW   D'10'
100
        MOVWF   t1count         ; 5 Sekunden einstellen
101
        MOVFW   dc
102
        xorwf   dcold, w        ; ist neu = alt?
103
        bz      IntT1End        ; ja: nichts tun
104
        ; neuen Wert im EEPROM speichern
105
        MOVFW   dc
106
        MOVWF   dcold
107
        CALL    EEWrite
108
IntT1End
109
        BCF     PIR1, TMR1IF    ; Flag loeschen
110
111
IntEnd
112
        SWAPF   STATUS_TEMP,W   ; Swap STATUS_TEMP register into W
113
                                ; (sets bank to original state)
114
        MOVWF   STATUS          ; Move W into Status register
115
        SWAPF   W_TEMP,F        ; Swap W_TEMP
116
        SWAPF   W_TEMP,W        ; Swap W_TEMP into W
117
        RETFIE
118
119
120
;**************************************************************
121
; Anfangsinitialisierung
122
init
123
124
; internen Takt 4MHz
125
        ; reset selects 4 MHz default
126
        BSF     STATUS,RP0      ; Bank1
127
        BSF     OSCCON, SCS     ; intosc is used
128
        BCF     STATUS,RP0      ; Bank0
129
        CLRF    flags
130
131
132
; PWM vorbereiten
133
; 4MHz-Takt -> 1 MHz-Zyklustakt
134
; Vorteiler 1:1 und Timer2 einschalten
135
        CLRF    T2CON           ; Vorteiler 1:1
136
        BSF     T2CON,TMR2ON    ; Timer2 ein
137
138
; Frequenz auf 32 kHz einstellen
139
        BSF     STATUS,RP0      ; Bank1
140
        MOVLW   0x1E            ;
141
        MOVWF   PR2             ; 32 kHz
142
        BCF     STATUS,RP0      ; Bank0
143
144
; Tastverhältnis auf alten Wert einstellen
145
        CLRW                    ; Adresse fuer EEPROM = 0
146
        CALL    EERead          ; alten Potiwert aus EEPROM lesen
147
        MOVWF   dc
148
        MOVWF   dcold
149
        MOVWF   CCPR1L          ; PWM auf alten Wert einstellen
150
151
; GP2/CCP1 auf Ausgang stellen
152
        BSF     STATUS,RP0      ; Bank1
153
        BCF     TRISIO, 2       ; GP2: output=0 12F683
154
        BCF     TRISC, 5        ; outout 16F684
155
        BCF     STATUS,RP0      ; Bank 0
156
157
; PWM MODE mit CCP1 initialisieren
158
        CLRF    CCP1CON         ; CCP1-Modus aus
159
        BSF     CCP1CON,CCP1M3  ; CCP1-Modus PWM-Mode, active high
160
        BSF     CCP1CON,CCP1M2  ;
161
162
163
; IO-Pins vorbereiten
164
        CLRF    GPIO            ; Init GPIO
165
        MOVLW   0x07            ; Set GP<2:0> to
166
        MOVWF   CMCON0          ; digital I/O
167
        BSF     STATUS,RP0      ; Bank1
168
        CLRF    ANSEL           ; digital I/O
169
        MOVLW   0x33            ; pull-up fuer GP0,1,4,5
170
        MOVWF   WPU
171
        BCF     OPTION_REG, 7   ; pull-up master
172
        BCF     STATUS,RP0      ; Bank 0
173
174
175
; Start-Encoderstand merken
176
        MOVFW   encoder         ; Port lesen
177
        MOVWF   alt             ; aktuelle encoder-Stellung nach alt
178
        MOVLW   B'00110000'     ; Schablone für die beiden Bits
179
        ANDWF   alt, f          ; nur die 2 Bits stehen lassen
180
181
182
; Timer 1 zum EEPROM-schreiben , testet alle 2 Sekunden auf Aenderung
183
; 1 MHz / 8 / 65536 = 1,9 Hz
184
        MOVLW   D'10'
185
        MOVWF   t1count         ; 5 Sekunden einstellen
186
        CLRF    TMR1L
187
        CLRF    TMR1H
188
        MOVLW   B'00110001'     ; Timer1 on, Vorteiler 8:1, interner Takt
189
        MOVWF   T1CON
190
        BSF     STATUS,RP0      ; Bank1
191
        CLRF    PIE1
192
        BSF     PIE1, TMR1IE    ; Int on
193
        BCF     STATUS,RP0      ; Bank0
194
        CLRF    INTCON
195
        BSF     INTCON, PEIE
196
        BSF     INTCON, GIE
197
198
199
;**********************************************************
200
; Hauptprogrammschleife
201
Main
202
203
204
; Tasten abfrage
205
UpKeyTest
206
        BTFSC   KeyUp
207
        GOTO    DownKeyTest
208
        CALL    wait1ms
209
        BTFSC   KeyUp
210
        GOTO    DownKeyTest
211
        INCF    dc,f
212
        INCF    dc,f
213
        BSF     UpKeyFlag
214
DownKeyTest
215
        BTFSC   KeyDown
216
        GOTO    Encoder
217
        CALL    wait1ms
218
        BTFSC   KeyDown
219
        GOTO    Encoder
220
        DECF    dc,f
221
        DECF    dc,f
222
        BSF     DownKeyFlag
223
224
225
; Encoder abfragen
226
Encoder
227
;       Schritt A       B
228
;               GP4     GP5
229
;       0       -       -
230
;       1       H       -
231
;       2       H       H
232
;       3       -       H
233
;       0       -       -
234
;       1       H       -
235
;       2       H       H
236
;       3       -       H
237
238
;       clrf    RotorFlags
239
        MOVFW   encoder                 ; Port lesen
240
        MOVWF   neu                     ; aktuelle encoder-Stellung nach new
241
        MOVLW   B'00110000'             ; Schablone für die beiden Bits
242
        ANDWF   neu, f                  ; nur die 2 Bits stehen lassen
243
        MOVFW   neu                     ; wurde der encoder bewegt?
244
        MOVWF   temp
245
        MOVFW   alt
246
        XORWF   temp, w                 ; ist neu = alt?
247
        BZ      Limits                  ; ja: nicht verdreht, also nichts tun
248
                                        ; nein: encoder verdreht, aber in welche Richtung?
249
                                        ; drehen wir mal Bit0 des alten werts zum Vergleich
250
                                        ;  nach links
251
        BCF     alt, 5
252
        CLRC                            ; Carry-Flag löschen
253
        RLF     alt, f                  ; alten Encoder-Stand um 1 Stelle nach links drehen
254
        MOVFW   neu
255
        XORWF   alt, f                  ; falls xorf >1 ergibt, dann war es eine Rechtsdrehung
256
        BZ      links                   ; links:  decrement counter
257
        BTFSS   alt, 4
258
        GOTO    rechts
259
        BTFSS   alt, 5
260
        GOTO    links
261
rechts
262
        INCF    dc,f                    ; rechts:  increment counter
263
        GOTO    weiter
264
links
265
        DECF    dc,f                    ; links:  decrement counter
266
weiter
267
        MOVFW   neu
268
        MOVWF   alt                     ; neu für nächsten Vergleich als alt speichern
269
270
271
; pruefen ob dc zwischen 0 und 1F liegt
272
Limits
273
        BTFSC   dc, 7           ; negativ?
274
        CLRF    dc              ; dc = 0
275
        MOVLW   B'11100000'
276
        ANDWF   dc, w           ; > 0x1F ?
277
        BTFSC   STATUS, Z
278
        GOTO    LimitsEnd
279
        MOVLW   0x1F
280
        MOVWF   dc
281
LimitsEnd
282
283
284
; Wert an PWM übergeben
285
        MOVFW   dc
286
        MOVWF   CCPR1L 
287
288
289
; warten auf freie Tasten
290
Free
291
        CALL    wait1ms         ; unterdruecken von Tasterprellen
292
FreeUp
293
        BTFSS   UpKeyFlag
294
        GOTO    FreeDown
295
FreeUpL
296
        BTFSS   KeyUp  
297
        GOTO    FreeUpL
298
        CALL    wait1ms         ; unterdruecken von Tasterprellen
299
FreeUpL1
300
        BTFSS   KeyUp  
301
        GOTO    FreeUpL1
302
        BCF     UpKeyFlag
303
304
FreeDown
305
        BTFSS   DownKeyFlag
306
        GOTO    FreeEnd
307
FreeDownL
308
        BTFSS   KeyDown
309
        GOTO    FreeDownL
310
        CALL    wait1ms         ; unterdruecken von Tasterprellen
311
FreeDownL1
312
        BTFSS   KeyDown
313
        GOTO    FreeDownL1
314
        BCF     DownKeyFlag
315
FreeEnd
316
317
318
        GOTO    Main
319
320
321
;**************************************************************
322
; Warteschleife 1 ms für einen 4-MHz-PIC-Takt
323
wait1ms
324
        MOVLW   .110           ; Zeitkonstante für 1ms
325
        MOVWF   loops2
326
Wai2    NOP
327
        NOP
328
        NOP
329
        NOP
330
        NOP
331
        NOP
332
        DECFSZ  loops2, F      ; 1 ms vorbei?
333
        GOTO    Wai2           ; nein, noch nicht
334
        RETURN
335
336
337
;**************************************************************
338
;  EEPROM-Routine für 12F683
339
;**************************************************************
340
; 12F683 hat 256 EEPROM-Zellen
341
; 1 000 000 Schreibzyklen sind garantiert       = 6 Tage lang mit 2 Hz Tasten druecken
342
;                                               = 60 Tage lang alle 5 Sekunden
343
344
; lesen der Zelle, deren Adresse in W steht, nach W
345
EERead
346
        BSF    STATUS, RP0     ; EEADR liegt in der Bank 1
347
        MOVWF  EEADR           ; schreibe die Adresse in EEADR
348
        BSF    EECON1, RD      ; EEPROM Leseprozeß starten
349
        MOVF   EEDAT, W        ; Die Daten der EEPROM Zelle nach W kopieren
350
        BCF    STATUS, RP0     ; Bank 0
351
        RETURN
352
353
354
; beschreiben des EEPROM; Adresse ist 0; Wert in w
355
EEWrite
356
        BSF     STATUS, RP0     ; der Bank 1
357
        CLRF    EEADR           ; Die Zelle 0x00 soll beschrieben werden
358
        MOVWF   EEDATA          ; w wollen wir schreiben
359
        BSF     EECON1, WREN    ; nun ist Schreiben erlaubt
360
; folgende Zeilen sind nicht noetig, wenn aus Int gerufen
361
;EEW_GIE
362
;       BCF     INTCON, GIE     ; verbieten aller Interrupts
363
;       BTFSC   INTCON,GIE      ; See AN576
364
;       GOTO    EEW_GIE
365
        ; Die folgenden 5 Zeilen müssen genau so im Code stehen!!!
366
        MOVLW   0x55            ;
367
        MOVWF   EECON2          ; schreibe 55h nach EECON2
368
        MOVLW   0xAA            ;
369
        MOVWF   EECON2          ; schreibe AAh nach EECON2
370
        BSF     EECON1, WR      ; starte den Schreibzyklus
371
;       BSF     INTCON, GIE     ; Interrupts wieder erlauben , falls noetig
372
        BCF     STATUS, RP0     ; Bank 0
373
        RETURN
374
375
;**************************************************************
376
377
378
379
        end
380
381
;**************************************************************

Hilfe wäre echt nett :)

mfg Dennis

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.