;********************************************************************* ; * ; Tutorial 20 I2C Master/Slave Communication * ; * ;********************************************************************* ;* TARGET PIC16F877 ;********************************************************************* ; Master Communicates with up to 8 remote ports and exchanges ; Port Information ; ;********************************************************************* ;* @version 0.1, 6 October 2001 ;* @author James Caska ;********************************************************************* list p=16F877 #include ;********************************************************************* ; Constants ;********************************************************************* COPY_START EQU .0 COPY_DONE EQU .7 COPY_READ EQU .5 COPY_WRITE EQU .6 ACK_OK EQU .0 ERROR_LCD EQU .4 ;********************************************************************* ; Registers ;********************************************************************* EEPROM_ADDRESS_H EQU .32 EEPROM_ADDRESS_L EQU .33 PageByteCount EQU .34 COPYLOOPCOUNT EQU .35 ADDRESS EQU .36 BUFFER EQU .40 ;Root of Buffer array BUFFER[0..31] ORG .0 GOTO INIT ORG .4 INTERRUPTHANDLER ;Interrupt not used in this example. All States are handled by polling RETFIE ;========================================== ; I2C Start Condition ;========================================== ; When the bus is idle, all devices on the bus have their SCL,SDA pins ; open circuit thus SCL and SDA are pulled high. When the master wants ; to do something it generates a start condition, by pulling the SDA ; low while SCL is high. This indicates to all slaves that something is ; about to happen ;========================================== START ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======Generate Start Bit Condition BSF STATUS,RP0 ;SSPCON2: is in Bank1 BSF SSPCON2,SEN I2C.Start.Wait BTFSC SSPCON2,SEN ;Poll until end of start condition GOTO I2C.Start.Wait BCF STATUS,RP0 ;Restore Bank0 RETURN ;========================================== ; I2C Restart Condition ;========================================== ; When the Master already has control of the bus, but wants to ; send a start condition it must use the restart sequence because the ; start conditions of the sequence are different to the start when bus ; is idle. ;========================================== RESTART ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======Generate Start Bit Condition BSF STATUS,RP0 ;SSPCON2: is in Bank1 BSF SSPCON2,RSEN I2C.Restart.Wait BTFSC SSPCON2,RSEN ;Poll until end of restart condition GOTO I2C.Restart.Wait BCF STATUS,RP0 ;Restore Bank0 RETURN ;========================================== ; I2C Stop Condition ;========================================== ; Once the master is finished with the bus it generates a stop sequence ; by letting the SDA line go from low to high while the SCL is high. ; This resets all slaves devices into into bus idle mode ready for the ; next start condition. ;========================================== STOP ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======Generate Stop Bit Condition BSF STATUS,RP0 ;SSPCON2: is in Bank1 BSF SSPCON2,PEN I2C.Stop.Wait BTFSC SSPCON2,PEN ;Poll until end of stop condition GOTO I2C.Stop.Wait BCF STATUS,RP0 ;Restore Bank0 RETURN ;========================================== ; I2C Transmit Byte and return ack to W ; 1 - Acknowledge Not Received ; 0 - Acknowledge Received ;========================================== ; Transmits a byte ;========================================== TX ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======Transmit the value on W ;=======Moving a value to SSPBUF begins the transmission BCF PIR1 , SSPIF ;Clear the Interrupt Flag, this will be set at the end of the transmission MOVWF SSPBUF ;Move W to SSPBUF which will trigger the I2C module to begin transmitting ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======Wait for I2C Transmit to complete BSF STATUS,RP0 ;SSPSTAT: is in Bank1 BTFSS SSPSTAT,BF ;CheckBufferIsActuallyFull GOTO I2C.TX.Error.ExpectedBufferFull BCF STATUS,RP0 ;Restore Bank0 I2C.TX.WaitForSSPInterrupt BTFSS PIR1,SSPIF GOTO I2C.TX.WaitForSSPInterrupt GOTO I2C.TX.Transmit.OK I2C.TX.Error.ExpectedBufferFull BCF STATUS,RP0 ;Restore Bank0 ;Insert Error Handling Here GOTO I2C.TX.Error.ExpectedBufferFull I2C.TX.Transmit.OK ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======Test I2C ACK Result read from slave BSF STATUS,RP0 ;SSPCON2: is in Bank1 MOVLW .1 ;1 = Acknowledge was not received from slave BTFSS SSPCON2,ACKSTAT MOVLW .0 ;0 = Acknowledge was received from slave BCF STATUS,RP0 ;Restore Bank0 RETURN ;====================================================== ; I2C Receive Command ; Initiates a Read Command to the I2C module and then ; waits until the interrupt is triggered from the ; receive ;====================================================== RX ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======Receive from I2C BCF PIR1,SSPIF ;Clear the interrupt flag before RX BSF STATUS,RP0 ;SSPCON2: is in Bank1 BSF SSPCON2,RCEN BCF STATUS,RP0 ;SSPCON2: is in Bank1 I2C.RX.WaitForSSPInterrupt BTFSS PIR1,SSPIF GOTO I2C.RX.WaitForSSPInterrupt MOVF SSPBUF,W RETURN ;====================================================== ; ACK COMMAND ;====================================================== ACK ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======ACK (Acknowledge) a Recieved Byte BCF PIR1,SSPIF ;Clear the interrupt flag before ACK BSF STATUS,RP0 ;SSPCON2: is in Bank1 BCF SSPCON2,ACKDT ;Clear ACKDT to Acknowledge Bit BSF SSPCON2,ACKEN ;Start Acknowledge Sequence BCF STATUS,RP0 ;SSPCON2: is in Bank1 I2C.ACK.WaitForEndSequence BTFSS PIR1,SSPIF ;Interrupt will be set at end of Acknowledge GOTO I2C.ACK.WaitForEndSequence RETURN ;====================================================== ; NACK COMMAND ;====================================================== NACK ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======NACK (No Acknowledge) a Recieved Byte BCF PIR1,SSPIF ;Clear the interrupt flag before ACK BSF STATUS,RP0 ;SSPCON2: is in Bank1 BSF SSPCON2,ACKDT ;Set ACKDT to transmit an NACK Bit BSF SSPCON2,ACKEN ;Start Acknowledge Sequence BCF STATUS,RP0 ;SSPCON2: is in Bank1 I2C.NACK.WaitForEndSequence BTFSS PIR1,SSPIF ;Interrupt will be set at end of Acknowledge GOTO I2C.NACK.WaitForEndSequence RETURN ;======================================================== ; Sends the value on the Master Port (PortD) to the remote ; device on address ADDRESS ;======================================================== TransmitMyPort CALL START BCF ADDRESS,0 ;Is a write command so clear write Bit MOVF ADDRESS,W CALL TX ;Transmit the Address to establish a connection IORLW .0 ;Check that the expected acknowledge is received BTFSS STATUS,Z ;Expect 0 = Ack received GOTO TransmitMyPort.DeviceNotFound MOVF PORTB,W ;Get the Port to transmit CALL TX ;Send It CALL STOP RETURN TransmitMyPort.DeviceNotFound ;No device at the CALL STOP RETURN ;======================================================== ; Does a port exchange with the I2C device at address W ;======================================================== ReceiveRemotePort CALL START BSF ADDRESS,0 ;Is a read so set read/write Bit MOVF ADDRESS,W CALL TX ;Transmit the Address to establish a connection IORLW .0 ;Check that the expected acknowledge is received BTFSS STATUS,Z ;Expect 0 = Ack received GOTO ReceiveRemotePort.DeviceNotFound CALL RX CALL NACK CALL STOP MOVF SSPBUF,W MOVWF PORTD RETURN ReceiveRemotePort.DeviceNotFound ;No device at the I2C Address CALL STOP RETURN ;======================================================== ; Does a port exchange with the I2C device at address W ;======================================================== doPortExchange MOVWF ADDRESS CALL TransmitMyPort CALL ReceiveRemotePort RETURN INIT ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;======Begin PORT Configuration BSF STATUS, RP0 ;PORT TRIS Registers are on page 1 ;======PORT A MOVLW .63 ;PORTA Configuration Bits MOVWF TRISA ;======PORT B MOVLW .255 ;PORTB Configuration Bits MOVWF TRISB ;======PORT C MOVLW .255 ;PORTC Configuration Bits MOVWF TRISC ;======PORT D MOVLW .0 ;PORTD Configuration Bits MOVWF TRISD BCF STATUS, RP0 ;Restore Page0 ;========================================== ;Autogenerated configuration code PIC16F877 ;Config Wiz V0.1, www.virtualbreadboard.com ;========================================== ;=======I2C Master Mode Configuration MOVLW B'00101000' MOVWF SSPCON ;=======I2C Bit Rate Setup BSF STATUS,RP0 ;SSPADD is in Bank1 MOVLW .9 MOVWF SSPADD BCF STATUS,RP0 ;Restore Bank0 ;=======I2C Slew Rate Control BSF STATUS,RP0 ;SSPSTAT is in Bank1 BSF SSPSTAT,SMP BCF STATUS,RP0 ;Restore Bank0 ;=======SCL/SDA PIN DIRECTION SETUP BSF STATUS,RP0 ;TRISC is in Bank1 MOVLW B'00011000' ; setup value IORWF TRISC,F ; SCL and SDA BCF STATUS,RP0 ;Restore Bank0 MAIN RLF PORTA,W ;Exchange ports with I2C at address = PortA ANDLW B'00011110' CALL doPortExchange GOTO MAIN END