Hallo Ich habe hier ein ziemliches Problem mit dem TWI eines Mega8: Ein Mega32 als Master versucht etwas zu senden, doch der Slave (Mega8) reagiert nicht im geringsten. Auf dem Master wird der TWI-Interrupt erwartungsgemäss ausgelöst (START sent, NOT ACK received). Die SCL-Leitung ist zuerst auf High, nach dem Senden dauerhaft auf Low (wie zu erwarten, da noch kein STOP gesendet wurde). Auf dem Slave passiert rein gar nichts - nicht mal der TWI-Interrupt wird ausgelöst. (Dann sollte eine LED angehen und ein Zeichen übers UART gesendet werden - nix von dem passiert. Ich bin langsam ein bisschen am verzweifeln, da ich dem Problem einfach nicht auf die Schliche komme. Primäres Ziel ist nun mal, dass der TWI-Interrupt auf dem Slave ausgelöst wird. Achja: Die Schaltung sollte stimmen. (Was für Pullups sollte man am besten verwenden? 1.8k Ohm?) Gruss Michael TWI-relevante Codefragmente:
1 | struct{ |
2 | unsigned char read:1; |
3 | |
4 | char * outbuffer; |
5 | uint8_t outptr; |
6 | uint8_t outlen; |
7 | |
8 | char * inbuffer; |
9 | uint8_t inptr; |
10 | uint8_t inlen; |
11 | }i2c; |
12 | |
13 | void i2c_init(uint8_t addr){ |
14 | TWAR = (addr << 1) | 1; |
15 | TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN) | (1 << TWIE); |
16 | }
|
17 | |
18 | void i2c_setinputtarget(char * buffer[], uint8_t len){ |
19 | i2c.inbuffer = buffer; |
20 | i2c.inlen = len; |
21 | i2c.inptr = 0; |
22 | }
|
23 | |
24 | void i2c_setoutputsource(char * buffer[], uint8_t len){ |
25 | i2c.outbuffer = buffer; |
26 | i2c.outlen = len; |
27 | i2c.outptr = 0; |
28 | }
|
29 | |
30 | void i2c_received(){ |
31 | uint8_t i = 0; |
32 | for(i = 0; i < i2c.inlen; i ++) |
33 | uart_sendchar(*(i2c.inbuffer + i)); |
34 | }
|
TWI-ISR:
1 | //TWI-Interrupt
|
2 | ISR(TWI_vect){ |
3 | PORTB = 0b00000000; |
4 | uart_sendchar('x'); |
5 | uint8_t status = TWSR & 0b11111100; |
6 | TWCR &= ~((1 << TWSTA) | (1 << TWSTO)); |
7 | |
8 | // Own SLA+W received, ACK returned
|
9 | if(status == 0x60){ |
10 | i2c.inptr = 0; |
11 | TWCR |= (1 << TWINT) | (1 << TWEA); |
12 | }
|
13 | // Arbitration lost
|
14 | else if(status == 0x68){ |
15 | |
16 | }
|
17 | // General call address received, ACK returned
|
18 | else if(status == 0x70){ |
19 | |
20 | }
|
21 | // Arbitration lost
|
22 | else if(status == 0x78){ |
23 | |
24 | }
|
25 | // Data received, ACK returned
|
26 | else if(status == 0x80){ |
27 | uart_sendchar(TWDR); |
28 | if(i2c.inptr < i2c.inlen - 1){ |
29 | *(i2c.inbuffer + i2c.inptr) = TWDR; |
30 | i2c.inptr ++; |
31 | TWCR |= (1 << TWINT) | (1 << TWEA); |
32 | }
|
33 | else{ |
34 | *(i2c.inbuffer + i2c.inptr) = TWDR; |
35 | i2c.inptr ++; |
36 | TWCR |= (1 << TWINT); |
37 | TWCR &= ~(1 << TWEA); |
38 | }
|
39 | }
|
40 | // Data received, NOT ACK returned
|
41 | else if(status == 0x88){ |
42 | *(i2c.inbuffer + i2c.inptr) = TWDR; |
43 | TWCR |= (1 << TWINT) | (1 << TWEA); |
44 | i2c_received(); |
45 | }
|
46 | // General-Call Data received, ACK returned
|
47 | else if(status == 0x90){ |
48 | |
49 | }
|
50 | // General-Call Data received, NOT ACK returned
|
51 | else if(status == 0x98){ |
52 | |
53 | }
|
54 | // STOP or REPEATED START condition received
|
55 | else if(status == 0xA0){ |
56 | TWCR |= (1 << TWINT) | (1 << TWEA); |
57 | }
|
58 | // SLA+R received, ACK returned
|
59 | else if(status == 0xA8){ |
60 | i2c.outptr = 0; |
61 | if(i2c.outptr < i2c.outlen - 1){ |
62 | TWDR = *(i2c.outbuffer + i2c.outptr); |
63 | i2c.outptr ++; |
64 | TWCR |= (1 << TWINT) | (1 << TWEA); |
65 | }
|
66 | else{ |
67 | TWDR = *(i2c.outbuffer + i2c.outptr); |
68 | TWCR &= ~(1 << TWEA); |
69 | TWCR |= (1 << TWINT); |
70 | }
|
71 | }
|
72 | // Arbitration lost
|
73 | else if(status == 0xB0){ |
74 | |
75 | }
|
76 | // Data byte transmitted, ACK received
|
77 | else if(status == 0xB8){ |
78 | if(i2c.outptr < i2c.outlen - 1){ |
79 | TWDR = *(i2c.outbuffer + i2c.outptr); |
80 | i2c.outptr ++; |
81 | TWCR |= (1 << TWINT) | (1 << TWEA); |
82 | }
|
83 | else{ |
84 | TWDR = *(i2c.outbuffer + i2c.outptr); |
85 | TWCR &= ~(1 << TWEA); |
86 | TWCR |= (1 << TWINT); |
87 | }
|
88 | }
|
89 | // Data byte transmitted, NOT ACK received
|
90 | else if(status == 0xC0){ |
91 | TWCR |= (1 << TWINT) | (1 << TWEA); |
92 | }
|
93 | // Last data byte transmitted (TWEA = 0), ACK received
|
94 | else if(status == 0xC8){ |
95 | |
96 | }
|
97 | }
|
Hauptprogramm:
1 | void main(){ |
2 | |
3 | DDRB = 0b00000010; |
4 | |
5 | PORTB = 0b00000010; |
6 | |
7 | uart_init(); |
8 | |
9 | sei(); |
10 | |
11 | char inbuffer[16]; |
12 | char outbuffer[16]; |
13 | |
14 | uart_sendchar('h'); |
15 | i2c_init(0); |
16 | i2c_setinputtarget(&inbuffer, 16); |
17 | i2c_setoutputsource(&outbuffer, 16); |
18 | |
19 | uint32_t cnt = 0; |
20 | |
21 | while(1){ |
22 | asm volatile("nop"); |
23 | if(flags.uart_received){ |
24 | sensor_capture(); |
25 | PORTB = (~(PORTB)) & (0b00000010); |
26 | flags.uart_received = 0; |
27 | }
|
28 | if(flags.datacapture_ready){ |
29 | sensor_transmit(); |
30 | flags.datacapture_ready = 0; |
31 | }
|
32 | }
|
33 | }
|