00001 00010 #include <util/twi.h> // enthaelt z. B. die Bezeichnungen fuer die Statuscodes in TWSR 00011 #include <avr/interrupt.h> // dient zur behandlung der Interrupts 00012 #include <stdint.h> // definiert den Datentyp uint8_t 00013 00014 #include "twislave.h" 00015 00016 // Bei zu alten AVR-GCC-Versionen werden die Interrupts anders genutzt, daher 00017 // in diesem Fall mit Fehlermeldung abbrechen 00018 #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 00019 # error "This library requires AVR-GCC 3.4.5 or later, update to newer AVR-GCC compiler!" 00020 #endif 00021 00022 // Schutz vor unsinnigen Buffergroessen 00023 #if (buffer_size > 254) 00024 # error Buffer zu gross gewaehlt! Maximal 254 Bytes erlaubt. 00025 #endif 00026 #if (buffer_size < 2) 00027 # error Buffer muss mindestens zwei Byte gross sein! 00028 #endif 00029 00030 volatile uint8_t buffer_adr; //< "Adressregister" fuer den Buffer 00031 00037 void init_twi_slave(uint8_t adr) { 00038 TWAR = adr; // Adresse setzen 00039 TWCR &= ~(1 << TWSTA) | (1 << TWSTO); 00040 TWCR |= (1 << TWEA) | (1 << TWEN) | (1 << TWIE); 00041 buffer_adr = 0xff; 00042 sei(); 00043 } 00044 00045 // Je nach Statuscode in TWSR muessen verschiedene Bitmuster in TWCR geschreiben werden (siehe Tabellen im Datenblatt). 00046 // Makros fuer die verwendeten Bitmuster: 00047 00048 // ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten 00049 #define TWCR_ACK TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (0 << TWWC); 00050 // NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten 00051 #define TWCR_NACK TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (0 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (0 << TWWC); 00052 // switched to the non adressed slave mode... 00053 #define TWCR_RESET TWCR = (1 << TWEN) | (1 << TWIE) | (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (0 << TWWC); 00054 00055 // Die Bitmuster fuer TWCR_ACK und TWCR_RESET sind gleich. Dies ist kein Fehler und dient nur der Uebersicht! 00056 00057 00063 ISR(TWI_vect) { 00064 uint8_t data = 0; 00065 00066 // TWI-Statusregister pruefen und noetige Aktion bestimmen 00067 switch (TW_STATUS) { 00068 case TW_SR_SLA_ACK: // 0x60 Slave Receiver, wurde adressiert 00069 TWCR_ACK; // naechstes Datenbyte empfangen, ACK danach 00070 buffer_adr = 0xFF; // Bufferposition ist undefiniert 00071 break; 00072 case TW_SR_DATA_ACK: // 0x80 Slave Receiver,Daten empfangen 00073 data = TWDR; // Empfangene Daten auslesen 00074 if (buffer_adr == 0xFF) { // erster Zugriff, Bufferposition setzen 00075 // Kontrolle ob gewuenschte Adresse im erlaubten bereich 00076 if (data <= buffer_size) { 00077 buffer_adr = data; // Bufferposition wie adressiert setzen 00078 } else { 00079 buffer_adr = 0; // Adresse auf Null setzen. Ist das sinnvoll? 00080 } 00081 TWCR_ACK; // naechstes Datenbyte empfangen, ACK danach, um naechstes Byte anzufordern 00082 } else { // weiterer Zugriff, Daten empfangen 00083 rxbuffer[buffer_adr] = data; // Daten in Buffer schreiben 00084 buffer_adr++; // Buffer-Adresse weiterzaehlen fuer naechsten Schreibzugriff 00085 if (buffer_adr < (buffer_size - 1)) { // im Buffer ist noch Platz fuer mehr als ein Byte 00086 TWCR_ACK; // naechstes Datenbyte empfangen, ACK danach, um naechstes Byte anzufordern 00087 } else { // es kann nur noch ein Byte kommen, dann ist der Buffer voll 00088 TWCR_NACK; // letztes Byte lesen, dann NACK, um vollen Buffer zu signaliseren 00089 } 00090 } 00091 break; 00092 case TW_ST_SLA_ACK: // ?!? 00093 case TW_ST_DATA_ACK: // 0xB8 Slave Transmitter, weitere Daten wurden angefordert 00094 if (buffer_adr == 0xFF) { // zuvor keine Leseadresse angegeben! 00095 buffer_adr = 0; 00096 } 00097 TWDR = txbuffer[buffer_adr]; // Datenbyte senden 00098 buffer_adr++; // bufferadresse fuer naechstes Byte weiterzaehlen 00099 if (buffer_adr < (buffer_size - 1)) { // im Buffer ist mehr als ein Byte, das gesendet werden kann 00100 TWCR_ACK; // naechstes Byte senden, danach ACK erwarten 00101 } else { 00102 TWCR_NACK; // letztes Byte senden, danach NACK erwarten 00103 } 00104 break; 00105 case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert 00106 case TW_SR_DATA_NACK: // 0x88 00107 case TW_ST_LAST_DATA: // 0xC8 Last data byte in TWDR has been transmitted (TWEA = "0"); ACK has been received 00108 case TW_SR_STOP: // 0xA0 STOP empfangen 00109 default: 00110 TWCR_RESET; // Uebertragung beenden, warten bis zur naechsten Adressierung 00111 break; 00112 } 00113 }