;*********************************************************************** ; Routinen für I2C ; Bus übernehmen i2c_on ; W senden i2c_tx ; Byte empfangen i2c_rx (nach w und d_byte) ; Bus freigeben i2c_off ;*********************************************************************** ; schreiben/lesen W nach/von Adresse adr_l/adr_h im I2C-Device adr_e write_i2c movwf d_byte ; Datenbyte zwischenspeichern call i2c_on ; Bus start rlf adr_h, w ; HI-Adresse 1 bit nach links und nach W andlw b'00001110' ; 3 Bits maskieren iorwf adr_e, w ; und nach I2C-Adresse andlw b'11111110' ; letztes Bit 0 = write Data call i2c_tx ; 1010 xxx0 sende I2C-Adresse movfw adr_l call i2c_tx ; sende interne Adresse LO movfw d_byte ; Datenbyte nach W holen call i2c_tx ; schreibe W nach Speicherzelle call i2c_off ; Bus stop return read_i2c call i2c_on ; Bus start rlf adr_h, w ; HI-Adresse 1 bit nach links und nach W andlw b'00001110' ; 3 Bits maskieren iorwf adr_e, w ; und nach I2C-Adresse andlw b'11111110' ; letztes Bit 0 = write Data call i2c_tx ; 1010 xxx0 sende I2C-Adresse movfw adr_l call i2c_tx ; sende interne Adresse LO call i2c_ron ; Bus repeated start rlf adr_h, w ; HI-Adresse 1 bit nach links und nach W andlw b'00001110' ; 3 Bits maskieren iorwf adr_e, w ; und nach I2C-Adresse iorlw b'00000001' ; letztes Bit 1 = read Data call i2c_tx ; 1010 xxx1 sende I2C-Adresse call i2c_rx ; lese Speicherzelle nach W call i2c_off ; Bus stop return ; I2C-Bus im Master-Mode übernehmen - START i2c_on bcf PIR1, SSPIF ; SSPIF Bit zurücksetzen bank1 bsf SSPCON2, SEN ; start condition bank0 btfss PIR1, SSPIF ; Bus schon frei ? goto $-1 ; bcf PIR1, SSPIF ; ja, Bus ist übernommen return ; I2C-Bus im Master-Mode übernehmen - repeated START i2c_ron bcf PIR1, SSPIF ; SSPIF Bit zurücksetzen bank1 bsf SSPCON2, RSEN ; repeated start condition bank0 btfss PIR1, SSPIF ; Bus schon frei ? goto $-1 ; bcf PIR1, SSPIF ; ja, Bus ist übernommen return ; I2C-Bus wieder freigeben - STOP i2c_off bank1 bcf PIR1, SSPIF ; SSPIF Bit zurücksetzen bsf SSPCON2, PEN ; Bus Freigabe anweisen bank0 btfss PIR1, SSPIF ; Bus schon frei ? goto $-1 ; bcf PIR1, SSPIF ; ja, Bus frei return ; ein Byte aus W auf I2C senden i2c_tx movwf SSPBUF ; W auf I2C-Bus senden btfss PIR1, SSPIF ; ACK schon empfangen ? goto $-1 ; bcf PIR1, SSPIF ; ja return ; ein Byte vom I2C empfangen i2c_rx bank1 bsf SSPCON2, RCEN ; Daten Empfang einschalten bank0 btfss PIR1, SSPIF ; Daten empfangen ? goto $-1 ; bcf PIR1, SSPIF ; ja movf SSPBUF, W ; empfangene Daten -> W return ; ACK senden, wenn Folgebyte kommt i2c_ack bank1 bsf SSPCON2, ACKEN ; ACK senden bank0 return