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