Autor Thema: I2C Schnittstelle mit PIC 16F877  (Gelesen 7666 mal)

baobab

  • Gast
I2C Schnittstelle mit PIC 16F877
« am: März 15, 2009, 16:29:37 Nachmittag »
hallo,

Ich kämpfe jetzt schon einige Tage mit meiner PIC schaltung!
Sie sollte nur einen Wert aus dem EEPROM 24LC512 über die I2C schnittstelle des PIC 16F877 auslesen
und über die Serielle schnittstelle ausgeben.
Leider bekomme ich nur FF zurück.
Ich weiss leider nicht, ob dies an meiner Schreibfunktion oder Lesefunktion liegt.
Würde mich über hilfe sehr freuen

dank im voraus
Hannes
ps: hier meine I2C subroutinen


init_i2c:
;---------------------------------------------------------------------
;baud rate = 100KHz @ 20MHz

banksel SSPSTAT
bsf SSPSTAT,SMP ; Slew rate disable
bcf SSPSTAT,CKE ; i2c standard

banksel SSPCON
clrf SSPCON
bsf SSPCON,SSPM3 ; I2C master mode in hardware
bsf SSPCON,SSPEN ; enable SSP module

movlw 0x31 ; ;
banksel SSPADD ; select SFR bank
movwf SSPADD

bcf STATUS, RP0
bcf STATUS, RP1 ; bank 0

return
;#####################################################################
;I2C unterprogramme
;#####################################################################
;************************************************************

;---------------------------------------------------------------------
I2CSTART:
banksel SSPCON2
bsf SSPCON2, SEN ; START Condition
test_start:
nop
nop
btfsc SSPCON2, SEN ; Prüfen ob START gesendet
goto test_start
banksel PIR1

return

;---------------------------------------------------------------------
;#####################################################################
;---------------------------------------------------------------------

I2CSTOP:
banksel SSPCON2
bsf SSPCON2, PEN
test_stop:
nop
nop
btfsc SSPCON2, PEN
goto test_stop
banksel PIR1
return

;---------------------------------------------------------------------
;#####################################################################
;---------------------------------------------------------------------

I2CSEND:
banksel PIR1
bcf PIR1,SSPIF ; clear interrupt flag
movwf SSPBUF ; move slave address to SSPBUF
test_send:
nop
nop
btfss PIR1,SSPIF ; has SSP completed sending SLAVE Address?
goto test_send ; no, loop back to test_send

bcf PIR1,SSPIF ; clear interrupt flag

return
;---------------------------------------------------------------------
;#####################################################################
;---------------------------------------------------------------------
I2CREAD:

bsf PORTB, 6
banksel PIR1
bcf PIR1,SSPIF ; clear interrupt flag


bsf STATUS, RP0
bcf STATUS, RP1 ; bank1

bsf SSPCON2, RCEN ; Read enable

banksel PIR1
test_read:
nop
nop
btfss   PIR1, SSPIF     ; fertig?
        goto    test_read       ; nein, noch nicht
bcf     PIR1, SSPIF     ; ja, alles fertig, nun noch SSPIF zurücksetzen

banksel SSPBUF
movf SSPBUF, W
banksel i2c_buffer
movwf i2c_buffer
banksel SSPCON2
bcf SSPCON2, RCEN

bcf STATUS, RP0
bcf STATUS, RP1 ; bank0
return
;---------------------------------------------------------------------
;#####################################################################
;---------------------------------------------------------------------

I2CCHECKACK:
movlw 0x00
movwf i2ccounter ; Ackpolling counter 0

check_ack:
nop
nop
banksel i2ccounter
incf i2ccounter
btfss STATUS,Z
goto I2CCHECKACK_END

banksel SSPCON2
btfsc SSPCON2,ACKSTAT ; was ACK received from slave?
goto check_ack ;
bsf SSPCON2, ACKSTAT
bcf STATUS, RP0
bcf STATUS, RP1

I2CCHECKACK_END:

return

;---------------------------------------------------------------------
;---------------------------------------------------------------------
I2C_WAKE_EEPROM:
call I2CSTART ; START Condition
I2C_WAKE_LOOP ; RESTART LOOP
movlw EEPROM_ADR ; EEPROM Adresse in W schreiben
btfsc I2C_RW_BIT ; Schreiben oder Lesen ?
bsf W,0
call I2CSEND ; Adr senden
call I2CCHECKACK ; Ack empfangen?

btfss STATUS,Z ; Prüfen ob RESTART gesendet werden muss
return ; Nein: zurück

banksel SSPCON2 ; Ja:
bsf SSPCON2,RSEN ; RESTART einleiten
btfsc SSPCON2, RSEN ; Prüfen ob restart gesendet
goto $-1 ; loop back
goto I2C_WAKE_LOOP ; Adresse erneut senden

return
;---------------------------------------------------------------------

I2C_SEND_ADR:

movwf i2c_eeprom_adr_h
call I2CSEND
call I2CCHECKACK

movwf i2c_eeprom_adr_l
call I2CSEND
call I2CCHECKACK
return
;---------------------------------------------------------------------

I2C_SEND_DATA:
movwf i2c_buffer
call I2CSEND
call I2CCHECKACK
return

;---------------------------------------------------------------------
I2C_READ_DATA:
call I2CREAD

banksel SSPCON2
bsf SSPCON2, ACKDT ; NOT ACK auswählen
bsf SSPCON2, ACKEN ; NOT ACK senden

btfsc SSPCON2, ACKEN ; Polling ob gesendet
goto $-1
return

Offline wberger

  • Full Member
  • ***
  • Beiträge: 205
    • Profil anzeigen
Re: I2C Schnittstelle mit PIC 16F877
« Antwort #1 am: März 15, 2009, 16:57:16 Nachmittag »
Deinen gesamten Code habe ich jetzt noch nicht durchgeschaut (habs nicht so mit ASM). Vorab aber noch eine generelle Frage. Bist du dir sicher, dass ein ACK zurückkommt?
Welchen Wert hat EEPROM_ADR?
Wie sind die Adresspins des eeproms angeschlossen?

Gruß
  Wolfgang

baobab

  • Gast
Re: I2C Schnittstelle mit PIC 16F877
« Antwort #2 am: März 15, 2009, 17:48:19 Nachmittag »
hallo wberger,

EEPROM_ADR habe ich wie folgt definiert:
#define EEPROM_ADR b'10100000'Die Adress Pins des 24LC512 liegen auf Masse.

Um einen Wert aus dem EEPROM zu lesen habe ich die oben zitierten Subroutinen wie folgt auf gerufen:
;lesn: Adr wählen

bcf I2C_RW_BIT ; R/W: write
call I2C_WAKE_EEPROM ; EEPROM addressieren

movlw 0x00
movwf i2c_eeprom_adr_h ; High Teil der Adr.
movlw 0x00
movwf i2c_eeprom_adr_l ; Low Teil der Adr
call I2C_SEND_ADR ; Low und High Teil der Adr senden



banksel SSPCON2
bsf SSPCON2, RSEN
btfsc SSPCON2, RSEN ; Repeated start condition
goto $-1


; Lesen
bsf I2C_RW_BIT ; Lesen initalisieren
call I2C_WAKE_LOOP ; Repeated start condition

call I2C_READ_DATA ; Daten Lesen und auf i2c_buffer speichern

call I2CSTOP ; I2C stoppen


Offline Christian

  • Newbie
  • *
  • Beiträge: 1
    • Profil anzeigen
Re: I2C Schnittstelle mit PIC 16F877
« Antwort #3 am: März 21, 2009, 10:49:11 Vormittag »
Hi, falls Du noch mit dem I2C kämpfst,
könnte ich dir meine schnipsel(ASM) zur verfügung stellen,
eventuell hilft Dir das ja ein wenig.

mfG
Christian

Offline wberger

  • Full Member
  • ***
  • Beiträge: 205
    • Profil anzeigen
Re: I2C Schnittstelle mit PIC 16F877
« Antwort #4 am: März 23, 2009, 20:39:11 Nachmittag »
Kannst du mir bitte mal den Abschnitt
  I2C_WAKE_LOOP   
erklären? Ist Status, Z nur gesetzt, wenn der Ack-Timeout eingetreten ist? Bist du dir sicher, dass das wie erwünscht funktioniert, oder wird hier unter Umständen ein Restart geschickt?

Gruß
  Wolfgang


Offline Landroval

  • Newbie
  • *
  • Beiträge: 1
    • Profil anzeigen
Re: I2C Schnittstelle mit PIC 16F877
« Antwort #5 am: März 27, 2014, 21:49:14 Nachmittag »
Hallo,
bin neu hier, aber falls dein Problem noch nicht gelöst ist:
In I2C_WAKE_LOOP: BSF W,0 setzt in keinem Falle Bit-0 im W Register!
Der Opcode sagt, dass nur die Bitnummer und die Adresse auf RAM eingetragen werden können.
Der Assembler interpretiert "W" als 0.
Damit wird über das "Indirekt"-Register adressiert.
Da ich nicht sehe, dass FSR sinnvoll initialisiert wurde, geht da was schief.
Das Bit wird irgendwo gesetzt, aber nicht im "W"ork-Register.

 


* Recent Topics