Subversion Repositories group.electronics

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 - 1
list        p=16F88
2
#include <p16f88.inc> ; Change to device that you are using.
3
	__CONFIG	_CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_ON & _HS_OSC
4
	ERRORLEVEL -302
5
;---------------------------------------------------------------------
6
;Constant Definitions
7
;---------------------------------------------------------------------
8
#define NODE_ADDR 0x4e ; I2C address of this node
9
; Change this value to address that
10
; you wish to use.
11
;---------------------------------------------------------------------
12
; Buffer Length Definition
13
;---------------------------------------------------------------------
14
#define RX_BUF_LEN 8 ; Length of receive buffer
15
;---------------------------------------------------------------------
16
; Variable declarations
17
;---------------------------------------------------------------------
18
    udata_shr
19
    WREGsave    res 1
20
 
21
    udata
22
    STATUSsave  res 1
23
    FSRsave     res 1
24
    PCLATHsave  res 1
25
    Index       res 1           ; Index to receive buffer
26
    Temp        res 1           ;
27
    RXBuffer    res RX_BUF_LEN  ; Holds rec'd bytes from master
28
; device.
29
;---------------------------------------------------------------------
30
; Vectors
31
;---------------------------------------------------------------------
32
STARTUP code 0x00
33
    nop
34
    goto    Startup ;
35
    nop             ; 0x0002
36
    nop             ; 0x0003
37
    goto    ISR     ; 0x0004
38
PROG code
39
;---------------------------------------------------------------------
40
; Macros
41
;---------------------------------------------------------------------
42
memset macro Buf_addr,Value,Length
43
    movlw   Length      ; This macro loads a range of data memory
44
    movwf   Temp        ; with a specified value. The starting
45
    movlw   Buf_addr    ; address and number of bytes are also
46
    movwf   FSR         ; specified.
47
SetNext movlw Value
48
    movwf   INDF
49
    incf    FSR,F
50
    decfsz  Temp,F
51
    goto    SetNext
52
    endm
53
LFSR macro Address,Offset   ; This macro loads the correct value
54
    movlw   Address         ; into the FSR given an initial data
55
    movwf   FSR             ; memory address and offset value.
56
    movf    Offset,W
57
    addwf   FSR,F
58
    endm
59
;---------------------------------------------------------------------
60
; Main Code
61
;---------------------------------------------------------------------
62
Startup
63
    bcf     STATUS,RP1
64
    bsf     STATUS,RP0
65
    call    Setup
66
    banksel WREGsave
67
Main clrwdt ; Clear the watchdog timer.
68
    btfsc   RXBuffer,7
69
    bsf     PORTB,2
70
    btfss   RXBuffer,7
71
    bcf     PORTB,2
72
    goto    Main ; Loop forever.
73
;---------------------------------------------------------------------
74
; Interrupt Code
75
;---------------------------------------------------------------------
76
ISR
77
    movwf   WREGsave    ; Save WREG
78
    movf    STATUS,W    ; Get STATUS register
79
    banksel STATUSsave  ; Switch banks, if needed.
80
    movwf   STATUSsave  ; Save the STATUS register
81
    movf    PCLATH,W    ;
82
    movwf   PCLATHsave  ; Save PCLATH
83
    movf    FSR,W       ;
84
    movwf   FSRsave     ; Save FSR
85
    banksel PIR1
86
    btfss   PIR1,SSPIF  ; Is this a SSP interrupt?
87
    goto    $           ; No, just trap here.
88
    bcf     PIR1,SSPIF
89
    call    SSP_Handler ; Yes, service SSP interrupt.
90
    banksel FSRsave
91
    movf    FSRsave,W   ;
92
    movwf   FSR         ; Restore FSR
93
    movf    PCLATHsave,W;
94
    movwf   PCLATH      ; Restore PCLATH
95
    movf    STATUSsave,W;
96
    movwf   STATUS      ; Restore STATUS
97
    swapf   WREGsave,F  ;
98
    swapf   WREGsave,W  ; Restore WREG
99
    retfie              ; Return from interrupt.
100
;---------------------------------------------------------------------
101
Setup
102
;
103
; Initializes program variables and peripheral registers.
104
;---------------------------------------------------------------------
105
    banksel PCON
106
    bsf     PCON,NOT_POR
107
    bsf     PCON,NOT_BOR
108
    banksel ANSEL
109
    movlw   0x00
110
    movwf   ANSEL
111
    banksel Index       ; Clear various program variables
112
    clrf    Index
113
    clrf    PORTB
114
    clrf    PIR1
115
    banksel TRISB
116
    ;clrf    TRISB
117
    bsf     TRISB,4
118
    bsf     TRISB,6
119
    bsf     TRISB,1
120
    bcf     TRISB,2 
121
    movlw   0x36        ; Setup SSP module for 7-bit
122
    banksel SSPCON
123
    movwf   SSPCON      ; address, slave mode
124
    movlw   NODE_ADDR
125
    banksel SSPADD
126
    movwf   SSPADD
127
    clrf    SSPSTAT
128
    banksel PIE1        ; Enable interrupts
129
    bsf     PIE1,SSPIE
130
    bsf     INTCON,PEIE ; Enable all peripheral interrupts
131
    bsf     INTCON,GIE  ; Enable global interrupts
132
    bcf     STATUS,RP0
133
    return
134
;---------------------------------------------------------------------
135
SSP_Handler
136
 
137
;---------------------------------------------------------------------
138
; The I2C code below checks for 5 states:
139
;---------------------------------------------------------------------
140
; State 1: I2C write operation, last byte was an address byte.
141
; SSPSTAT bits: S = 1, D_A = 0, R_W = 0, BF = 1
142
;
143
; State 2: I2C write operation, last byte was a data byte.
144
; SSPSTAT bits: S = 1, D_A = 1, R_W = 0, BF = 1
145
;
146
; State 3: I2C read operation, last byte was an address byte.
147
; SSPSTAT bits: S = 1, D_A = 0, R_W = 1 (see Appendix C for more information)
148
;
149
; State 4: I2C read operation, last byte was a data byte.
150
; SSPSTAT bits: S = 1, D_A = 1, R_W = 1, BF = 0
151
;
152
; State 5: Slave I2C logic reset by NACK from master.
153
; SSPSTAT bits: S = 1, D_A = 1, BF = 0 (see Appendix C for more information)
154
;
155
; For convenience, WriteI2C and ReadI2C functions have been used.
156
;----------------------------------------------------------------------
157
    banksel SSPSTAT
158
    movf    SSPSTAT,W   ; Get the value of SSPSTAT
159
    andlw   b'00101101' ; Mask out unimportant bits in SSPSTAT.
160
    banksel Temp        ; Put masked value in Temp
161
    movwf   Temp        ; for comparision checking.
162
State1:                 ; Write operation, last byte was an   
163
    movlw   b'00001001' ; address, buffer is full.
164
    xorwf   Temp,W      ;
165
    btfss   STATUS,Z    ; Are we in State1?
166
    goto    State2      ; No, check for next state.....
167
    memset RXBuffer,0,RX_BUF_LEN ; Clear the receive buffer.
168
    clrf    Index       ; Clear the buffer index.
169
    banksel SSPBUF      ; Do a dummy read of the SSPBUF.
170
    movf    SSPBUF,W
171
    return
172
State2:                 ; Write operation, last byte was data,
173
    movlw   b'00101001' ; buffer is full.
174
    xorwf   Temp,W
175
    btfss   STATUS,Z    ; Are we in State2?
176
    goto    State3      ; No, check for next state.....
177
    LFSR RXBuffer,Index ; Point to the buffer.
178
    banksel SSPBUF      ; Get the byte from the SSP.
179
    movf    SSPBUF,W
180
    movwf   INDF        ; Put it in the buffer.
181
    incf    Index,F     ; Increment the buffer pointer.
182
    movf    Index,W     ; Get the current buffer index.
183
    sublw   RX_BUF_LEN  ; Subtract the buffer length.
184
    btfsc   STATUS,Z    ; Has the index exceeded the buffer length?
185
    clrf    Index       ; Yes, clear the buffer index.
186
    return
187
State3:                 ; Read operation, last byte was an address,
188
    movf    Temp,W ;
189
    andlw   b'00101100' ; Mask BF bit in SSPSTAT
190
    xorlw   b'00001100'
191
    btfss   STATUS,Z    ; Are we in State3?
192
    goto    State4      ; No, check for next state.....
193
    clrf    Index       ; Clear the buffer index.
194
    LFSR RXBuffer,Index ; Point to the buffer
195
    movf    INDF,W      ; Get the byte from buffer.
196
    call    WriteI2C    ; Write the byte to SSPBUF
197
    incf    Index,F     ; Increment the buffer index.
198
    return
199
State4:                 ; Read operation, last byte was data,
200
    banksel SSPCON      ; buffer is empty.
201
    btfsc   SSPCON, CKP
202
    goto    State5
203
 
204
    movlw   b'00101100'
205
    xorwf   Temp,W
206
    btfss   STATUS,Z    ; Are we in State4?
207
    goto    State5      ; No, check for next state....
208
    movf    Index,W     ; Get the current buffer index.
209
    sublw   RX_BUF_LEN  ; Subtract the buffer length.
210
    btfsc   STATUS,Z    ; Has the index exceeded the buffer length?
211
    clrf    Index       ; Yes, clear the buffer index.
212
    LFSR RXBuffer,Index ; Point to the buffer
213
    movf    INDF,W      ; Get the byte
214
    call    WriteI2C    ; Write to SSPBUF
215
    incf    Index,F     ; Increment the buffer index.
216
    return
217
 
218
State5:
219
    movf    Temp,W      ; NACK received when sending data to the master
220
    andlw   b'00101000' ; Mask RW bit in SSPSTAT
221
    xorlw   b'00101000' ;
222
    btfss   STATUS,Z    ;
223
    goto    I2CErr  ;
224
    return              ; If we aren’t in State5, then something is
225
                        ; wrong.
226
I2CErr nop
227
    banksel PORTB       ; Something went wrong! Set LED
228
    bsf     PORTB,2     ; and loop forever. WDT will reset
229
    goto    $           ; device, if enabled.
230
    return
231
;---------------------------------------------------------------------
232
; WriteI2C
233
;---------------------------------------------------------------------
234
WriteI2C
235
    banksel SSPSTAT
236
    btfsc   SSPSTAT,BF  ; Is the buffer full?
237
    goto    WriteI2C    ; Yes, keep waiting.
238
    banksel SSPCON      ; No, continue.
239
DoI2CWrite
240
    bcf     SSPCON,WCOL ; Clear the WCOL flag.
241
    movwf   SSPBUF      ; Write the byte in WREG
242
    btfsc   SSPCON,WCOL ; Was there a write collision?
243
    goto    DoI2CWrite
244
    bsf     SSPCON,CKP  ; Release the clock.
245
    return
246
 
247
end