Subversion Repositories group.electronics

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
6 pfowler 1
    list        p=16F84A
2
    include    "p16F84a.inc"
3
 
4
;***** CONFIGURATION
5
           __CONFIG _PWRTE_ON & _HS_OSC & _WDT_OFF
6
 
7
; pin assignments
8
    #define SDA         0           ; Pin 0
9
    #define SCL         1           ; Pin 1
10
    #define TRIS_SDA    TRISB,SDA
11
    #define TRIS_SCL    TRISB,SCL
12
    #define I2C_SDA     PORTB,SDA
13
    #define I2C_SCL     PORTB,SCL
14
    #define LED         PORTB,2
15
 
16
    #define I2C_SLAVE1 0x27
17
    #define I2C_SLAVE2 0x26
18
 
19
    CBLOCK     0CH
20
 
21
        _I              ; Loop counter
22
        byte_send       ; Byte to send to i2c
23
        byte_read       ; Byte read from i2c
24
        byte_temp       ; Store byte while address send
25
        i2c_addr        ; Address to read/write
26
        i2c_ret         ; I2C Return Value
27
 
28
        dly_loop1       ; Loops for delays
29
        dly_loop2
30
    ENDC
31
 
32
    ORG 0
33
    goto start           ; jump over to main routine
34
 
35
;***** Initialisation
36
start
37
        ; configure ports
38
        clrw                    ; configure PORTB as all outputs
39
        tris    PORTB
40
        clrf    PORTB
41
        movlw   b'00001011'     ; RA0 - Input - Toggle SW, Mode Select
42
                                ; RA1 - Input - Pulse SW, Record
43
                                ; RA2 - Output - LED, Mode
44
                                ; RA3 - Input - Switch, Reset
45
        tris    PORTA
46
 
47
        clrf    byte_send
48
        clrf    byte_read
49
 
50
;***** Main loop
51
main_loop
52
        bsf     LED
53
        call    ReadByte        ; Read byte from SLAVE2
54
        bcf     LED
55
 
56
        movfw   byte_read       ; Copy the byte read
57
        ;movlw   b'10101010'
58
        movwf   byte_send       ;   into the byte to send
59
 
60
        call    Delay_Short
61
 
62
        bsf     LED
63
        call    SendByte       ; Send byte to SLAVE1
64
        bcf     LED
65
 
66
        call    Delay_Long
67
        goto    main_loop
68
 
69
ReadByte
70
        movlw   I2C_SLAVE2      ; Address of Slave2
71
        movwf   i2c_addr
72
        bsf     STATUS,C        ; Set mode to read
73
        call    I2C_Start       ; Send the address with mode
74
        call    ReadAck
75
        ;movf    i2c_ret
76
        ;btfss   STATUS,Z
77
        ;goto    SendErr
78
        call    I2C_Read        ; Read byte into byte_read
79
        call    ReadAck
80
 
81
        call    I2C_End
82
 
83
        return
84
 
85
 SendByte
86
        movfw   byte_send       ; Save the byte while sending address
87
        movwf   byte_temp
88
        movlw   I2C_SLAVE1      ; 7-bit address of dev
89
        movwf   i2c_addr        ; Set it in the address
90
        bcf     STATUS,C        ; Use Write mode ('0')
91
        call    I2C_Start       ; Start a transmission
92
        call    ReadAck         ; Wait for Ack from slave
93
        ;movf    i2c_ret         ; Check return value
94
        ;btfss   STATUS,Z        ; Goto SendEnd on NACK
95
        ;goto    SendErr
96
        movfw   byte_temp
97
        movwf   byte_send
98
        ;movfw   byte_send       ; Copy byte to write (counter) to w
99
        call    I2C_Write       ; Write the byte to the line
100
        call    ReadAck            ; Should read byte from bus here
101
                                ;  checking that its a Nack
102
 
103
        call    I2C_End         ; End the packet
104
 
105
        return
106
 
107
SendErr
108
        call    I2C_End
109
 
110
        return
111
 
112
 
113
I2C_Start
114
        rlf     i2c_addr,f      ; Attach mode (STATUS,C) to 1st bit
115
        call    Start           ; Start the Trans
116
        movfw   i2c_addr
117
        movwf   byte_send       ; Send the complete address
118
        call    I2C_Write       ; Write byte to port
119
        return
120
 
121
I2C_End
122
        call    Stop
123
        return
124
 
125
I2C_Write
126
        ;movwf   byte_send
127
        movlw   .8              ; 8 bits to send
128
        movwf    _I
129
_WriteBit
130
        rlf     byte_send,f        ; Move highest bit to C
131
        btfss   STATUS,C        ; If 'C' is clear
132
        call    SDA_Low         ;   -> Set data low
133
        btfsc   STATUS,C        ; If 'C' is set
134
        call    SDA_High        ;   -> Set data high
135
 
136
        call    SCL_Pulse
137
 
138
        decfsz  _I,f        ; Decrement counter, if not clear
139
        goto    _WriteBit         ;   -> Send next bit
140
        call    SDA_Low         ; Set low to allow slave to write
141
        return
142
 
143
I2C_Read
144
        movlw   .8              ; 8 bits to read
145
        movwf    _I
146
        clrf    byte_read       ; Clear the read byte
147
        bcf     STATUS,C
148
        call    SDA_High        ; Set high so slave can write
149
_ReadBit
150
        call    SCL_High       ; Pull Clock high, bit should arrive
151
        ;btfss   I2C_SDA        ; If sda is clear
152
        bcf     STATUS,C         ;   -> Set status 0
153
        btfsc   I2C_SDA        ; If sda is set
154
        bsf     STATUS,C
155
        call    SCL_Low         ; Send the clock low
156
 
157
        rlf     byte_read,f        ; Move highest bit to C
158
 
159
        decfsz  _I,f        ; Decrement counter, if not clear
160
        goto    _ReadBit         ;   -> Send next bit
161
        ;call    SDA_Low         ; Set low to allow slave to write
162
        return
163
 
164
Nack                            ; Clock a high SDA
165
        call    SDA_High
166
        call    SCL_Pulse
167
        return
168
 
169
Ack                            ; Clock a high SDA
170
        call    SDA_Low
171
        call    SCL_Pulse
172
        return
173
 
174
ReadAck
175
        call    SDA_High        ; SDA high to allow slave to write
176
        call    SCL_High
177
        clrf    i2c_ret
178
        btfsc   I2C_SDA
179
        bsf     i2c_ret,0
180
        call    SCL_Low
181
        return
182
 
183
Start
184
        call    SDA_High
185
        call    SCL_High
186
        call    SDA_Low
187
        call    SCL_Low
188
        return
189
 
190
Stop                            ; Bring SDA high while Clock high
191
        call    SCL_Low
192
        call    SDA_Low
193
        call    SCL_High
194
        call    SDA_High
195
        return
196
 
197
SCL_Pulse
198
        call  SCL_High
199
        call  SCL_Low
200
        return
201
 
202
SDA_High
203
        bsf     STATUS,RP0      ; Bank 1
204
        bsf     TRIS_SDA        ; Make SDA pin input
205
        bcf     STATUS,RP0      ; Back to bank 0
206
        call    Delay_Short
207
        return
208
 
209
SDA_Low
210
        bcf     I2C_SDA
211
        bsf     STATUS,RP0
212
        bcf     TRIS_SDA        ; Make SDA pin output
213
        bcf     STATUS,RP0
214
        call    Delay_Short
215
        return
216
 
217
SCL_High
218
        bsf     STATUS,RP0      ; Bank 1
219
        bsf     TRIS_SCL        ; Make SDA pin input
220
        bcf     STATUS,RP0      ; Back to bank 0
221
        call    Delay_Short
222
        return
223
 
224
SCL_Low
225
        bcf     I2C_SCL
226
        bsf     STATUS,RP0
227
        bcf     TRIS_SCL        ; Make SDA pin output
228
        bcf     STATUS,RP0
229
        call    Delay_Short
230
        return
231
 
232
Delay_Short                 ; 25us delay
233
        movlw   .5
234
        movwf   dly_loop2
235
Delay_Short_1
236
        nop
237
        decfsz  dly_loop2,f
238
        goto    Delay_Short_1
239
        return
240
 
241
Delay_Long
242
        movlw   .250        ; 250ms delay
243
        movwf   dly_loop1
244
Outer
245
        movlw   .110        ; Close to 1ms when set to .110
246
        movwf   dly_loop2
247
Inner
248
        nop
249
        nop
250
        nop
251
        nop
252
        nop
253
        nop
254
        decfsz  dly_loop2,f
255
        goto    Inner
256
        decfsz  dly_loop1,f
257
        goto    Outer
258
        return
259
 
260
END
261