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

odczyt i zapis w zewnętrznym eepormie 512k

kamil1cos7 16 Sty 2012 10:51 1091 8
REKLAMA
  • #1 10404467
    kamil1cos7
    Poziom 14  
    Cześć, chciałem sobie podłączyć zewnętrzny eeprom do atmega8 przez interfejs TWI, napisałem procedury ale niestety nie działają i nie wiem w czym jest problem.
    Linie NC eepromu pozostawiłem bez połączenia, A1 i A0 zwarłem do masy, piny te służą do zaadresowania max 4 kostek eeprom na interfejsie TWI i tutaj dla pewności zapytam czy jeśli zwarłem je do masy to później w programie kiedy jako pierwszy bajt wysyłam adres urządzenia to adres tej kostki w miejscach przeznaczonych na A1 i A0 będzie '00', czy tak?? SDA i SCL przez 10k do zasilania, Vcc i GND to wiadomo, a WP do masy...

    Moje procedury:
    
    ;********************************************************************
    ;Ustawienie zegara Fscl = 100kHz
    ;Wzór na stronie 167 noty aplikacyjnej Atmega8
    
    sbi DDRC, 4
    sbi DDRC, 5		;piny TWI jako wyjścia
    
    ldi r16, 32
    out TWBR, r16		
    
    ldi r16, 0b00000000
    out TWSR, r16			
    
    ;********************************************************************
    
    ;***********************************************************************
    ;Procedura transmisji sygnalu 'start'
    
    twi_start:	ldi r17, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
    			out TWCR, r17
    			
    			wait_twint:
    				in r17, TWCR
    				sbrs r17, TWINT
    			rjmp wait_twint 
    			
    			ret
    			
    ;Procedura transmisji sygn 'stop'		
    
    twi_stop:	ldi r17, (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
    			out TWCR, r17
    				
    			wait1_twint:
    				in r17, TWCR
    				sbrc r17, TWINT
    			rjmp wait1_twint 
    			
    			ret
    			
    ;Procedura wyslania bajtu danych
    ;	parametr	r16 - dana wejsciowa
    
    twiwrite_r16:	ldi r17, (1<<TWINT)|(1<<TWEN)
    				out TWDR, r16
    				out TWCR, r17
    				
    				wait2_twint:
    					in r17, TWCR
    					sbrs r17, TWINT
    				rjmp wait2_twint 
    
    				ret
    
    ;Procedura odczytu bajtu danych
    ;	parametr	r16 - dana wyjsciowa
    
    twiread_ACK_r16:	ldi r18, (1<<TWINT)|(1<<TWEN)|(1<<TWEA)
    					out TWCR, r18
    				
    					wait3_twint:
    						in r17, TWCR
    						sbrs r17, TWINT
    					rjmp wait3_twint
    				 
    					in r16, TWDR
    				
    					ret
    
    twiread_noACK_r16:	ldi r18, (1<<TWINT)|(1<<TWEA)
    					out TWCR, r18
    					
    					wait4_twint:
    						in r17, TWCR
    						sbrs r17, TWINT
    					rjmp wait4_twint
    				 
    					in r16, TWDR
    				
    					ret
    					
    ;***********************************************************************
    ;Procedury obslugi zewnetrzengo EEPROM 512kb
    
    ;procedura zapisu bajtu pod zadany adres
    ;parametry	r16	- dana wejściowa	; X - adres	do zapisu
    
    twiwrite16_tX:	push r16
    					rcall twi_start
    				
    					ldi r16, 0b10100000
    					rcall twiwrite_r16
    				
    					mov r16, XH
    					rcall twiwrite_r16
    
    					mov r16, XL
    					rcall twiwrite_r16
    				
    					pop r16
    					rcall twiwrite_r16
    				
    					rcall twi_stop
    					ret
    
    ;procedura odczutu bajtu z podanego adresu
    ;parametr: 	r16 - odczytany bajt	X - adres do odczytu
    
    twireadr16_fX:		rcall twi_start
    				
    					ldi r16, 0b10100000
    					rcall twiwrite_r16
    					
    					mov r16, XH
    					rcall twiwrite_r16
    
    					mov r16, XL
    					rcall twiwrite_r16
    
    					rcall twi_start
    					ldi r16, 0b10100001
    					rcall twiwrite_r16
    				
    					rcall twiread_noACK_r16
    					rcall twi_stop
    				
    					ret
    				
    


    Aby sprawdzić działanie chciałem najpierw zapisać bajt pod jakiś adres a potem go odczytać spod tego samego adresu ale się nie udało...
    
    	ldi r16, 234
    	ldiw X, 0
    	rcall twiwrite16_tX
    	
    	ldiw X, 0
    	rcall twireadr16_fX
    

    I potem miało się to wyświetlić na LCD ale niestety efektem był migający kursor, procedury obsługi LCD mi działają na 100% więc nie w tym problem.

    Zamieszczam jeszcze z noty eepromu przebiegi zapisu i odczytu:

    Dodano po 2 [minuty]:

    Znajduja się tutaj przebiegi zapisu, odczytu i format pierwszego bajtu.

    Wszelkie pomysły i sugestie bardzo wskazane...
    Z góry dzięki,
    Pozdrawiam
  • REKLAMA
  • #2 10405021
    rad231276
    Poziom 12  
    Może jakiś schemat byś też dodał... Najpierw należy mieć coś na 100% działającego układ
    albo sprawdzony soft - w przeciwnym wypadku nigdy się nie dojdzie co jest nie tak...
  • REKLAMA
  • #3 10406829
    kamil1cos7
    Poziom 14  
    hmm schemat... w schemacie jest tylko połączenie odpowiednie pinów zasilania i masy, PC0-PC3 do wyświetlacza lcd, PD0 i PD1 też do wyświetlacza i one są przeznaczone na RS i EN wyświetlacza lcd.
    Tak złożona całość działa i wyświetla to co trzeba... więc na pewno nie ma w tym błędu. EEPROM podłączony jest tak jak wcześniej napisałem. Całość jest na płytce stykowej.
  • REKLAMA
  • #4 10408296
    kiziu13
    Poziom 17  
    Co do adresu, to tak, stan na pinach adresowych przekłada się bezpośrednio na stan odpowiadających im bitów w adresie.

    W oczy rzucił mi się sposób ładowania adresu. DS milczy, jakoby dało się załadować stałą do pary rejestrów (ldiw). Najpewniej będziesz musiał ładować go po bajcie. Po drugie, nie wiem po co masz pętlę czekającą po wysłaniu sygnału STOPu. Co prawda wielu kodów nie widziałem, ale we wszystkich, które miałem okazję przejrzeć, końcem było po prostu wysłanie sygnału STOP bez czekania po nim.
  • #5 10409169
    kamil1cos7
    Poziom 14  
    Ale 'ldiw' to jest macro;) Później jak widać w kodzie, wysyłam osobno najpierw starszy a potem młodszy bajt adresu.
    Znalazłem dwa błędy w tym swoim kodzie jak na razie...
    Pierwszy w procedurze odczytu bez ACK, poprawiona wygląda tak:
    twiread_noACK_r16:	ldi r17, (1<<TWINT)|(1<<TWEN)
    					out TWCR, r17
    		
    					wait4_twint:
    						in r17, TWCR
    						sbrs r17, TWINT
    					rjmp wait4_twint
    				 
    					in r16, TWDR
    				
    					ret


    I drugi błąd w przesyłaniu bajtu danych:
    twiwrite_r16:	out TWDR, r16
    				ldi r17, (1<<TWINT)|(1<<TWEN)|(1<<TWEA)
    				out TWCR, r17
    							
    				wait2_twint:
    					in r17, TWCR
    					sbrs r17, TWINT
    				rjmp wait2_twint 
    
    				ret


    I teraz sytuacja się nieco zmieniła, wydaje mi się że na lepsze... Po wykonaniu programu na wyświetlaczu otrzymuję liczbę 255... Teraz pytanie o czym to świadczy. Moim zdaniem działa procedura odczytu, bo z eepromem zewnętrznym jest wydaje mi się tak samo jak z tym wbudowanym w uP i komórki pamięci przed zapisem mają wartość FF czyli 255, więc odczytuje tylko czy z podanego adresu czy z jakiegoś innego to jeszcze nie wiadomo... Możliwe też że, działa procedura zapisu i odczytu ale adresowania jest złe w nich... hmmm
    Proszę o kolejne sugestie;)
  • REKLAMA
  • #6 10409224
    kiziu13
    Poziom 17  
    Co do odczytu, masz rację, umknął mi brak włączenia zamiast ACK, ale zapis masz źle. Przy zapisie nie wysyła się ACK, wysyła go zawsze odbiorca, czyli w wypadku zapisu kostka EEPROMu.
  • #7 10409255
    kamil1cos7
    Poziom 14  
    aha, czyli tam w procedurze zapisu powinno byc:

    ldi r17, (1<<TWINT)|(1<<TWEN)

    Zmieniłem i nadal na lcd 255...

    Dodano po 16 [minuty]:

    haha teraz to dopiero jest ciekawie;) Sęk tkwi w moim sygnale 'STOP', po pierwsze nie powinien on wyglądać tak jak wyżej napisałem tylko tak:

    twi_stop:	ldi r17, (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
    			out TWCR, r17
    				
    			wait1_twint:
    				in r17, TWCR
    				sbrc r17, TWSTO
    			rjmp wait1_twint 
    			
    			ret

    Przypadkiem odkryłem że jeśli użyję takiej formy przy zapisie i odczycie to działa zapis a odczyt nie... Jeśli zaś użyje formy bez pętli to działa odczyt a zapis nie:P
    hehe wyjście z sytuacji jest teraz proste... ale niech mi ktoś wyjaśni czemu jest tak a nie inaczej:P
  • #8 10409375
    kiziu13
    Poziom 17  
    Sprawa wygląda tak. Nie ma żadnej pętli po STOPie, wysyłasz poprawny sygnał i kończysz działanie, czyli procedura wygląda tak:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    Problem tkwi w czasie zapisu. Zgodnie z rysunkiem 3 na stronie 7 (http://www.atmel.com/dyn/resources/prod_documents/doc1116.pdf) należy odczekać kilka/kilkanaście milisekund, ażeby kostka mogła wykonać poprawny cykl zapisu (t_WR).
  • #9 10409431
    kamil1cos7
    Poziom 14  
    Właśnie doszedłem do tego... W nocie EEPROM-u jest to nawet napisane. Dokładnie że zapis będzie trwał max 5ms...

    Tutaj gotowe, działające procedury jakby ktoś chciał:
    ;*******************************************************************
    ;Ustawienie zegara Fscl = 100kHz
    ;Wzór na stronie 167 noty aplikacyjnej Atmega8
    
    sbi DDRC, 4
    sbi DDRC, 5		;piny TWI jako wyjścia
    
    ldi r16, 32
    out TWBR, r16		
    
    ldi r16, 0b00000000
    out TWSR, r16			
    
    ;********************************************************************
    
    ;***********************************************************************
    ;Procedura transmisji sygnalu 'start'
    
    twi_start:	ldi r17, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
    			out TWCR, r17
    			
    			wait_twint:
    				in r17, TWCR
    				sbrs r17, TWINT
    			rjmp wait_twint 
    			
    			ret
    			
    ;Procedura transmisji sygn 'stop'		
    
    twi_stop:	ldi r17, (1<<TWINT)|(1<<TWEN)|(1<<TWSTO)
    			out TWCR, r17
    			
    			ret
    			
    ;Procedura wyslania bajtu danych
    ;	parametr	r16 - dana wejsciowa
    
    twiwrite_r16:	out TWDR, r16
    				ldi r17, (1<<TWINT)|(1<<TWEN)
    				out TWCR, r17
    							
    				wait2_twint:
    					in r17, TWCR
    					sbrs r17, TWINT
    				rjmp wait2_twint 
    
    				ret
    
    ;Procedura odczytu bajtu danych
    ;	parametr	r16 - dana wyjsciowa
    
    twiread_ACK_r16:	ldi r17, (1<<TWINT)|(1<<TWEN)|(1<<TWEA)
    					out TWCR, r17
    				
    					wait3_twint:
    						in r17, TWCR
    						sbrs r17, TWINT
    					rjmp wait3_twint
    				 
    					in r16, TWDR
    				
    					ret
    
    twiread_noACK_r16:	ldi r17, (1<<TWINT)|(1<<TWEN)
    					out TWCR, r17
    		
    					wait4_twint:
    						in r17, TWCR
    						sbrs r17, TWINT
    					rjmp wait4_twint
    				 
    					in r16, TWDR
    				
    					ret
    					
    ;***********************************************************************
    ;Procedury obslugi zewnetrzengo EEPROM 512kb
    
    ;procedura zapisu bajtu pod zadany adres
    ;parametry	r16	- dana wejściowa	; X - adres	do zapisu
    
    twiwriter16_tX:		rcall twi_start
    					
    					push r16
    				
    					ldi r16, 0b10100000
    					rcall twiwrite_r16
    				
    					mov r16, XH
    					rcall twiwrite_r16
    
    					mov r16, XL
    					rcall twiwrite_r16
    				
    					pop r16
    					rcall twiwrite_r16
    
    					rcall twi_stop	
    					
    					ldi r16, 5
    					rcall wait_ms		
    					
    					ret
    
    ;procedura odczutu bajtu z podanego adresu
    ;parametr: 	r16 - odczytany bajt	X - adres do odczytu
    
    twireadr16_fX:		rcall twi_start
    
    					ldi r16, 0b10100000
    					rcall twiwrite_r16
    					
    					mov r16, XH
    					rcall twiwrite_r16
    
    					mov r16, XL
    					rcall twiwrite_r16
    
    					rcall twi_start
    					ldi r16, 0b10100001
    					rcall twiwrite_r16
    		
    					rcall twiread_noACK_r16
    
    					rcall twi_stop		
    					
    					ret
    				
    


    Dziękuje wszystkim za pomoc;)

    Pozdrawiam
REKLAMA