Hallo, ich habe ein seltsames Problem mit dem I2C-Bus für den Arduino Due im Atmel Studio. Initialisierung und Master Write funktioniert, d.h. der SLC ist richtig programmiert für 100kHz und die Master Write Routine nach dem Flußdiagramm im Datenblatt vom SAM3X8E funktioniert auch. Mit dem Skop kann ich die Signale SDA und SCL sehen und es sieht alles korrekt aus. Aber meine Master Read Routine funktioniert nicht, obwohl ich mich auch genau an das Flußdiagramm im Datenblatt halte. Hier der Code für meine Master Read Funktion, ich rufe die auf mit aw_twi_master_receive(TWI0, 0x44, 1, data); // 0x44 is slave address
1 | ////////////////////////////////////////////////////////////////////////////////
|
2 | //
|
3 | // TWI master mode: receive data
|
4 | //
|
5 | // parameters:
|
6 | // Twi* p_twi TWI0, TWI1
|
7 | // uint32_t adr slave address 0x00-0x7f
|
8 | // uint32_t no_data number of data bytes after slave address
|
9 | // uint8_t* data data array
|
10 | //
|
11 | // return:
|
12 | // uint32_t error
|
13 | //
|
14 | ////////////////////////////////////////////////////////////////////////////////
|
15 | uint32_t aw_twi_master_receive(Twi *p_twi, uint32_t adr, uint32_t no_data, uint8_t *data) |
16 | {
|
17 | uint32_t status, timeout, i; |
18 | |
19 | if (adr > 0x7f) |
20 | return 1; |
21 | if (no_data < 1) |
22 | return 1; |
23 | p_twi->TWI_CR = 0x00000024; // disable slave, enable master |
24 | p_twi->TWI_MMR = (adr << 16) | 0x00001000; // slave adr, read |
25 | if (no_data == 1) // one data byte |
26 | {
|
27 | p_twi->TWI_CR = 0x00000003; // write START | STOP |
28 | timeout = 20000000; |
29 | do // wait for RXRDY = 1 |
30 | {
|
31 | status = p_twi->TWI_SR; |
32 | timeout -= 1; |
33 | } while (((status & 0x00000002) == 0) && (timeout > 0)); |
34 | if (timeout == 0) |
35 | return 2; |
36 | data[0] = (uint8_t)(p_twi->TWI_RHR & 0x000000ff); // read data |
37 | timeout = 20000000; |
38 | do // wait for TXCOMP = 1 |
39 | {
|
40 | status = p_twi->TWI_SR; |
41 | timeout -= 1; |
42 | } while (((status & 0x00000001) == 0) && (timeout > 0)); |
43 | if (timeout == 0) |
44 | return 3; |
45 | }
|
46 | else
|
47 | {
|
48 | p_twi->TWI_CR = 0x00000001; // write START |
49 | i = 0; |
50 | while (i < no_data) |
51 | {
|
52 | timeout = 20000000; |
53 | do // wait for RXRDY = 1 |
54 | {
|
55 | status = p_twi->TWI_SR; |
56 | timeout -= 1; |
57 | } while (((status & 0x00000002) == 0) && (timeout > 0)); |
58 | if (timeout == 0) |
59 | return 4; |
60 | data[i] = (uint8_t)(p_twi->TWI_RHR & 0x000000ff); // read data |
61 | i += 1; |
62 | if (i >= (no_data - 1)) |
63 | p_twi->TWI_CR = 0x00000002; // write STOP |
64 | }
|
65 | timeout = 20000000; |
66 | do // wait for RXRDY = 1 |
67 | {
|
68 | status = p_twi->TWI_SR; |
69 | timeout -= 1; |
70 | } while (((status & 0x00000002) == 0) && (timeout > 0)); |
71 | if (timeout == 0) |
72 | return 5; |
73 | data[i] = (uint8_t)(p_twi->TWI_RHR & 0x000000ff); // read data |
74 | timeout = 20000000; |
75 | do // wait for TXCOMP = 1 |
76 | {
|
77 | status = p_twi->TWI_SR; |
78 | timeout -= 1; |
79 | } while (((status & 0x00000001) == 0) && (timeout > 0)); |
80 | if (timeout == 0) |
81 | return 6; |
82 | }
|
83 | return 0; |
84 | }
|
Knackpunkt ist die Abfrage von RXRDY in TWI_SR, das wird nie auf 1 gesetzt. Somit schlägt mein rudimentärer Timeout, den ich für Testzwecke eingebaut habe, zu und die Funktion endet mit dem Fehlercode 2, d.h. Timeout beim Warten auf RXRDY im Zweig für Master Read mit einem Datenbyte. Das gleiche passiert auch beim Master Read mit mehreren Datenbytes. Ist das Datenblatt da fehlerhaft oder unvollständig? Der I2C-Slave ist hardwaremäßig angeschlossen und beim Master Write kommt von dem auch ein Ackknowledge. Gruß Andy