Hallo,
ich implementiere gerade einen I2C Slave (USI) und weil ich das Rad
nicht neu erfinden will, habe ich mir die
AVR312 - Using the USI module as a I2C slave
heruntergeladen.
Im Interrupt USI_START_VECTOR macht Atmel einen busy wait:
1 | #pragma vector=USI_START_VECTOR
|
2 | __interrupt void USI_Start_Condition_ISR(void)
|
3 | {
|
4 | unsigned char tmpUSISR; // Temporary variable to store volatile
|
5 | tmpUSISR = USISR; // Not necessary, but prevents warnings
|
6 | // Set default starting conditions for new TWI package
|
7 | USI_TWI_Overflow_State = USI_SLAVE_CHECK_ADDRESS;
|
8 | DDR_USI &= ~(1<<PORT_USI_SDA); // Set SDA as input
|
9 |
|
10 | // -----------------------------------
|
11 | // BUSY - WAIT im Interrupt
|
12 | while ( (PIN_USI & (1<<PORT_USI_SCL)) & !(tmpUSISR & (1<<USIPF)) );
|
13 | // Wait for SCL to go low to ensure the "Start Condition" has completed.
|
14 | // -----------------------------------
|
15 | // If a Stop condition arises then leave the interrupt to prevent waiting forever.
|
16 | USICR = (1<<USISIE)|(1<<USIOIE)| // Enable Overflow and Start Condition Interrupt. (Keep StartCondInt to detect RESTART)
|
17 | (1<<USIWM1)|(1<<USIWM0)| // Set USI in Two-wire mode.
|
18 | (1<<USICS1)|(0<<USICS0)|(0<<USICLK)| // Shift Register Clock Source = External, positive edge
|
19 | (0<<USITC);
|
20 | USISR = (1<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)| // Clear flags
|
21 | (0x0<<USICNT0); // Set USI to sample 8 bits i.e. count 16 external pin toggles.
|
22 | }
|
Wenn ich mich da nicht täusche, dann verstöst das gegen die Haager
Landkriegsordnung....
Im Notfall, wenn es keine bessere Lösung gibt, dann müsste man noch
einen Interrupt auf diesen Flankenwechsel implementieren...
Oder hat jemand eine bessere Idee? Und/Oder vielleicht eine Lösung?
Schöne Grüße
Jens Riebold