The basis of the framework is that the master sends a command byte with bit 7 (go bit) set, followed by any number of data bytes. The interrupt routine on the slave reads and stores the data and command and sets a flag for the main program when a new command has been received.
This allows the main program to act on the data and provide appropriate output in an output buffer. Once the processing is complete the main program clears the go bit in the command byte.
Thus the i2c master can send a command with data and then repeatedly read the command byte to check for the go bit being cleared. In this way it knows that the slave processing is completed and the data is ready for download
The example main slave program is:
Code: Select all
Device = 18F14K22
Clock = 64
Include "utils.bas"
Include "I2CSlave.bas"
Include "usart.bas"
Include "convert.bas"
dim i as byte
SetAllDigital()
SetBaudrate(br19200)
EnableI2C_isr()
While true
if i2cslave.dataavailable then
USART.Write("i2cStatus:", DecToStr(i2cstatus)," buff(0):",dectostr(DataBuffer(0)),13, 10) // decimal number
if i2cstatus=%10000001 then ' process valid command
for i=0 to databufferindex-1
outbuffer(i)=databuffer(i)*2
next
endif
delayms(1000) 'make the master wait a bit to demonstrate polling
i2cstatus=i2cstatus and %01111111 ' clear the go bit
endif
I2CSlave.DataAvailable = False
Wend
Code: Select all
Module I2CSlave
#option ISR_SHADOW = false
' Registers And bits associated with i2c hardware SSP
' SSPSTAT bits
Dim BF As SSPSTAT.0 ' Buffer Full Status flag
Dim UA As SSPSTAT.1 ' Update Address bit
Dim R_W As SSPSTAT.2 ' Read/Write bit information bit
Dim S As SSPSTAT.3 ' Start bit
Dim P As SSPSTAT.4 ' STOPP bit
Dim D_A As SSPSTAT.5 ' Data/NOT_Address bit
Dim CKE As SSPSTAT.6 ' SPI Clock Edge Select
Dim SMP As SSPSTAT.7 ' Sample bit
' SSPCON bits Slave mode 7 bits
Dim SSPM0 As SSPCON1.0 ' SSP mode bits 0
Dim SSPM1 As SSPCON1.1 ' " 1
Dim SSPM2 As SSPCON1.2 ' " 1
Dim SSPM3 As SSPCON1.3 ' " 0
Dim CKP As SSPCON1.4 ' Clock, 1 = Enable clock, 0 = clock stretch
Dim SSPEN As SSPCON1.5 ' SSP Enable Bit
Dim SSPOV As SSPCON1.6 ' Receive overflow indicator Bit. In receive mode, a
' Byte is received While the SSPBUF is holding
' previous Byte. Must be cleared in software.
Dim WCOL As SSPCON1.7 ' Write collision detect Bit. In slave mode, 1 means
' SSBUF written While transmitting previous Word.
' Must be cleared in software.
Dim SSPIF As PIR1.3 ' SSP Interrupt flag Bit
Const SLAVE_ADDR = $22 ' Even number, must match address sent by Master PIC
' To Read from Slave, make address from Master = (address + 1)
Const DataBufferLen = 100 ' RX Buffer size
Public Dim DataBufferIndex,outbufferindex As Byte ' RX Buffer current Index
Public Dim DataBuffer(DataBufferLen) As Byte
Public Dim outBuffer(DataBufferLen) As Byte
Public dim i2cStatus,i2caddress as byte
Dim CASE_SWITCH,CKPbit,SSPCONBITS,scratch As Byte ' States situation to be used by Select function
Public Dim DataAvailable As Boolean
' There can be 5 possible i2c states, SSPSTAT register relevant bits
Interrupt isr_I2C(2)
save (0)
SSPIF = 0
CASE_SWITCH = SSPSTAT And %00101101
SSPCONBITS=SSPCON1
CKPbit=SSPCONBITS and %00010000
state1:
if (CASE_SWITCh XOR %00001001) <> 0 goto state2test
DataAvailable = false
DataBufferIndex = 255
i2cAddress = SSPBUF
goto statedone
state2test:
if (CASE_SWITCh XOR %00101001) <> 0 goto state3test
if databufferindex=255 then
databufferindex=0
i2cstatus=SSPBUF
else
DataBuffer(DataBufferIndex) = SSPBUF
Inc(DataBufferIndex)
endif
goto statedone
state3test:
if ((CASE_SWITCH AND %00101100) XOR %00001100) <> 0 goto state4test
outbufferindex=0
scratch=SSPBUF 'clear the BF flag
SSPBUF = i2cstatus 'send status data byte
goto exitonly
state4test:
if CKPbit<>0 goto state5test
If (CASE_SWITCh XOR %00101100) <> 0 goto exitonly
SSPBUF = outbuffer(outbufferindex) 'send status data byte
inc(outbufferindex)
goto exitonly
state5test:
CASE_SWITCH=CASE_SWITCH AND %00101000 'now mask out RW bit
If (CASE_SWITCh XOR %00101000) <> 0 goto exitonly
Errorstate:
' put error handling here
statedone:
DataAvailable = SSPCONBITS.booleans(4)
exitonly:
restore
CKP=1
End Interrupt
Sub InitI2C()
Input(PORTB.5) ' Set SCL and SDA as inputs
Input(PORTB.7)
'SSPCON1 = $36 ' SSP settings: i2c slave mode, 7-bit address, enable SSP
'SSPCON1 = %00110111 ' SSP settings: i2c slave mode, 7-bit address, enable SSP
SSPCON1 = %00111110 ' i2c Slave, 7 bit Addr, I2C Start/Stop interrupts enabled
SSPADD = SLAVE_ADDR ' Initial slave address setting
SSPCON2.7 = 0 ' disable general call address
SSPSTAT = 0 ' Clear SSP Status reg
PIE1.3 = 1 ' Enable SSP interrupts (SSPIE)
SSPIF = 0 ' Clear SSP Interrupt flag
INTCON.6 = 1 ' Enable perpheral Interrupts
INTCON.7 = 1 ' Enable Global Interrupts
End Sub
Public Sub EnableI2C_isr()
Enable(isr_I2C)
End Sub
Public Sub DisableI2C_isr()
Disable(isr_I2C)
End Sub
InitI2C()
DataAvailable = false
outbufferindex=0
databufferindex=0
Code: Select all
#picaxe28X1
setfreq m4
hi2csetup i2cmaster, $22, i2cfast_4, i2cbyte
do
hi2cout (%10000001,44,46,47,48) 'Command 1 with Go bit set
w7=0
do
inc w7
hi2cin (b0)
loop while b0>127 ' loop while go bit still set
hi2cin (b0,b1,b2,b3,b4)
sertxd (#w7," ",#b0," ",#b1," ",#b2," ",#b3," ",#b4,cr,lf)
loop
Best regards
Peter