1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
| 'Als je de timer steeds laat tellen tot zijn maximale waarde,
'is de pwm frequentie veel te laag
'Daarom laat de de timer beginnen vanaf een bepaalde waarde,
'aangezien het een 16 bits timer is
'moeten er 2 prescalers worden weggeschreven
#DEFINE PRESCALER 0xFF
#DEFINE PRESCALER2 0xE9
'De code begint altijd hier
ORG 00h
GOTO INIT
'Iedere keer als er een interrupt komt springt de code naar adres 0x4.
'Dat is een feit, kan je niet instellen oid, dat doet de PIC automagisch
ORG 04h
'aangezien een interrupt op ieder moment in het programma kan komen
'kan het zien dat op dat moment het W register in gebruik is,
'en W wordt in de interruptlus ook gebruikt, als de interrupt dan klaar is
'heeft W een andere waarde en zal de uitkomst van de berekening
'in de onderbroken code dus verkeerd zijn.
'om dat op te lossen worden W, STATUS en PCLATH tijdelijk weggeschreven
MOVWF W_SAVE
MOVF STATUS,W
MOVWF S_SAVE
MOVF PCLATH,W
MOVWF P_SAVE
GOTO INT_HANDLER
'Initializatiefunctie
INIT
'spring naar bank1 om de i/o registers goed te zetten
BSF STATUS,RP0
CLRF TRISA
BCF STATUS,RP0
'Initialiseer nu de timer
TIMER_INIT
'Schrijf de offsets weg
MOVLW PRESCALER
MOVWF TMR1H
MOVLW PRESCALER2
MOVWF TMR1L
'Timer1 heeft ook nog een eigen prescaler die hem langzamer maakt,
'de onderstaande 2 regels zetten die uit
BCF T1CON,T1CKPS0 ;clear prescaler
BCF T1CON,T1CKPS1
'Zet de oscillator modus uit, en set de timer modus.
'Als laatste: zet de timer aan.
BCF T1CON,T1OSCEN ;disable oscilator
BCF T1CON,TMR1CS ;select timer mode
BSF T1CON,TMR1ON ;enable timer 1
'Zet nu de interrupts aan
INTERRUPT_INIT
'Selecteer BANK1, en clear de interrupt registers voor de zekerheid
'Zodoende weet je zeker dat er niet per ongelijk een andere interrupt aanstaat
BSF STATUS,RP0
CLRF PIE1
CLRF INTCON
'Set TMR1IE ( TIMER1 INTERRUPT ENABLE), zodat er een interrupt komt
'Als timer1 een overlfow geeft.
'Zet daarna GIE (General interrupt enable), en PEIE (perhipel interrupt enable) aan
BSF PIE1,TMR1IE ;enable timer interrupt
BSF INTCON,GIE
BSF INTCON,PEIE
BCF STATUS,RP0
'De main lus, hier kan je je normale code infietsen
ENDLESS
NOP
NOP
GOTO ENDLESS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; INTERRUPT CODE
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
'Deze functie wordt aangeroepen als de interrupt klaar is,
'De timer wordt gereset, W, STATUS en PCLATH teruggezet
'En de interrupt wordt verlaten
RET
'Timer1 flag clearen, en de prescaler weer schrijven
BCF PIR1, TMR1IF
MOVLW PRESCALER
MOVWF TMR1H
MOVLW PRESCALER2
MOVWF TMR1L
'Schrijf de registers weer terug, zodat de normale lus verder kan gaan
;Called on normal interrupt return
MOVF P_SAVE,W ;restore context
MOVWF PCLATH
MOVF S_SAVE,W
MOVWF STATUS
SWAPF W_SAVE,F
SWAPF W_SAVE,W
'en RETFIE (Return From Interrupt)
RETFIE ;and return from interrupt
'Deze functie wordt geroepen als er een interrupt is.
INT_HANDLER
'Vooor de zekerheid controleren of het wel écht timer1 is die een interrupt geeft
BTFSC PIR1,TMR1IF
GOTO INT_TIMER
'Zo niet stop ermeer
GOTO RET
'De timer code zelf
INT_TIMER
'Iedere ronde wordt PWMCOUNTER één verlaagd, zodra die nul is,
'Worden alle LED's uitgezet en begint de PWM cyclus opnieuw
DECF PWMCOUNTER ;decrease
BTFSC STATUS,Z
CLRF PORTA
'Als PWMCOUNTER gelijk is aan GREEN, zet dan de groene LED aan
MOVF PWMCOUNTER,W
XORWF GREEN,W
BTFSC STATUS,Z
BSF PORTA,2
'Als PWMCOUNTER gelijk is aan BLUE, zet dan de blauwe LED aan
MOVF PWMCOUNTER,W
XORWF BLUE,W
BTFSC STATUS,Z
BSF PORTA,1
'Als PWMCOUNTER gelijk is aan RED, zet dan de rode LED aan
MOVF PWMCOUNTER,W
XORWF RED,W
BTFSC STATUS,Z
BSF PORTA,3
'En er is weer één stap voltooid (een PWM cyclus bestaat uit 256 stappen)
'Zodoende: hou er mee op
GOTO RET
'Deze END wordt nooit bereikt door de code, maar als je die niet neerzet,
'dan gaat MPLAB raar doen.
END |