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