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

[ATmega32] problem z transmisją TWI/I2C

ceZar PK 17 Sie 2008 20:13 2244 2
REKLAMA
  • #1 5448289
    ceZar PK
    Poziom 11  
    Witam.
    Natrafiłem na pewien uciążliwy problem... W swoim projekcie realizuję transmisję przez TWI między AVRem a zegarem czasu rzeczywistego DS1307. Wykorzystuję sprzętową obsługę TWI. Transmisję w obie strony, czyli zapis czasu do DS1307 oraz późniejsze jego odczytywanie, udało mi się zrealizować i jako tako to działało. Tylko że wszystko działo się to jeszcze póki ATmega32 pracowała z domyślnym zegarem czyli wewnętrznym oscylatorem 1MHz. Gdy zaprogramowałem Fuse Bity tak aby umożliwić pracę z zewnętrznym rezonatorem 16MHz transmisja przestała działać. Transmisja powinna działać z częstotliwością 100kHz i wiem że powinno się ustawiać rejestry TWBR i preskaler w TWSR tak aby tą częstotliwość osiągnąć. Jednak wcześniej (przed programowaniem Fuse Bitów) zapomniałem o tym i działało a teraz ustawiłem TWBR na 72, czyli 16Mhz/(16+2*72*1)=100kHz i niby powinno działać a tak nie jest. Ma ktoś pomysł co może być nie tak? Program piszę w asemblerze. Poniżej zamieszczam moją procedurę zapisu:
    ;wysłanie danych - tryb Master Transmitter
    
    i2c_write:	LDI 	R16,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)		;sekwencja startowa
    			OUT		TWCR, R16				
    
     wait1:		IN		R16,TWCR			;oczekiwanie na ustawienie flagi TWINT
    			SBRS	R16,TWINT
    			RJMP	wait1
    			
    			IN		R16,TWSR			;sprawdzenie poprawności statusu startu
    			ANDI	R16,0xF8
    			CPI		R16,START
    			BRNE	error_w
    
    			LDI 	R16,SLA_W			;wysłanie Slave Address + W
    			OUT 	TWDR,R16
    			LDI 	R16,(1<<TWINT)|(1<<TWEN)
    			OUT 	TWCR,R16
    
     wait2:		IN		R16,TWCR			;oczekiwanie na ustawienie flagi TWINT
    			SBRS 	R16,TWINT
    			RJMP 	wait2
    
    			IN		R16,TWSR			;sprawdzenie poprawności statusu SLA_W
    			ANDI	R16,0xF8
    			CPI		R16,MT_SLA_ACK
    			BRNE	error_w
    
    			MOV 	R16,WORD_ADDR		;wysłanie adresu wskaźnika dla DS1307
    			OUT 	TWDR,R16
    			LDI 	R16,(1<<TWINT)|(1<<TWEN)
    			OUT 	TWCR,R16
    
     wait3:		IN		R16,TWCR			;oczekiwanie na ustawienie flagi TWINT
    			SBRS 	R16,TWINT
    			RJMP 	wait3
    
    			IN		R16,TWSR			;sprawdzenie poprawności statusu danych
    			ANDI	R16,0xF8
    			CPI		R16,MT_DATA_ACK
    			BRNE	error_w
    
    			MOV 	R16,DATA_W			;wysłanie bajtu danych
    			OUT 	TWDR,R16
    			LDI 	R16,(1<<TWINT)|(1<<TWEN)
    			OUT 	TWCR,R16
    
     wait4:		IN		R16,TWCR			;oczekiwanie na ustawienie flagi TWINT
    			SBRS 	R16,TWINT
    			RJMP 	wait4
    
    			IN		R16,TWSR			;sprawdzenie poprawności statusu danych
    			ANDI	R16,0xF8
    			CPI		R16,MT_DATA_ACK
    			BRNE	error_w
    
    			LDI		R16,(1<<TWINT)|(1<<TWEN)|(1<<TWSTO)		;sekwencja stop
    			OUT		TWCR,R16
    
    			RET
  • REKLAMA
  • #2 5458658
    rfhzcx
    Poziom 14  
    Sprawdź bity TWPS w status rejetrze TWI
    Być może warto tylko zmienić TWBR na 1 a zminić częstoliwość SCL poprzez zmianę bitów TWPS
    Pozdro
    KA
  • #3 5459836
    ceZar PK
    Poziom 11  
    Spróbowałem pokombinować z preskalerem ale nic z tego. Preskaler w TWSR ustawiłem na 4 a do rejestru TWBR wpisałem 18 co również powinno dać 100kHz:
    16Mhz/(16+2*18*4)=100kHz
    Nie zadziałało... Bawiłem się tez z Fuse Bitami i okazuje się że transmisja działa poprawnie dla wewnętrznego generatora 1MHz, 2MHz, 4MHz a nawet 8MHz, czyli dla każdego z możliwych wewnętrznych generatorów ATmegi. Działa nawet bez jakichkolwiek ustawień w TWSR i TWBR. Natomiast gdy ustawienia Fuse Bitów zmienie na jakikolwiek zewnętrzny rezonator kwarcowy wszystko przestaje działać:|
REKLAMA