PDA

View Full Version : I2C Master/Slave 16F88/16F767 working code



DanPBP
- 30th January 2007, 08:04
Hi Guys,

After a few days of trying, I got this code to work. One 16F88 as master, and two 16F767 as slaves, just to test that the address is working fine. I only test to send one byte. I will have to test to read one, but wanted to share the code anyway:



'--- MASTER BEGINS ----------------------------------------------------------------------------

@ device pic16f88, intrc_osc_noclkout ; system clock options
@ device pic16f88, wdt_on ; watchdog timer
@ device pic16f88, pwrt_on ; power-on timer
@ device pic16f88, mclr_off ; master clear options (internal)
@ device pic16f88, protect_off ; code protect off

'---
DEFINE OSC 8

DEFINE I2C_HOLD 1
DEFINE I2C_SLOW 1

osccon = %01111000 '8mhz

'---
cmcon = 7
ansel = 0

'---

scl VAR PORTB.4 ' i2c clock input
sda VAR PORTB.1 ' i2c data input

'---

main:
High PORTA.6
Pause 500

Low PORTA.6
Pause 500

' First 16f767 - address 6

I2CWrite sda, scl, $06, [15], bogus
Pause 100

I2CWrite sda, scl, $06, [30], bogus
Pause 100

' Second 16f767 - address 8

I2CWrite sda, scl, $08, [45], bogus
Pause 100

I2CWrite sda, scl, $08, [60], bogus
Pause 100

GoTo main

'---

bogus:
GoTo main

'---

End

'--- MASTER ENDS ----------------------------------------------------------------------------




'--- FIRST SLAVE STARTS ----------------------------------------------------------------------------

@ DEVICE PIC16F767, INTRC_OSC_NOCLKOUT ; System Clock Options
@ DEVICE PIC16F767, WDT_ON ; Watchdog Timer
@ DEVICE PIC16F767, PWRT_ON ; Power-On Timer
@ DEVICE PIC16F767, MCLR_OFF ; Master Clear Options (Internal)
@ DEVICE PIC16F767, PROTECT_OFF ; Code Protect Off

'---

DEFINE OSC 8
OSCCON = %01110000

'---

CMCON = 7 ' Comparators Off
ADCON0 = 0 ' A/D Modules Off
ADCON1 = %11111111 ' All Digital Pins
TRISA = %00000000

'---

DEFINE I2C_HOLD 1
DEFINE I2C_SLOW 1

'---

' Alias pins
scl VAR PORTC.3 ' I2C clock input
sda VAR PORTC.4 ' I2C data input

'---

' Define used register flags
SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag
BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full
R_W VAR SSPSTAT.2 ' SSP (I2C) Read/Write
D_A VAR SSPSTAT.5 ' SSP (I2C) Data/Address
CKP VAR SSPCON.4 ' SSP (I2C) SCK Release Control
SSPEN VAR SSPCON.5 ' SSP (I2C) Enable
SSPOV VAR SSPCON.6 ' SSP (I2C) Receive Overflow Indicator
WCOL VAR SSPCON.7 ' SSP (I2C) Write Collision Detect

'---

' Define constants
I2Caddress CON 6 ' Make our address 6

'---

LEDA VAR PORTB.2
LEDB VAR PORTB.6
LEDC VAR PORTB.7

'---

' Allocate RAM

datain VAR BYTE ' Data in
readcnt VAR BYTE
dataout VAR BYTE[8]

'---

' Initialize I2C slave mode
SSPADD = I2Caddress ' Set our address
SSPCON2 = 0 ' General call address disabled
SSPCON = $36 ' Set to I2C slave with 7-bit address

'---

' POST

Low leda
Pause 100

High leda
Pause 100

Low leda
Pause 100

High leda
Pause 100

GoTo main

'---

i2cslave: ' I2C slave subroutine

SSPIF = 0 ' Clear interrupt flag

IF R_W = 1 Then i2crd ' Read data from us

IF BF = 0 Then i2cexit ' Nothing in buffer so exit

IF D_A = 1 Then i2cwr ' Data for us (not address)

IF SSPBUF != I2Caddress Then i2cexit ' Clear the address from the buffer

readcnt = 0 ' Mark as first read

GoTo i2cexit

'---

i2cwr: ' I2C write data to us
datain = SSPBUF ' Put data into array
GoTo i2cexit

'---

i2crd: ' I2C read data from us
IF D_A = 0 Then
readcnt = 0 ' Mark as first read
EndIF

SSPBUF = dataout[readcnt] ' Get data from array
CKP = 1 ' Release SCL line
readcnt = readcnt + 1 ' Move along read count

GoTo i2cexit ' That's it

'---

i2cexit:

Return

'---

main:
IF SSPIF = 1 Then

GoSub i2cslave

Low leda
Pause 10

High leda
Pause 10

IF datain = 15 Then
Low ledb
Pause 10
High ledb
Pause 10
EndIF

IF datain = 30 Then
Low ledc
Pause 10
High ledc
Pause 10
EndIF

EndIF

SSPOV = 0
WCOL = 0

GoTo main

'---

End

'--- FIRST SLAVE ENDS ----------------------------------------------------------------------------




'--- SECOND SLAVE STARTS ----------------------------------------------------------------------------

@ DEVICE PIC16F767, INTRC_OSC_NOCLKOUT ; System Clock Options
@ DEVICE PIC16F767, WDT_ON ; Watchdog Timer
@ DEVICE PIC16F767, PWRT_ON ; Power-On Timer
@ DEVICE PIC16F767, MCLR_OFF ; Master Clear Options (Internal)
@ DEVICE PIC16F767, PROTECT_OFF ; Code Protect Off

'---

DEFINE OSC 8
OSCCON = %01110000

'---

CMCON = 7 ' Comparators Off
ADCON0 = 0 ' A/D Modules Off
ADCON1 = %11111111 ' All Digital Pins
TRISA = %00000000

'---

DEFINE I2C_HOLD 1
DEFINE I2C_SLOW 1

'---

' Alias pins
scl VAR PORTC.3 ' I2C clock input
sda VAR PORTC.4 ' I2C data input

'---

' Define used register flags
SSPIF VAR PIR1.3 ' SSP (I2C) interrupt flag
BF VAR SSPSTAT.0 ' SSP (I2C) Buffer Full
R_W VAR SSPSTAT.2 ' SSP (I2C) Read/Write
D_A VAR SSPSTAT.5 ' SSP (I2C) Data/Address
CKP VAR SSPCON.4 ' SSP (I2C) SCK Release Control
SSPEN VAR SSPCON.5 ' SSP (I2C) Enable
SSPOV VAR SSPCON.6 ' SSP (I2C) Receive Overflow Indicator
WCOL VAR SSPCON.7 ' SSP (I2C) Write Collision Detect

'---

' Define constants
I2Caddress CON 8 ' Make our address 8

'---

LEDA VAR PORTB.2
LEDB VAR PORTB.6
LEDC VAR PORTB.7

'---

' Allocate RAM

datain VAR BYTE ' Data in
readcnt VAR BYTE
dataout VAR BYTE[8]

'---

' Initialize I2C slave mode
SSPADD = I2Caddress ' Set our address
SSPCON2 = 0 ' General call address disabled
SSPCON = $36 ' Set to I2C slave with 7-bit address

'---

' POST

Low leda
Pause 100

High leda
Pause 100

Low leda
Pause 100

High leda
Pause 100

GoTo main

'---

i2cslave: ' I2C slave subroutine

SSPIF = 0 ' Clear interrupt flag

IF R_W = 1 Then i2crd ' Read data from us

IF BF = 0 Then i2cexit ' Nothing in buffer so exit

IF D_A = 1 Then i2cwr ' Data for us (not address)

IF SSPBUF != I2Caddress Then i2cexit ' Clear the address from the buffer

readcnt = 0 ' Mark as first read

GoTo i2cexit

'---

i2cwr: ' I2C write data to us
datain = SSPBUF ' Put data into array
GoTo i2cexit

'---

i2crd: ' I2C read data from us
IF D_A = 0 Then
readcnt = 0 ' Mark as first read
EndIF

SSPBUF = dataout[readcnt] ' Get data from array
CKP = 1 ' Release SCL line
readcnt = readcnt + 1 ' Move along read count

GoTo i2cexit ' That's it

'---

i2cexit:

Return

'---

main:
IF SSPIF = 1 Then

GoSub i2cslave

Low leda
Pause 10

High leda
Pause 10

IF datain = 45 Then
Low ledb
Pause 10
High ledb
Pause 10
EndIF

IF datain = 60 Then
Low ledc
Pause 10
High ledc
Pause 10
EndIF

EndIF

SSPOV = 0
WCOL = 0

GoTo main

'---

End

'--- SECOND SLAVE ENDS ----------------------------------------------------------------------------

Hope it helps.

Regards,
Daniel.

JoeyWallice
- 23rd October 2012, 12:04
Can you put up your wiring diagram please

Thanks

DanPBP
- 23rd October 2012, 23:31
I'm afraid I don't have them anymore, but you only need two wires between each PIC and a pull-up resistor on each...