I2C Schnittstelle mit PIC 16F877
Dienstag, 22. Mai 2012
 
 

PIC Mikrocontroller Forum  |  PIC Mikrocontroller  |  Programmiersprache Assembler  |  Schnittstellen (Assembler)  |  I2C Schnittstelle mit PIC 16F877 « vorheriges nächstes »
Seiten: [1] Nach unten Drucken
Autor Thema: I2C Schnittstelle mit PIC 16F877  (Gelesen 2458 mal)
 
baobab
Gast
« am: März 15, 2009, 16:29:37 »

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


Code:
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
Code:
;#####################################################################
;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
Gespeichert
wberger
Full Member
***
Offline Offline

Beiträge: 204


Profil anzeigen
« Antworten #1 am: März 15, 2009, 16:57:16 »

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
Gespeichert
baobab
Gast
« Antworten #2 am: März 15, 2009, 17:48:19 »

hallo wberger,

EEPROM_ADR habe ich wie folgt definiert:
Code:
#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:
Code:
;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

Gespeichert
Christian
Newbie
*
Offline Offline

Beiträge: 1


Profil anzeigen
« Antworten #3 am: März 21, 2009, 10:49:11 »

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
Gespeichert
wberger
Full Member
***
Offline Offline

Beiträge: 204


Profil anzeigen
« Antworten #4 am: März 23, 2009, 20:39:11 »

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

Gespeichert
Seiten: [1] Nach oben Drucken 
« vorheriges nächstes »
Gehe zu:  

Powered by MySQL Powered by PHP Made for Mozilla (Firefox) Made for Internet Explorer
Seite erstellt in 0.042 Sekunden mit 19 Zugriffen.
 
Top! Top!