twislave.c


1
#include "main.h"
2
3
volatile uint8_t buffer_adr;
4
5
/*Initaliserung des TWI-Inteface. Muss zu Beginn aufgerufen werden, sowie bei einem Wechsel der Slave Adresse
6
Parameter adr: gewünschte Slave-Adresse
7
*/
8
void init_twi_slave(int adr)
9
{
10
  switch(adr) {
11
     case 1:
12
       TWAR= I2CADDR0; //Adresse setzen
13
       break;
14
     case 2:
15
       TWAR= I2CADDR1; //Adresse setzen
16
       break;
17
     case 3:
18
       TWAR= I2CADDR2; //Adresse setzen
19
       break;
20
     case 4:
21
       TWAR= I2CADDR3; //Adresse setzen
22
       break;
23
     case 5:
24
       TWAR= I2CADDR4; //Adresse setzen
25
       break;
26
     case 6:
27
       TWAR= I2CADDR5; //Adresse setzen
28
       break;
29
     case 7:
30
       TWAR= I2CADDR6; //Adresse setzen
31
       break;
32
     case 8:
33
       TWAR= I2CADDR7; //Adresse setzen
34
       break;
35
     default:
36
       TWAR= I2CADDR0; //Adresse setzen
37
       break;
38
  }
39
     
40
  TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
41
  TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);   
42
  buffer_adr=0xFF;  
43
}
44
45
46
//Je nach Statuscode in TWSR müssen verschiedene Bitmuster in TWCR geschreiben werden(siehe Tabellen im Datenblatt!). 
47
//Makros für die verwendeten Bitmuster:
48
49
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten
50
#define TWCR_ACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);  
51
52
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     
53
#define TWCR_NACK TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
54
55
//switch to the non adressed slave mode...
56
#define TWCR_RESET TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(1<<TWSTO)|(0<<TWWC);  
57
58
59
/*ISR, die bei einem Ereignis auf dem Bus ausgelöst wird. Im Register TWSR befindet sich dann 
60
ein Statuscode, anhand dessen die Situation festgestellt werden kann.
61
*/
62
ISR (TWI_vect)  
63
{
64
uint8_t data=0;
65
66
switch (TW_STATUS) //TWI-Statusregister prüfen und nötige Aktion bestimmen 
67
{
68
69
// Slave Receiver 
70
71
case TW_SR_SLA_ACK: // 0x60 Slave Receiver, Slave wurde adressiert
72
     if (i2cbuf == 0) {
73
      TWCR_ACK; // nächstes Datenbyte empfangen, ACK danach senden
74
      buffer_adr=0xFF; //Bufferposition ist undefiniert
75
    } else {
76
      TWCR_NACK;
77
    }
78
break;
79
  
80
case TW_SR_DATA_ACK: // 0x80 Slave Receiver, ein Datenbyte wurde empfangen
81
  data=TWDR; //Empfangene Daten auslesen
82
  if (buffer_adr == 0xFF) //erster Zugriff, Bufferposition setzen
83
    {
84
      //Kontrolle ob gewünschte Adresse im erlaubten bereich
85
      if(data<i2c_buffer_size+1)
86
        {
87
          buffer_adr= data; //Bufferposition wie adressiert setzen
88
        }
89
      else
90
        {
91
          buffer_adr=0; //Adresse auf Null setzen. Ist das sinnvoll? TO DO!
92
        }        
93
      TWCR_ACK;  // nächstes Datenbyte empfangen, ACK danach, um nächstes Byte anzufordern
94
    }
95
  else //weiterer Zugriff, nachdem die Position im Buffer gesetzt wurde. NUn die Daten empfangen und speichern
96
    {
97
    
98
      if(buffer_adr<i2c_buffer_size+1)
99
        {
100
            i2cdata[buffer_adr]=data; //Daten in Buffer schreibe
101
        }
102
      buffer_adr++; //Buffer-Adresse weiterzählen für nächsten Schreibzugriff
103
      TWCR_ACK;  
104
    }
105
break;
106
107
108
//Slave transmitter
109
110
case TW_ST_SLA_ACK: //0xA8 Slave wurde im Lesemodus adressiert und hat ein ACK zurückgegeben.
111
  //Hier steht kein break! Es wird also der folgende Code ebenfalls ausgeführt!
112
  
113
case TW_ST_DATA_ACK: //0xB8 Slave Transmitter, Daten wurden angefordert
114
115
  if (buffer_adr == 0xFF) //zuvor keine Leseadresse angegeben! 
116
    {
117
      buffer_adr=0;
118
    }  
119
    
120
  if(buffer_adr<i2c_buffer_size+1)  
121
    {
122
      TWDR = i2cdata[buffer_adr]; //Datenbyte senden
123
      buffer_adr++; //bufferadresse für nächstes Byte weiterzählen
124
    }
125
  else
126
    {
127
      TWDR=0; //Kein Daten mehr im Buffer
128
    }
129
  TWCR_ACK;
130
break;
131
case TW_SR_STOP:
132
        TWCR_ACK;
133
        i2cbuf = 1;
134
        break;
135
case TW_ST_DATA_NACK: // 0xC0 Keine Daten mehr gefordert 
136
case TW_SR_DATA_NACK: // 0x88 
137
case TW_ST_LAST_DATA: // 0xC8  Last data byte in TWDR has been transmitted (TWEA = “0”); ACK has been received
138
default:   
139
    TWCR_RESET;
140
break;
141
  
142
}
143
}