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.
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.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
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