Ich habe da mal eine Verständnisfrage zu der USI Stop detection. Ich bin gerade dabei den Attiny2313 als I2C Slave zu programmieren und da ist mir etwas aufgefallen was ich nicht verstehe, was ich aber in vielen anderen Quellcodes schon gefunden habe.
Wenn man ein Byte vom Master empfängt dann läd man den counter je erst mit 0x0E (Bei positiv und negativer flanken erkennung). Nach dem nächsten Counter Overflow prüft man die USISIF (Start-Flag) und die USIPF (Stop-Flag) um auf einen eventuellen Repeated Start oder eine Stop Sequenz zu prüfen.
Nun meine Frage. Die Stop Sequenz dürfte man doch so garnicht erkennen oder doch? Da eine Stopsequenz doch nur eine positive Flanke an SCL erzeugt oder lieg ich da falsch? SCL geht auf high und während SCL high ist geht SDA auf high. Das war es doch mit der Stop Sequenz. Die 2te Flanke um den Counter zum überlaufen zu bringen taucht doch nie auf.
Code:
.equ SDA = PB5
.equ SCL = PB7
.def TEMP = R16
USI_I2C_INIT: push TEMP
in TEMP,DDRB
andi TEMP,0x5F
out DDRB,TEMP
in TEMP,PORTB
andi TEMP,0x5F
out PORTB,TEMP
clr TEMP
ldi TEMP,1<<USISIE|0<<USIOIE|1<<USIWM1|1<<USIWM0|1<<USICS1
out USICR,TEMP
ldi TEMP,0x0F
out USISR,TEMP
pop TEMP
ret
USI_I2C_CONTINUE: push TEMP
ori TEMP,(1<<USISIF) + (1<<USIOIF) + (1<<USIPF) + 0x00
out USISR,TEMP
_usi_i2c_continue_wait: sbis USISR,USIOIF
rjmp _usi_i2c_continue_wait
pop TEMP
ret
USI_I2C_CHECK_STOP: clr TEMP
sbic USISR,USIPF
sbr TEMP,0
ret
USI_I2C_CHECK_START: clr TEMP
sbic USISR,USISIF
sbr TEMP,0
ret
USI_I2C_SEND_ACK: push TEMP
sbi DDRB,SDA
ldi TEMP,0x0E
rcall USI_I2C_CONTINUE
cbi DDRB,SDA
pop TEMP
ret
USI_I2C_SEND_BYTE_ACK: rcall USI_I2C_SEND_BYTE
ldi TEMP,0x0E
rcall USI_I2C_CONTINUE
clr TEMP
sbis USIDR,0
sbr TEMP,0
ret
USI_I2C_SEND_BYTE: out USIDR,TEMP
sbi DDRB,SDA
ldi TEMP,0x00
rcall USI_I2C_CONTINUE
cbi DDRB,SDA
ret
USI_I2C_READ_BYTE_ACK: rcall USI_I2C_READ_BYTE
cpi TEMP,0x00
brne _usi_i2c_read_byte_ack_2
_usi_i2c_read_byte_ack_1: rcall USI_I2C_SEND_ACK
_usi_i2c_read_byte_ack_2: ret
USI_I2C_READ_BYTE: clr TEMP2
ldi TEMP,0x0E
rcall USI_I2C_CONTINUE
rcall USI_I2C_CHECK_STOP
sbrc TEMP,0
rjmp _usi_i2c_read_byte_2
rcall USI_I2C_CHECK_START
sbrs TEMP,0
rjmp _usi_i2c_read_byte_1
ldi TEMP,0x02
rjmp _usi_i2c_read_byte_2
_usi_i2c_read_byte_1: ldi TEMP,0x02
rcall USI_I2C_CONTINUE
in TEMP2,USIDR
clr TEMP
_usi_i2c_read_byte_2: ret
HIer mal mein Quellcode für die USI Schnittstelle. In dem Unterprogramm USI_I2C_READ_BYTE liegt das was ich oben beschrieben habe. Counter auf 0x0E, testen auf Start Stop, Counter auf 0x02, Rest Byte lesen. Bei der Funktion wird bei Start und Stop erkennung einfach ein Rückgabewert in TEMP gespeichert. So dass das weitere vorgehen vom Hauptprogramm vorgenommen werden kann.
Wäre schön wenn mir jemand erklären könnte ob ich mit meinen Überlegungen oben richtig oder falsch liege. Und wenn ich richtig liege wie man dann am besten vorgeht um die Stop Sequenz richtig zu detektieren.
Vielen Dank
Lesezeichen