1 | // Sendet beliebig viele Bytes an den adressierten Slave und empfängt
|
2 | // anschließend beliebig viele Bytes von dem Slave.
|
3 |
|
4 | // slave_address ist die Adresse des Slave in 7bit Schreibweise (0-127).
|
5 | // send_data zeigt auf die zu sendenden Daten, z.B. ein Array von Bytes.
|
6 | // send_bytes gibt an, wieviele Bytes gesendet werden sollen.
|
7 | // rcv_data zeigt auf einen Puffer, wo die empfangenen Daten abgelegt werden
|
8 | // sollen, z.B. ein Array von Bytes.
|
9 | // rcv_Bytes gibt an, wieviele Bytes empfangen werden sollen.
|
10 | // Der Rückgabewert zeigt an, wie viele Bytes tatsächlich empfangen wurden.
|
11 |
|
12 | // Wenn man nur senden will, gibt man rcv_data=0 und rcv_bytes=0 an.
|
13 | // Wenn man nur empfangen will, gibt man send_data=0 und send_bytes=0 an.
|
14 | // Es ist erlaubt, bei send_bytes und rcv_bytes Zeiger auf den selben Puffer zu übergeben.
|
15 |
|
16 | uint8_t i2c_communicate(uint8_t slave_address, void* send_data, uint8_t send_bytes, void* rcv_data, uint8_t rcv_bytes) {
|
17 | uint8_t rcv_count=0;
|
18 |
|
19 | // Adresse ein Bit nach links verschieben, um Platz für das r/w Flag zu schaffen
|
20 | slave_address=slave_address<<1;
|
21 |
|
22 | if (send_bytes>0) {
|
23 | // Sende Start
|
24 | TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
|
25 | while (!(TWCR & (1<<TWINT)));
|
26 | uint8_t status=TWSR & 0xf8;
|
27 | if (status != 0x08 && status != 0x10) goto error;
|
28 |
|
29 | // Sende Adresse (write mode)
|
30 | TWDR=slave_address;
|
31 | TWCR=(1<<TWINT) | (1<<TWEN);
|
32 | while (!(TWCR & (1<<TWINT)));
|
33 | if ((TWSR & 0xf8) != 0x18) goto error;
|
34 |
|
35 | // Sende Daten
|
36 | while (send_bytes>0) {
|
37 | TWDR=*((uint8_t*)send_data);
|
38 | TWCR=(1<<TWINT) | (1<<TWEN);
|
39 | while (!(TWCR & (1<<TWINT)));
|
40 | if ((TWSR & 0xf8) != 0x28) goto error;
|
41 | send_data++;
|
42 | send_bytes--;
|
43 | }
|
44 | }
|
45 |
|
46 | if (rcv_bytes>0) {
|
47 | // Sende START
|
48 | TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTA);
|
49 | while (!(TWCR & (1<<TWINT)));
|
50 | uint8_t status=TWSR & 0xf8;
|
51 | if (status != 0x08 && status != 0x10) goto error;
|
52 |
|
53 | // Sende Adresse (read mode)
|
54 | TWDR=slave_address + 1;
|
55 | TWCR=(1<<TWINT) | (1<<TWEN);
|
56 | while (!(TWCR & (1<<TWINT)));
|
57 | if ((TWSR & 0xf8) != 0x40) goto error;
|
58 |
|
59 | // Empfange Daten
|
60 | while (rcv_bytes>0) {
|
61 | if (rcv_bytes==1) {
|
62 | // das letzte Byte nicht mit ACK quittieren
|
63 | TWCR=(1<<TWINT) | (1<<TWEN);
|
64 | }
|
65 | else {
|
66 | // alle anderen Bytes mit ACK quittieren
|
67 | TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWEA);
|
68 | }
|
69 | while (!(TWCR & (1<<TWINT)));
|
70 | uint8_t status=TWSR & 0xf8;
|
71 | if (status!=0x50 && status != 0x58) goto error;
|
72 | *((uint8_t*)rcv_data)=TWDR;
|
73 | rcv_data++;
|
74 | rcv_bytes--;
|
75 | rcv_count++;
|
76 | }
|
77 |
|
78 | }
|
79 |
|
80 | // Sende STOP
|
81 | TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
82 | return rcv_count;
|
83 |
|
84 | error:
|
85 | // Sende STOP
|
86 | TWCR=(1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
|
87 | return 0;
|
88 | }
|