I2CBufferSize con 16 Reg_Pointer Var Byte BANKA ; Address register I2CDATA Var Byte BANKA ; data to read/write I2CAddr Var Byte BANKA ; Device address I2C_Wait var byte BANKA countI2C var byte BANKA I2CWRBuff var byte (I2CBufferSize) BANK2 I2CWRsize Var Byte BANKA I2CRDBuff var byte (I2CBufferSize) BANK2 I2CRDsize Var Byte BANKA I2CErrCode Var Byte BANKA I2CErrCode = 0 asm ; configure SSP for hardware master mode I2C bcf SSPSTAT,SMP ; Slew rate control Enabled (400kHz) bsf SSPCON1,SSPM3 ; I2C master mode in hardware bsf SSPCON1,SSPEN ; enable SSP module movlw 0x0E ; set I2C clock rate to 400kHz ; movlw 0x59 ; set I2C clock rate to 100kHz movwf SSPADD bsf TRISC,3 ; I2C SCL pin is input bsf PORTC,3 ; (will be controlled by SSP) bsf TRISC,4 ; I2C SDA pin is input bsf PORTC,4 ; (will be controlled by SSP) endasm goto Over_I2C_Subs ;************************************************************ ; Main Routines ;----------------------------------------------------------- Write1Byte: I2CErrCode.1 = 0 I2CAddr.0 = 0 ;Set Write Bit Gosub StartI2C ;Send Start, Addr, Wait for Ack if I2CErrCode.1 = 1 then RETURN I2CDATA = I2CWRBuff(0) gosub I2CWRByte ;Send I2CDATA Byte Gosub SendStopBit ;Send Stop Bit Return ;----------------------------------------------------------- WriteXBytes: I2CErrCode.1 = 0 I2CAddr.0 = 0 ;Set Write Bit Gosub StartI2C ;Send Start, Addr, Wait for Ack if I2CErrCode.1 = 1 then RETURN For countI2C = 0 to I2CWRsize-1 I2CDATA = I2CWRBuff(countI2C) gosub I2CWRByte ;Send I2CDATA Byte next countI2C Gosub SendStopBit ;Send Stop Bit Return ;----------------------------------------------------------- Read1Byte: I2CErrCode.1 = 0 I2CAddr.0 = 1 ;Set Read Bit Gosub StartI2C ;Send Start, Addr, Wait for Ack if I2CErrCode.1 = 1 then RETURN gosub I2CRDByte I2CRDBuff(0) = I2CDATA gosub Send_NO_Ack Gosub SendStopBit Return ;----------------------------------------------------------- ReadXBytes: I2CErrCode.1 = 0 I2CAddr.0 = 1 ;Set Read Bit Gosub StartI2C ;Send Start, Addr, Wait for Ack if I2CErrCode.1 = 1 then RETURN for countI2C = 0 to I2CRDsize-2 gosub I2CRDByte gosub Send_Ack I2CRDBuff(countI2C) = I2CDATA next countI2C countI2C = I2CRDsize - 1 gosub I2CRDByte gosub Send_NO_ACK Gosub SendStopBit I2CRDBuff(countI2C) = I2CDATA Return ;************************************************************ ; Process Routines ;----------------------------------------------------------- StartI2C: asm clrf _I2C_Wait bsf SSPCON2,SEN ; Send start bit btfsc SSPCON2,SEN ; Has SEN cleared yet? goto $-2 ; No, loop back to test. Send_RepStart bcf PIR1,SSPIF ; clear interrupt flag movf _I2CAddr,W movwf SSPBUF ; move slave address to SSPBUF btfss PIR1,SSPIF ; has SSP completed sending SLAVE Address? goto $-2 ; no, loop back to test btfss SSPCON2,ACKSTAT ; was ACK received from slave? return ; yes, return to calling routine ;------------------- Repeat 256 times if no ACK infsnz _I2C_Wait, F goto _I2CResError bsf SSPCON2,RSEN ; send repeated start bit btfsc SSPCON2,RSEN ; has repeated start been sent yet? goto $-2 ; no, loop back to test bra Send_RepStart ; send slave address again ;------------------- endasm Return ;----------------------------------------------------------- I2CWRByte: ASM bcf PIR1,SSPIF ; clear interrupt flag movff _I2CDATA,SSPBUF ; move data to SSPBUF btfss PIR1,SSPIF ; has SSP completed sending data? goto $-2 ; no, loop back to test btfsc SSPCON2,ACKSTAT ; has slave sent ACK? goto $-2 ; no, try again ENDASM Return ;----------------------------------------------------------- I2CRDByte: asm bcf PIR1,SSPIF ; clear interrupt flag bsf SSPCON2,RCEN ; enable receive mode btfss PIR1,SSPIF ; has SSP received a data byte? goto $-2 ; no, loop back to test movff SSPBUF,_I2CDATA ; save data to RAM ;bcf SSPCON2,RCEN ; disable receive mode - NOT NEED, AUTO CLRD BY HRDWR endasm Return ;----------------------------------------------------------- SendStopBit asm bsf SSPCON2,PEN ; send stop bit btfsc SSPCON2,PEN ; has stop bit been sent? goto $-2 ; no, loop back to test endasm Return ;----------------------------------------------------------- Send_NO_Ack: asm bsf SSPCON2,ACKDT ; NO_ACK bsf SSPCON2,ACKEN ; send ACKDT bit btfsc SSPCON2,ACKEN ; has ACKDT bit been sent yet? goto $-2 ; no, loop back to test endasm Return ;----------------------------------------------------------- Send_Ack: asm bcf SSPCON2,ACKDT ; ACK bsf SSPCON2,ACKEN ; send ACKDT bit btfsc SSPCON2,ACKEN ; has ACKDT bit been sent yet? goto $-2 ; no, loop back to test endasm Return ;----------------------------------------------------------- I2CResError: I2CErrCode.1 = 1 hserout [13,10,"I2C Error!!!",13,10] Return ;----------------------------------------------------------- Over_I2C_Subs: