Od niedawna mam mały problem z zapisem do eepromu typu 24c64. Odczyt działa mi elegancko, ale z zapisem mam już mały kłopot. Próbowałem różnych podejść do sprawy, ale wszystko poszło na marne. Najlepiej zobrazuje to kod programu:
Proszę o pomoc, bo już nie mam co wymyślić.
O co tak na prawdę mi chodzi. Po wysłaniu porcji danych (jednego bajtu) powinienem otrzymać od eepromu potwierdzenie ACK. W dokumentacji Atmega8 zobaczyłem, że powinienem otrzymać kod od interfejsu 0x28, a otrzymuję 0x20. Wygląda na to, że wysyłam jeszcze raz SLA+W, a to nie prawda.
Kod główny programu:
Kod: Zaznacz cały
.INCLUDE "m8def.inc"
;makra
.MACRO twi_check_error
;przesowamy w prawo o 2 miejsca, aby nie brac pod uwage prescalera
in TWI_REGISTER, TWSR
cbr TWI_REGISTER, (1 << TWPS1) | (1 << TWPS0)
cpi TWI_REGISTER, @0
brne twi_error
.ENDMACRO
.dseg
.def TWI_REGISTER = r25
.cseg
.org 0x000
rjmp reset
reset:
LDI R16, HIGH( RAMEND)
OUT SPH, R16
LDI R16, LOW( RAMEND)
OUT SPL, R16
clr r16
ldi r16, (1 << TWPS0)
out TWSR, r16
ldi r16, 20
out TWBR, R16
sbi PORTC, PC5
sbi PORTC, PC4
rcall twi_start
;error ?
twi_check_error 0x08
;adres urzadzenia + zapis
ldi TWI_REGISTER, 0x50 << 1 ; + 0
rcall twi_send_data
;error ?
twi_check_error 0x18
;msb
ldi TWI_REGISTER, 0x00
rcall twi_send_data
;error ?
twi_check_error 0x28
;lsb
ldi TWI_REGISTER, 0x00
rcall twi_send_data
;error ?
twi_check_error 0x28
ldi r17, 0x00
zapis:
;zapisujemy bajt
ldi TWI_REGISTER, 0x61
rcall twi_send_data
twi_check_error 0x28
inc r17
cpi r17, 20
brne zapis
rcall twi_stop
;zapetlamy
petla:
rjmp petla
;blad na interfejsie twi
twi_error:
mov EEPROM_DATA, TWI_REGISTER
rcall write_to_eeprom
rjmp petla
.INCLUDE "..\biblioteki\twi.inc"
Kod: Zaznacz cały
;wysylamy dane
twi_send_data:
;zapis danych
out TWDR, TWI_REGISTER
ldi TWI_REGISTER, (1 << TWINT) | (1 << TWEN) | (1 << TWEA)
;wysylamy dane na zlacze
out TWCR, TWI_REGISTER
rcall twi_busy
;konczymy wysylanie danych
ret
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;operacja odcytywania bajtu
twi_read_data:
;dajemy sygnal do odczytu
ldi TWI_REGISTER, (1 << TWINT) | (1 << TWEN) | (1 << TWEA)
out TWCR, TWI_REGISTER
rcall twi_busy
;odczytujemy dane
in TWI_REGISTER, TWDR
ret
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;wysylanie STARTU
twi_start:
ldi TWI_REGISTER, (1 << TWINT) | (1 << TWSTA) | (1 << TWEN) | (1 << TWEA)
out TWCR, TWI_REGISTER
rcall twi_busy
ldi TWI_REGISTER, (0 << TWINT) | (0 << TWSTA) | (1 << TWEN) | (1 << TWEA)
out TWCR, TWI_REGISTER
;koniec, powracamy
ret
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
twi_stop:
ldi TWI_REGISTER, (1 << TWSTO) | (1 << TWEN) | (1 << TWINT)
;wysylamy nasze ustawienia
out TWCR, TWI_REGISTER
;wylaczamy interfejs twi
ldi TWI_REGISTER, 0 << TWEN
out TWCR, TWI_REGISTER
;wyslano stop, powracamy do programy
ret
;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
;sprawdznaie czy interfejs TWI jest zajety
twi_busy:
;wczytanie rejestru kontrolnego
in TWI_REGISTER, TWCR
;porownanie bitu przerwania TWINT, jesli 1
sbrs TWI_REGISTER, TWINT
;to omijamy skok do ponownego sprawdzenia
rjmp twi_busy
;powrot
ret
[ Dodano: 2007-11-14, 20:11 ]
Czy mógłby mi ktoś pomóc z problemem?
Na internecie nie znalazłem przykładu w asemblerze do obsługi sprzętowego eepromu.