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