Noch eine weitere Frage, wie lese ich das ganze wieder aus?
Servus,
also auf meinem Testboard ist ein externes EEPROM 24LC256 und dieses würde ich gerne absprechen(PIC16F877A). Also ich würde gerne Daten draufschreiben und diese dann auch wieder auslesen.
Ich habe im Democode auch folgenden Code in asm gefunden.
Code:write_eeprom banksel SSPCON2 ;write to EEPROM bsf SSPCON2,SEN ;start bit btfsc SSPCON2,SEN goto $-1 movlw B'10100000' ;send control byte (write) banksel SSPBUF movwf SSPBUF call ssprw banksel SSPCON2 btfsc SSPCON2,ACKSTAT ;ack? goto $-1 movlw 0x00 ;send slave address HIGH byte banksel SSPBUF movwf SSPBUF call ssprw banksel SSPCON2 btfsc SSPCON2,ACKSTAT ;ack? goto $-1 movlw 0x05 ;send slave address LOW byte(0x0005) banksel SSPBUF movwf SSPBUF call ssprw banksel SSPCON2 btfsc SSPCON2,ACKSTAT ;ack? goto $-1 banksel temperature movf temperature,w ;send slave DATA = temperature movwf SSPBUF call ssprw banksel SSPCON2 btfsc SSPCON2,ACKSTAT ;ack? goto $-1 bsf SSPCON2,PEN ;stop bit btfsc SSPCON2,PEN goto $-1 banksel TMR1L bcf PIR1,TMR1IF ;clear TIMER1 overflow flag clrf TMR1L ;clear registers for next overflow clrf TMR1H return ;------------------------ IDLE MODULE ------------------------------------- ssprw ;check for idle SSP module movlw 0x00 banksel SSPCON2 andwf SSPCON2,w sublw 0x00 btfss STATUS,Z goto $-4 btfsc SSPSTAT,R_W goto $-1 return
Aber leider funktioniert die ganze Geschichte nicht. Und da ich davon nicht all zu viel Ahnung habe, brauche ich nun Hilfe.
Hat irgendwer einen Beispielcode, der funzt?
Danke
Gruß
Noch eine weitere Frage, wie lese ich das ganze wieder aus?
Hallo,
wenn du nicht weist wie man das ausliest, woher weist du dann das das Schreiben nicht geht? Das Auslesen geht folgendermaßen: Du sendest das Controlbyte mit Bit 0 = 0 (Bit 0 = 1 bedeutet lesen, Bit 0 = 0 bedeutet schreiben), anschließend die Adresse (High- und Lowteil), daraufhin ein Restart (gibts beim MSSP-Modul ein Bit; SSPCON2,RSEN), dann wieder das Controlbyte mit Bit 0 = 1 (=lesen) und dann liest du die Daten Byte für Byte (mit SSPCON2,RCEN wird ein Byte eingelesen, nach jedem Byte Acknowledge senden bcf SSPCON2,ACKDT und dann bsf SSPCON2,ACKEN), wenn du keine weiteren Daten mehr einlesen möchtest sendest du statt Acknowlede ein NotAcknowledge (bsf SSPCON2,ACKDT und dann bsf SSPCON2,ACKEN).
Gruß,
Michael
PS: Entschuldigt den Schreibstil aber ich habe heute 11h gelötet.
Guten Morgen,
also ich mein Oszi wahlweise an an der Daten und Wahlweise an der Clock Leitung. Aber ich sehe einfach kein Signal. Selbst, wenn ich die Frequenz runter schraube.... also ich habe einen 4 MHz Quarz dran, was ja bedeutet, dass diese intern mit 1Mhz arbeitet, was wiederum die oberste Grenze für den EEPROM ist. Aber es tut net...
Hallo,
wie hast du das MSSP-Modul initialisiert? Bei mir läuft der Bus mit 100kHz. Dazu schreibe ich ins Register SSPCON 28h und in SSPADD 31h für 100kHz bei 20MHz. Außerdem müssen PORTC.3 und .4 auf Eingang stehen.
Gruß,
Michael
Servus,
also irgendwie ist der Bereich der PIC schwach frequentiert. Ich habe nach wie vor das Problem mit dem EEPROM.
Ich habe mich jetzt noch mal im Detail mit I2C Programmierung auseinander gesetzt und bin bei sprut fündig geworden und versuche das Beispiel mit dem EEPROM umzusetzen, doch auch das mag nicht so recht klappen!
Das ist der Code von der Seite, den ich versuche zum laufen zu bekommen. Dort wird die Initialisierung genauso gemacht, wie ich das in meinem Code mache.Code:EPPROM_INIT ; einstellen von RC3 & RC4 auf input bsf STATUS, RP0 ; Bank 1 movlw B'00011000' ; RC3,4 inputs iorwf TRISC, f ; + RC2=CCP1 output bcf STATUS, RP0 ; Bank 0 ;bcf PORTC,3 ;bcf PORTC,4 ; einstellen des I2C-Taktes auf knapp 400 kHz bsf STATUS, RP0 ; Bank 1 movlw d'9' ; clock = 4MHz/(4*(9+1)) = 100kHz movwf SSPADD ; für I2C bcf STATUS, RP0 ; Bank 0 movlw B'00001000' ; master mode, clock=Fosc/(4*(SSPADD+1)) movwf SSPCON ; bsf SSPCON, SSPEN ; MSSP-Modul enable EEPROM_SCHREIBEN ;**Schreibe Wert 5 auf Speicher-Adresse 3 in 24C04************* call i2c_on ; Bus aktiv movlw H'A0' ; 1010 0000 call i2c_tx ; 24C04 zum Schreiben adressieren movlw 0x00 ; high Teil der Adresse (Page) call i2c_tx movlw 0x03 ; low Teil der Adresse call i2c_tx movlw 0x05 ; Wert der auf Adresse 3 soll call i2c_tx call i2c_off ; Bus freigeben ; Fertig. Nun beginnt im EEPROM ein Lösch-Schreib-Zyklus ; mit dem der Wert 5 in die EEPROM-Zelle 3 geschrieben wird. ; Das wird etwa 10 ms dauern. Solange ist der 24C04 nicht ansprechbar. ; ; .... ; das Programm geht dann irgentwie weiter EEPROM_LESEN ;**Stelle EEPROM auf Speicher-Adresse 3 ein************* call i2c_on ; Bus aktiv movlw H'A0' ; 1010 0000 call i2c_tx ; 24C04 zum Schreiben adressieren movlw 0x00 ; high Teil der Adresse call i2c_tx movlw 0x03 ; low Teil der Adresse call i2c_tx call i2c_off ; Bus freigeben ;Nun steht der Adress-Pointer im 24C04 auf dem Wert 3. ;Nun können wir den I2C-Bus erneut aktivieren, um ein Byte aus dem 24C04 zu lesen. Das ist unser Datenbyte. ;**Lesen des aktuellen Bytes aus 24C04************* call i2c_on ; Bus aktiv movlw H'A0' ; 1010 0001 call i2c_tx ; 24C04 zum lesen adressieren call i2c_rx movfw SSPBUF ; I2C Empfangsregister auslesen movwf DATENPUFFER ; Byte in Speicherzelle Datenpuffer retten call i2c_off ; Bus freigeben ;***I2C UNTERPROGRAMME************************************************************ ; ; I2C-Bus im Master-Mode übernehmen i2c_on bcf PIR1, SSPIF ; SSPIF Bit löschen bsf STATUS, RP0 bsf SSPCON2, SEN ; Bus Übernahme anweisen bcf STATUS, RP0 goto i2c_warte ; ein Byte aus W senden i2c_tx movwf SSPBUF ; -> zum I2C-Slave übertragen goto i2c_warte ;ein Byte vom Slave empfangen (nach SSPBUF) i2c_rx bsf STATUS, RP0 bsf SSPCON2, RCEN ; Daten Empfang einschalten bcf STATUS, RP0 goto i2c_warte ; I2C-Bus wieder freigeben i2c_off bsf STATUS, RP0 bsf SSPCON2, PEN ; Bus Freigabe anweisen bcf STATUS, RP0 i2c_warte btfss PIR1, SSPIF ; fertig? goto i2c_warte ; nein, noch nicht bcf PIR1, SSPIF ; ja, alles fertig, nun noch SSPIF zurücksetzen return ;***ENDE UNTERPROGRAMME********************************************************** ; End of I2C routines
Mein Problem ist, dass ich gleich bei der Aktivierung des Busses im Unterprogramm (voriger durchlauf von i2c_on) i2c_warte hängen bleibe und sich der PIC dann totläuft, wenn er das setzen von SSPIF wartet.
Jemand ne Idee?
Gruß und Danke
Hallo,
ja die PICs sind hier in der Minderheit. Dein Problem klingt nach vergessenen Pullup-Widerständen. Können die EEPROMs wirklich 400kHz? Ich bin mir momentan nicht sicher. Mess einfach mal die Spannung an PortC.3 und .4, dort müssten eigentlich 5V anliegen. Wenn dem nicht so ist könnte ein Reset (Power-On-Reset) des Speicherbausteins nicht schaden.
Gruß,
Michael
Servus,
ja der 24LC256 kann 400 kHz aber ich Takte mit nur 100kHz
Achja und die Widerstände sind selbstverständlich auch vorhanden
Hallo,
ich habe mir jetzt mal den Code (von Sprut) im Detail angesehen. Das Einzige was mir auffällt ist ein Fehelr in der Zeile
movlw H'A0' ; 1010 0001
beim Lesen des aktuellen Bytes. Im Kommentar steht der Wert richtig drin, vorne aber nicht (H'A1' statt H'A0').
Wenn der PIC den Bus garnicht erst übernehmen kann stimmt normalerweise was mit den Pegeln an den Busleitungen nicht. Mess also bitte mal mit einem Multimeter die 5V nach. Wenn man den Bus nämlich abschießt kann es vorkommen dass eine oder beide Leitungen dauerhaft auf LOW liegen.
Ich habe soeben das Programm in einen 16F877 geladen, es läuft einwandfrei. Ich habe nur zwei Wartezeiten und ein paar nops zum Debuggen eingefügt. Die Adresse des EEPROMS (24C512) ist bei mir 0A4h.
Gruß,
Michael
Lesezeichen