logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Błędny zapis/odczyt EEPROM 24C02 z ASM51 - odczyt wartości 255, WP do masy

bolek 03 Lip 2006 12:12 1657 6
REKLAMA
  • #1 2786054
    bolek
    Poziom 35  
    Posty: 4099
    Pomógł: 86
    Ocena: 299
    Problem polega na tym że nie moge poprawnie dogadać się z pamięcią eeprom, program odczytuje mi same wartości 255, i wygląda na to że coś nie tak jest z zapisem, tak jak by nie zapisał poprawnie zmienionych wartosci
    Noga WP sciągnieta do masy, pull-up na SDA i SCL jest. pamięc poprawnie podpięta bo przy próbie odczytu (wywołanie adresu 160) nie wywala byka. Procedury działały z innymi układami na i2c i nie było problemu


    
    ;*************************************************************************
    LOAD:
    	CALL I2C_STOP		;NA WSZELKI WYPADEK, ZEBY I2C START BYLO PRAWIDŁOWE
    	CALL I2C_START
    	MOV A, #160		;ADRES EEPROMA
    	CALL I2C_WRITE
    	MOV ERR_I2C, C
    	MOV A, #1		;ADRES KOMURKI
    	CALL I2C_WRITE
    	CALL I2C_START
    	MOV A, #161		;BO BEDZIEMY ODCZYTYWAC
    	CALL I2C_WRITE
    
    	CLR C
    	CALL I2C_READ
    	MOV V_MAX, A
    	CALL I2C_READ
    	MOV V_MIN, A	
    	CALL I2C_READ
    	MOV V_MAN, A	
    	CALL I2C_READ
    	MOV V_STA, A	
    	CALL I2C_READ
    	MOV V_STO, A
    	CALL I2C_READ
    	MOV SERIA, A	
    	CALL I2C_READ
    	MOV HAM, A
    	CALL I2C_READ
    	MOV TIMEA, A	
    	CALL I2C_READ
    	MOV TIMEB, A	
    	SETB C
    	CALL I2C_READ
    	MOV OCZKA, A	
    	CALL I2C_STOP
    	RET
    ;*************************************************************************
    SAVE:
    	
    	CALL I2C_START
    	MOV A, #160		;ADRES EEPROMA
    	CALL I2C_WRITE
    	MOV ERR_I2C, C
    	MOV A, #1		;ADRES KOMURKI
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, V_MAX
    	CALL I2C_WRITE
    	CALL WAIT_10MS	
    	MOV A, V_MIN	
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, V_MAN	
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, V_STA	
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, V_STO
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, SERIA	
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, HAM	
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, TIMEA	
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, TIMEB	
    	CALL I2C_WRITE
    	CALL WAIT_10MS
    	MOV A, OCZKA	
    	CALL I2C_WRITE
    
    	CALL I2C_STOP
    	CALL LOAD
    	RET
    


    Procedury do obslugi I2c
    ;*************************************************************************
    I2C_WRITE:			;ZAPISUJE NA I2C ZAWARTOSC ACC. ODDAJE ACK W CY
    	CLR 	SCL		;SKASUJ SCL- BO NASTAPI WYSTAWIENIE BITU NA SDA
    	MOV 	R2, #8		;BO OSIEM BITOW DO WYSLANIA
    I2W:	RLC 	A		;"WYSTAWIENIE" KOLEJNEGO BITU
    	MOV 	SDA, C		;USTAW LINIE SDA
    	CALL 	I2C_TAKT	;OPUZNIENIE...
    	SETB 	SCL		;\
    	CALL 	I2C_TAKT	; >IMPULS SCL
    	CLR 	SCL		;/
    	CALL 	I2C_TAKT	;OPUZNIENIE...
    	DJNZ 	R2, I2W		;JESLI WYSLANO 8 BITOW, TO ODBIERZ ACK
    	SETB 	SDA		;PO ZAKANCZENIU TANSMISJI USTAW 1 NA SDA	
    	ACALL 	I2C_TAKT	;OPUZNIENIE...
    	SETB 	SCL	;WYSTAWIENIE IMPULSU ACK
    	MOV 	C, SDA	;PRZEPISANIE IMPULSU ACK DO CY->
    	CLR 	SCL		;CY=0 TO SLAVE ODPOWIEDZIAŁ
    	RET		;CY=1 TO SLAVE NIE ODPOWIEDZIAŁ
    ;****************************************************************************
    I2C_READ:			;ZAPISUJE DO ACC WARTOSC Z ODEBRANA Z I2C.
    	SETB 	SDA			;Z CY WYSYLANA JEST WIADOMOSC O ACK I NACK
    	CLR 	SCL		;TAK PROFILAKTYCZNIE... 
    	MOV 	R2, #8		;BO ODBIERZEMY OSIEM BITOW
    	ACALL 	I2C_TAKT
    	
    I2R:	RLC 	A		;PRZESUN FLAGE I "ODSLON" MSB DO ZAPISU
    	SETB 	SCL		;IMPULS SCL I ZDJECIE BITU Z I2C TUZ PRZED OPADNIECIEM 	
    	ACALL 	I2C_TAKT	;SYGNALU NA SCL.
    	MOV 	C, SDA		;
    	CLR 	SCL		;
    	ACALL 	I2C_TAKT	;
    	DJNZ 	R2, I2R		;JESLI ODEBRANO 8 BITOW, TO WYSLIJ  ACK
    	RLC 	A		;PRZEWIN FLAGE NA SWOJE MIEJSCE
    	MOV 	SDA , C		;WYSTAW FLAGE NA LINIE SDA 
    	SETB 	SCL		;\
    	ACALL 	I2C_TAKT	; > IMPULS NACK
    	CLR 	SCL		;/
    	RET
    ;***********************************************************************
    I2C_START:
    	SETB 	SDA
    	SETB 	SCL		;PRZY USTAWIONYM SCL WYZRUJ LINIE SDA->
    	ACALL 	I2C_TAKT	;TO JEST WARUNEK STARTU DLA I2C
    	CLR 	SDA		;UFAKA! PROGRAM NIE KASUJE BITU SCL
    	ACALL 	I2C_TAKT	;
    	RET
    ;************************************************************************
    I2C_STOP:
    	CLR 	SDA
    	ACALL 	I2C_TAKT
    	SETB 	SCL		;PRZY USTAWIONYM SCL USTAW LINIE SDA->
    	ACALL 	I2C_TAKT	;TO JEST WARUNEK STOPU DLA I2C
    	SETB 	SDA 
    	RET
    ;*************************************************************************
    I2C_TAKT:			;TAKT ZEGARA I2C 6us DLA KWARCA 24MHz->
    	NOP			;(MIN. 4us- Z APLIKACJI)
    	NOP
    	NOP
    	NOP
    	NOP
    	NOP
    	NOP
    	NOP
    	NOP
    	NOP
    	NOP
    	NOP
    	RET
    ;*************************************************************************
    WAIT_10MS:
    	MOV R1, #40
    	MOV R3, #255
    MS10:	DJNZ R3, $
    	DJNZ R1, MS10
    	RET
    ;*************************************************************************
  • REKLAMA
  • #2 2787313
    zumek
    Poziom 39  
    Posty: 3352
    Pomógł: 695
    Ocena: 52
    
    ;*************************************************************************
    LOAD:
    	CALL I2C_STOP		;NA WSZELKI WYPADEK, ZEBY I2C START BYLO PRAWIDŁOWE
    	CALL I2C_START
    	MOV A, #160		;ADRES EEPROMA
    	CALL I2C_WRITE
    	MOV ERR_I2C, C
            jc obsluga_bledu        ; to bym dodał
    	CLR C
    ...
    I2C_WRITE:			;ZAPISUJE NA I2C ZAWARTOSC ACC. ODDAJE ACK W CY
    	ACALL 	I2C_TAKT	;OPUZNIENIE...
    	SETB 	SCL	;WYSTAWIENIE IMPULSU ACK
    ;za mało czasu na odpowiedź - dodałbym
            acall i2c_takt
    	MOV 	C, SDA	;PRZEPISANIE IMPULSU ACK DO CY->
    	CLR 	SCL		;CY=0 TO SLAVE ODPOWIEDZIAŁ
    	RET		;CY=1 TO SLAVE NIE ODPOWIEDZIAŁ
    


    Piotrek
  • REKLAMA
  • #3 2787845
    bolek
    Poziom 35  
    Posty: 4099
    Pomógł: 86
    Ocena: 299
    dzięki.

    obsługe błedu mam, C jest przepisywane do err_i2c i dalej obrabiane.
    Powstawiałem większe zwłoki czasowe i coś się ruszyło. Tak ogólnie to zapomniałem dodać że kwarc ma 24MHz, tak więc cykl trwa 500ns
    Tak na szybko to powiem że nie prawidłowo zczytuje mi ostatni bajt "oczka" - niekiedy się zapisze poprawnie, niekiedy nie

    Działam dalej
  • REKLAMA
  • #4 2787926
    Skubik
    Poziom 15  
    Posty: 106
    Pomógł: 12
    Ocena: 2
    Załwazyłem cos i mam jedno ale mianowicie jak odczytujesz bajt po bajcie z pamieci na I2C to w procedurze odczytu nie dawaj bitu potwierdzenia odbioru. Bit potwierdzenia odbioru daj dopiero przy ostatnim bajcie jaki czytasz i zaraz po nim bit stopu.
  • REKLAMA
  • #5 2787953
    bolek
    Poziom 35  
    Posty: 4099
    Pomógł: 86
    Ocena: 299
    tak też jest zrobione, zauważ że po wywołaniu adresu (do odczytu) 161 mam skasowaną flage C, która używam jako NACK/ACK. Jest ona ustawiona dopiero na ostatnim bajcie.

    --------------------------------------------------------------------------------
    coś to kiepsko widze, jeśli ktoś ma pewne procedury to prosił bym podesłać na bolo(_at_)poczta.ox.pl
  • #6 2789551
    bolek
    Poziom 35  
    Posty: 4099
    Pomógł: 86
    Ocena: 299
    Doprowadziłem do stanu w którym pamięć trzyma dane do puki nie odłącze zasilania. Teraz już nawet zapisuje pojedyńczo każdy bajt.
    Po zaniku zasilania, niktóre komurki przyjmują dziwne, aczkolwiek stałe wartości. przekładam pamięci w podstawce i nic.
    Zawsze gdy dokonam zapisu natychmiast robie odczyt i wartości są takie jakie chciałem zapisać, jak zrobie reset też wczyta dobrze. Tylko jak wyłącze zasilanie dzieją się cuda...

    Ktoś ma jakąś teorie?
  • #7 7988814
    ravm0
    Poziom 2  
    Posty: 2
    Witam! Odświeże temat. Też mam ten problem, że odczytuje mi z pamięci same wartości 255. Ma ktoś pomysł jaka jest tego przyczyna?

    Program:
    
    
    SDA EQU P2.4
    SCL EQU P2.3
    LED EQU P2.7
    
    I2C_fault bit 40h
    I2C_busy bit 41h
    I2C_no_ack bit 42h
    I2C_ostatni_bajt bit 43h
    
    licznik_bitow_I2C equ R0
    
    org 0H
    
    LJMP START
    
    
    org 100H
    START:
    	LCALL delay
    	LCALL delay
    	LCALL delay
    	LCALL delay
    	LCALL delay
    
    ;zapisywanie do eepromu
    	LCALL start_I2C
    	MOV A,#10101000B 		;ADRES EEPROM/ZAPIS
    	LCALL zapis_bajtu_I2C
    	MOV A,#00000100B 		;ADRES STRONY
    	LCALL zapis_bajtu_I2C
    	MOV A,#00001111B 		;DANE
    	LCALL zapis_bajtu_I2C
    	LCALL stop_I2C
    
    	LCALL delay
    	LCALL delay
    
    ;odczytanie z eepromu
    	LCALL start_I2C
    	MOV A,#10101001B		;ADRES EEPROM/ODCZYT 
    	LCALL zapis_bajtu_I2C
    	LCALL odczyt_bajtu_I2C
    	LCALL stop_I2C
    
    	CJNE A, #11111111B, LOOPEK	   ;POROWNANIE DANYCH, w akumulatorze 
                                                       ;jest wartosc oczytana z eepromu
    	CLR LED				   ;JESLI ROWNE TO ZAPAL DIODE
    
    
    LOOPEK:
    	SJMP LOOPEK
    
    ;************************************
    wait_5us:
    
    	NOP
    	NOP
    	RET
    
    SCL_high:                     ;testowanie linii scl
    	SETB SCL
    	JNB SCL, $           ;oczekiwanie na rzeczywisty wysoki stan  scl
    	RET
    
    stop_I2C:
    	CLR SDA
    	LCALL SCL_high
    	LCALL wait_5us
    	SETB SDA               ;zbocze narastajace sda przy wysokim scl
    	LCALL wait_5us
    	CLR I2C_busy
    	RET
    
    zapis_bajtu_I2C:
    	MOV licznik_bitow_I2C, #8
    wr_loop:
    	RLC A                           ;
    	MOV SDA, C                  ;ladowanie na sda kolejnych bitow z akumulatora
    	LCALL wait_5us
    	LCALL SCL_high             ;ustawienie wysokiego scl, czyli poczatek
                                              ;transmisji bitu
    	LCALL wait_5us
    	CLR SCL
    	LCALL wait_5us
    	DJNZ licznik_bitow_I2C, wr_loop       ;petla dla 8 bitow
    
    	SETB SDA
    	LCALL SCL_high             ;poczatek odbierania ack
    	LCALL wait_5us
    	JNB SDA, no_wr_ACK      ;jesli brak ack to ustaw znacznik
    	SETB I2C_no_ack
    no_wr_ACK:
    	CLR SCL
    	LCALL wait_5us
    	RET
    
    start_I2C:
    	SETB I2C_busy
    	CLR I2C_no_ack
    	CLR I2C_fault
    	JNB SCL, fault
    	JNB SDA, fault
    	CLR SDA            ;sygnal startu (zbocze opadajace sda przy wysokim scl)
    	LCALL wait_5us
    	CLR SCL
    	LCALL wait_5us
    
    	RET
    fault:
    	SETB I2C_fault
    	RET
    
    odczyt_bajtu_I2C:
    	MOV licznik_bitow_I2C, #8
    rd_loop:
    	LCALL SCL_high
    	LCALL wait_5us
    	MOV C, SDA                      ;zapisanie wartosci z linii sda do C
    	RLC A                               ;zaladowanie C do akumulatora
    	LCALL wait_5us
    	CLR SCL
    	LCALL wait_5us
    	DJNZ licznik_bitow_I2C, rd_loop      ;petla dla 8 bitow
    
    	SETB SDA                      ;wysoki stan sda przy przesylaniu ACK czylih
                                               ;brak potwiedzenia
    	LCALL wait_5us
    	LCALL SCL_high
    	LCALL wait_5us
    	CLR SCL
    	SETB SDA
    	LCALL wait_5us
    	RET
    
    

Podsumowanie tematu

✨ Problem dotyczy błędnego zapisu i odczytu pamięci EEPROM 24C02 za pomocą asemblera dla mikrokontrolera z rodziny 8051 (ASM51). Odczyt zwraca stale wartość 255, co sugeruje, że zapis nie przebiega poprawnie. Noga WP (Write Protect) jest podłączona do masy, a linie SDA i SCL mają rezystory podciągające. Procedury I2C działały poprawnie z innymi układami, jednak tutaj pojawiają się problemy. W kodzie asemblera zastosowano standardowe procedury startu, zapisu i odczytu na magistrali I2C, z obsługą bitów ACK/NACK. Zauważono, że przy odczycie bajtów z EEPROM bit potwierdzenia odbioru (ACK) powinien być ustawiany tylko przy ostatnim bajcie, co jest spełnione w implementacji. Po zwiększeniu opóźnień czasowych komunikacja zaczęła działać lepiej, jednak problem z nieprawidłowym odczytem ostatniego bajtu nadal występuje. Po zapisaniu danych i natychmiastowym odczycie wartości są poprawne, a także po resecie mikrokontrolera, natomiast po zaniku zasilania niektóre komórki EEPROM przyjmują nieoczekiwane wartości. Przekładanie pamięci w podstawce nie rozwiązuje problemu. W dyskusji zasugerowano dodanie dodatkowej obsługi błędów i zwiększenie opóźnień w procedurach I2C, aby zapewnić poprawne działanie magistrali i synchronizację z pamięcią EEPROM 24C02 pracującą przy kwarcu 24 MHz (cykl 500 ns).
REKLAMA