;********************************************************************* ; * ; Tutorial 19 Copying a 24LC64 EEPROM using I2C Master mode * ; communications. * ; * ;********************************************************************* ;* TARGET PIC16F877 ;********************************************************************* ; Uses I2C to Read and Write to an 24LC64 I2C EEPROM ; ;********************************************************************* ;* @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 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_ERROR ;=================================================== ; There is no error handling in this example, any error ; will cause a jump to this infinite error loop and ; the processor will fall asleep ;=================================================== I2C_ERROR BSF PORTB,ERROR_LCD ;Error! Requires a reset as no error handling. SLEEP NOP GOTO I2C_ERROR RETURN ;========================================== ; 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 ;========================================== I2CXTX ;========================================== ;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 TX CALL I2CXTX IORLW .0 ;Check that the expected acknowledge is received BTFSS STATUS,Z ;Expect 0 = Ack received GOTO I2C_ERROR 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 ;=================================================== ;Writes a Page of 32 bytes from the buffer into the ;destination EEPROM ;=================================================== WriteBufferIntoEEPROM BSF PORTB,COPY_WRITE CALL START WriteBufferIntoEEPROM.PollEEPROM CALL RESTART ;Generate a Start Condition MOVLW B'10100010' ;Sequential Read, from 1010000 address EEPROM CALL I2CXTX IORLW .0 ;If the EERPOM is still writing then it will not ACKNOWLEDGE. BTFSS STATUS,Z GOTO WriteBufferIntoEEPROM.PollEEPROM ;Hence we keep trying until the EEPROM is available. MOVF EEPROM_ADDRESS_H,W ;Move the address to transmit and send it CALL TX MOVF EEPROM_ADDRESS_L,W CALL TX MOVLW .32 MOVWF PageByteCount MOVLW BUFFER ;Put BUFFER Pointer into Indirect Register MOVWF FSR WriteBufferIntoEEPROM.Loop MOVF INDF,W MOVWF PORTD CALL TX INCF FSR,F DECFSZ PageByteCount,F GOTO WriteBufferIntoEEPROM.Loop CALL STOP ;Stop MOVLW .32 ;Increment the EEPROM Adress by a page(32 bytes) ADDWF EEPROM_ADDRESS_L,F BTFSC STATUS,C INCF EEPROM_ADDRESS_H,F BCF PORTB,COPY_WRITE RETURN ;=================================================== ;Reads a Page of 32 bytes from the source EEPROM ;into the buffer ready to write back to the dest eeprom ;The EEPROM uses Sequential Read mode to read 32 byte ;page in one go. ;=================================================== ReadPageIntoBuffer BSF PORTB,COPY_READ CALL START ;Generate a Start Condition MOVLW B'10100000' ;Sequential Read, begins by setting the address with a write command CALL TX MOVF EEPROM_ADDRESS_H,W CALL TX MOVF EEPROM_ADDRESS_L,W CALL TX CALL RESTART ;Generate a Start Condition MOVLW B'10100001' ;Sequential Read, from 1010000 address EEPROM CALL TX MOVLW .32 MOVWF PageByteCount MOVLW BUFFER ;Put BUFFER Pointer into Indirect Register MOVWF FSR ReadPage.Loop CALL RX MOVWF PORTD MOVWF INDF INCF FSR,F DECF PageByteCount,W BTFSS STATUS,Z CALL ACK DECFSZ PageByteCount,F GOTO ReadPage.Loop CALL NACK CALL STOP ;Stop BCF PORTB,COPY_READ RETURN doCopy CLRF EEPROM_ADDRESS_H ;Clear the Copy From/To Address CLRF EEPROM_ADDRESS_L MOVLW .2 MOVWF COPYLOOPCOUNT doCopy.Loop CALL ReadPageIntoBuffer CALL WriteBufferIntoEEPROM DECFSZ COPYLOOPCOUNT GOTO doCopy.Loop 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 B MOVLW .1 ;PORTB Configuration Bits MOVWF TRISB ;======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 BTFSS PORTB,COPY_START ;Wait until the Copy DIP goes high GOTO MAIN CALL doCopy ;do the copy, copy from one eeprom to the other BSF PORTB,COPY_DONE ;Indicate copy is complete WaitUntilCopyToggledLow BTFSC PORTB,COPY_START GOTO WaitUntilCopyToggledLow BCF PORTB,COPY_DONE GOTO MAIN END