Subversion Repositories group.electronics

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4 pfowler 1
;---------------------------------------------------------------------
2
; File: an734_PIC16.asm
3
;
4
; Written By: Stephen Bowling, Microchip Technology
5
;
6
; Version: 1.00
7
;
8
; Assembled using Microchip Assembler
9
;
10
; Functionality:
11
;
12
; This code implements the basic functions for an I2C slave device
13
; using the SSP module. All I2C functions are handled in an ISR.
14
; Bytes written to the slave are stored in a buffer. After a number
15
; of bytes have been written, the master device can then read the
16
; bytes back from the buffer.
17
;
18
; Variables and Constants used in the program:
19
;
20
; The start address for the receive buffer is stored in the variable
21
; 'RXBuffer'. The length of the buffer is denoted by the constant
22
; value 'RX_BUF_LEN'. The current buffer index is stored in the
23
; variable 'Index'.
24
;
25
;--------------------------------------------------------------------
26
;
27
; The following files should be included in the MPLAB project:
28
;
29
; an734_PIC16.asm-- Main source code file
30
;
31
; 16f877a.lkr-- Linker script file
32
; (change this file for the device you are using)
33
;
34
;---------------------------------------------------------------------
35
;---------------------------------------------------------------------
36
; Include Files
37
;---------------------------------------------------------------------
38
list        p=16F88
39
#include <p16f88.inc> ; Change to device that you are using.
40
	__CONFIG	_CONFIG1, _CP_OFF & _CCP1_RB3 & _CCPMX_RB3 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_ON & _HS_OSC
41
	ERRORLEVEL -302
42
;---------------------------------------------------------------------
43
;Constant Definitions
44
;---------------------------------------------------------------------
45
#define NODE_ADDR 0x4e ; I2C address of slave 2
46
 
47
    #define LED0         PORTA,0
48
    #define LED1         PORTA,1
49
    #define LED2         PORTA,2
50
    #define LED3         PORTA,3
51
    #define LED4         PORTA,4
52
    #define LED5         PORTB,2
53
    #define LED6         PORTB,0
54
    #define LED7         PORTB,5
55
; Change this value to address that
56
; you wish to use.
57
;---------------------------------------------------------------------
58
; Buffer Length Definition
59
;---------------------------------------------------------------------
60
#define RX_BUF_LEN 8 ; Length of receive buffer
61
;---------------------------------------------------------------------
62
; Variable declarations
63
;---------------------------------------------------------------------
64
    udata_shr
65
    WREGsave    res 1
66
    RXBuffer    res RX_BUF_LEN
67
 
68
 
69
    udata
70
    STATUSsave  res 1
71
    FSRsave     res 1
72
    PCLATHsave  res 1
73
    Index       res 1           ; Index to receive buffer
74
    Temp        res 1           ;
75
 
76
 
77
; device.
78
;---------------------------------------------------------------------
79
; Vectors
80
;---------------------------------------------------------------------
81
STARTUP code 0x00
82
    nop
83
    goto    Startup ;
84
    nop             ; 0x0002
85
    nop             ; 0x0003
86
    goto    ISR     ; 0x0004
87
PROG code
88
;---------------------------------------------------------------------
89
; Macros
90
;---------------------------------------------------------------------
91
memset macro Buf_addr,Value,Length
92
    movlw   Length      ; This macro loads a range of data memory
93
    movwf   Temp        ; with a specified value. The starting
94
    movlw   Buf_addr    ; address and number of bytes are also
95
    movwf   FSR         ; specified.
96
SetNext movlw Value
97
    movwf   INDF
98
    incf    FSR,F
99
    decfsz  Temp,F
100
    goto    SetNext
101
    endm
102
LFSR macro Address,Offset   ; This macro loads the correct value
103
    movlw   Address         ; into the FSR given an initial data
104
    movwf   FSR             ; memory address and offset value.
105
    movf    Offset,W
106
    addwf   FSR,F
107
    endm
108
;---------------------------------------------------------------------
109
; Main Code
110
;---------------------------------------------------------------------
111
Startup
112
    bcf     STATUS,RP1
113
    bsf     STATUS,RP0
114
    call    Setup
115
    banksel WREGsave
116
    banksel RXBuffer
117
    clrf    RXBuffer
118
        bcf     LED0
119
        bcf     LED1
120
        bcf     LED2
121
        bcf     LED3
122
        bcf     LED4
123
        bcf     LED5
124
        bcf     LED6
125
        bcf     LED7
126
 
127
Main clrwdt ; Clear the watchdog timer.
128
    banksel PORTB
129
    btfsc   RXBuffer,0
130
    bsf     LED0
131
    btfss   RXBuffer,0
132
    bcf     LED0
133
 
134
    btfsc   RXBuffer,1
135
    bsf     LED1
136
    btfss   RXBuffer,1
137
    bcf     LED1
138
 
139
    btfsc   RXBuffer,2
140
    bsf     LED2
141
    btfss   RXBuffer,2
142
    bcf     LED2
143
 
144
    btfsc   RXBuffer,3
145
    bsf     LED3
146
    btfss   RXBuffer,3
147
    bcf     LED3
148
 
149
    btfsc   RXBuffer,4
150
    bsf     LED4
151
    btfss   RXBuffer,4
152
    bcf     LED4
153
 
154
    btfsc   RXBuffer,5
155
    bsf     LED5
156
    btfss   RXBuffer,5
157
    bcf     LED5
158
 
159
    btfsc   RXBuffer,6
160
    bsf     LED6
161
    btfss   RXBuffer,6
162
    bcf     LED6
163
 
164
    btfsc   RXBuffer,7
165
    bsf     LED7
166
    btfss   RXBuffer,7
167
    bcf     LED7
168
 
169
    goto    Main ; Loop forever.
170
;---------------------------------------------------------------------
171
; Interrupt Code
172
;---------------------------------------------------------------------
173
ISR
174
    movwf   WREGsave    ; Save WREG
175
    movf    STATUS,W    ; Get STATUS register
176
    banksel STATUSsave  ; Switch banks, if needed.
177
    movwf   STATUSsave  ; Save the STATUS register
178
    movf    PCLATH,W    ;
179
    movwf   PCLATHsave  ; Save PCLATH
180
    movf    FSR,W       ;
181
    movwf   FSRsave     ; Save FSR
182
    banksel PIR1
183
    btfss   PIR1,SSPIF  ; Is this a SSP interrupt?
184
    goto    $           ; No, just trap here.
185
    bcf     PIR1,SSPIF
186
    call    SSP_Handler ; Yes, service SSP interrupt.
187
    banksel FSRsave
188
    movf    FSRsave,W   ;
189
    movwf   FSR         ; Restore FSR
190
    movf    PCLATHsave,W;
191
    movwf   PCLATH      ; Restore PCLATH
192
    movf    STATUSsave,W;
193
    movwf   STATUS      ; Restore STATUS
194
    swapf   WREGsave,F  ;
195
    swapf   WREGsave,W  ; Restore WREG
196
    retfie              ; Return from interrupt.
197
;---------------------------------------------------------------------
198
Setup
199
;
200
; Initializes program variables and peripheral registers.
201
;---------------------------------------------------------------------
202
    banksel PCON
203
    bsf     PCON,NOT_POR
204
    bsf     PCON,NOT_BOR
205
    banksel ANSEL
206
    movlw   0x00
207
    movwf   ANSEL
208
    banksel Index       ; Clear various program variables
209
    clrf    Index
210
    clrf    PORTB
211
    clrf    PIR1
212
    banksel TRISB
213
    clrf    TRISB
214
    bsf     TRISB,4
215
    bsf     TRISB,1
216
 
217
    banksel TRISA
218
    clrf    TRISA
219
    movlw   0x36        ; Setup SSP module for 7-bit
220
    banksel SSPCON
221
    movwf   SSPCON      ; address, slave mode
222
    movlw   NODE_ADDR
223
    banksel SSPADD
224
    movwf   SSPADD
225
    clrf    SSPSTAT
226
    banksel PIE1        ; Enable interrupts
227
    bsf     PIE1,SSPIE
228
    bsf     INTCON,PEIE ; Enable all peripheral interrupts
229
    bsf     INTCON,GIE  ; Enable global interrupts
230
    bcf     STATUS,RP0
231
    return
232
;---------------------------------------------------------------------
233
SSP_Handler
234
 
235
;---------------------------------------------------------------------
236
; The I2C code below checks for 5 states:
237
;---------------------------------------------------------------------
238
; State 1: I2C write operation, last byte was an address byte.
239
; SSPSTAT bits: S = 1, D_A = 0, R_W = 0, BF = 1
240
;
241
; State 2: I2C write operation, last byte was a data byte.
242
; SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 1
243
;
244
; State 3: I2C read operation, last byte was an address byte.
245
; SSPSTAT bits: S = 1, D_A = 0, R_W = 1 (see Appendix C for more information)
246
;
247
; State 4: I2C read operation, last byte was a data byte.
248
; SSPSTAT bits: S = 1, D_A = 1, R_W = 1, BF = 0
249
;
250
; State 5: Slave I2C logic reset by NACK from master.
251
; SSPSTAT bits: S = 1, D_A = 1, BF = 0 (see Appendix C for more information)
252
;
253
; For convenience, WriteI2C and ReadI2C functions have been used.
254
;----------------------------------------------------------------------
255
    banksel SSPSTAT
256
    movf    SSPSTAT,W   ; Get the value of SSPSTAT
257
    andlw   b'00101101' ; Mask out unimportant bits in SSPSTAT.
258
    banksel Temp        ; Put masked value in Temp
259
    movwf   Temp        ; for comparision checking.
260
State1:                 ; Write operation, last byte was an   
261
    movlw   b'00001001' ; address, buffer is full.
262
    xorwf   Temp,W      ;
263
    btfss   STATUS,Z    ; Are we in State1?
264
    goto    State2      ; No, check for next state.....
265
    memset RXBuffer,0,RX_BUF_LEN ; Clear the receive buffer.
266
    clrf    Index       ; Clear the buffer index.
267
    banksel SSPBUF      ; Do a dummy read of the SSPBUF.
268
    movf    SSPBUF,W
269
    return
270
State2:                 ; Write operation, last byte was data,
271
    movlw   b'00101001' ; buffer is full.
272
    xorwf   Temp,W
273
    btfss   STATUS,Z    ; Are we in State2?
274
    goto    State3      ; No, check for next state.....
275
    LFSR RXBuffer,Index ; Point to the buffer.
276
    banksel SSPBUF      ; Get the byte from the SSP.
277
    movf    SSPBUF,W
278
    movwf   INDF        ; Put it in the buffer.
279
    incf    Index,F     ; Increment the buffer pointer.
280
    movf    Index,W     ; Get the current buffer index.
281
    sublw   RX_BUF_LEN  ; Subtract the buffer length.
282
    btfsc   STATUS,Z    ; Has the index exceeded the buffer length?
283
    clrf    Index       ; Yes, clear the buffer index.
284
    return
285
State3:                 ; Read operation, last byte was an address,
286
    movf    Temp,W ;
287
    andlw   b'00101100' ; Mask BF bit in SSPSTAT
288
    xorlw   b'00001100'
289
    btfss   STATUS,Z    ; Are we in State3?
290
    goto    State4      ; No, check for next state.....
291
    clrf    Index       ; Clear the buffer index.
292
    LFSR RXBuffer,Index ; Point to the buffer
293
    movf    INDF,W      ; Get the byte from buffer.
294
    call    WriteI2C    ; Write the byte to SSPBUF
295
    incf    Index,F     ; Increment the buffer index.
296
    return
297
State4:                 ; Read operation, last byte was data,
298
    banksel SSPCON      ; buffer is empty.
299
    btfsc   SSPCON, CKP
300
    goto    State5
301
 
302
    movlw   b'00101100'
303
    xorwf   Temp,W
304
    btfss   STATUS,Z    ; Are we in State4?
305
    goto    State5      ; No, check for next state....
306
    movf    Index,W     ; Get the current buffer index.
307
    sublw   RX_BUF_LEN  ; Subtract the buffer length.
308
    btfsc   STATUS,Z    ; Has the index exceeded the buffer length?
309
    clrf    Index       ; Yes, clear the buffer index.
310
    LFSR RXBuffer,Index ; Point to the buffer
311
    movf    INDF,W      ; Get the byte
312
    call    WriteI2C    ; Write to SSPBUF
313
    incf    Index,F     ; Increment the buffer index.
314
    return
315
 
316
State5:
317
    movf    Temp,W      ; NACK received when sending data to the master
318
    andlw   b'00101000' ; Mask RW bit in SSPSTAT
319
    xorlw   b'00101000' ;
320
    btfss   STATUS,Z    ;
321
    goto    I2CErr  ;
322
    return              ; If we aren?t in State5, then something is
323
                        ; wrong.
324
I2CErr nop
325
    banksel PORTB       ; Something went wrong! Set LED
326
    bsf     PORTB,2     ; and loop forever. WDT will reset
327
    goto    $           ; device, if enabled.
328
    return
329
;---------------------------------------------------------------------
330
; WriteI2C
331
;---------------------------------------------------------------------
332
WriteI2C
333
    banksel SSPSTAT
334
    btfsc   SSPSTAT,BF  ; Is the buffer full?
335
    goto    WriteI2C    ; Yes, keep waiting.
336
    banksel SSPCON      ; No, continue.
337
DoI2CWrite
338
    bcf     SSPCON,WCOL ; Clear the WCOL flag.
339
    movwf   SSPBUF      ; Write the byte in WREG
340
    btfsc   SSPCON,WCOL ; Was there a write collision?
341
    goto    DoI2CWrite
342
    bsf     SSPCON,CKP  ; Release the clock.
343
    return
344
 
345
end