1 | /* *************************************
|
2 | TWI Lib Version 5 oder so
|
3 | bhm 2006
|
4 | ************************************** */
|
5 |
|
6 | // bislang keinmultimaster support
|
7 | // keine Garanie für irgendwas
|
8 | // Bemerkungen, Fehlerreports usw willkommen
|
9 |
|
10 |
|
11 | #ifndef _TWILIB_
|
12 | #define _TWILIB_ 1
|
13 | //Zugriff auf IO's des Controllers
|
14 | #include <stdint.h>
|
15 | #include <compat/twi.h>
|
16 |
|
17 | void init_Master (void) {
|
18 | TWSR &= ~(_BV(TWPS0) | _BV(TWPS1)); //0b11111100: Prescaler auf 1 setzen, Bit 1 und 0 auf 0
|
19 | TWBR = 0x0A; //Bitrate auf 10 setzen, gibt 220kHz Bustakt bei 8MHz
|
20 | }
|
21 |
|
22 | void init_Slave (uint8_t SlvAdd) {
|
23 | TWAR = SlvAdd; // eigene Address, hier ohne general call
|
24 | TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > ACK,
|
25 | }
|
26 |
|
27 |
|
28 | void waitTWINT (void) {
|
29 | uint32_t m=0,mmax=8000000; //zZt einfach eine große Zahl
|
30 |
|
31 | while (bit_is_clear(TWCR, TWINT)) {
|
32 | if (m++ > mmax) return; // bricht waitTWINT ab, TW_Status enthält dann TW_NO_INFO
|
33 | }
|
34 | }
|
35 |
|
36 | // *********** MasterTransmitter *************
|
37 | // Daten in *Data, lenmax #Daten senden, MT #gesendete Daten
|
38 | uint8_t MT (uint8_t SlvAdd, uint8_t *Data, uint8_t lenmax) {
|
39 | uint8_t len=1;
|
40 |
|
41 | TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); //sende start
|
42 | waitTWINT();
|
43 | if ((TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START)){ // chk Start | repeated start
|
44 | goto ENDE;
|
45 | }
|
46 |
|
47 | TWDR = SlvAdd + TW_WRITE; //Addresse des Slaves angeben, SLA+W
|
48 | TWCR = _BV(TWINT) | _BV(TWEN); // sende sla_w
|
49 | waitTWINT();
|
50 | if (TW_STATUS != TW_MT_SLA_ACK) { // chk sla_ack
|
51 | goto STOP;
|
52 | }
|
53 |
|
54 | do {
|
55 | TWDR = *Data++; // Datum laden
|
56 | TWCR = _BV(TWINT) | _BV(TWEN); // sende Datum
|
57 | waitTWINT();
|
58 | if (TW_STATUS != TW_MT_DATA_ACK) { // chk data_ack
|
59 | goto STOP;
|
60 | }
|
61 | } while (len++<lenmax);
|
62 |
|
63 | STOP:
|
64 | TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); // sende stop, kein warten auf TWINT
|
65 |
|
66 | ENDE:
|
67 | return len-1;
|
68 | }
|
69 |
|
70 | // *********** MasterReceiver *************
|
71 | // empfangene Daten nach *Data, Speicher muss bereitgestellt sein,
|
72 | // lenmax #Daten empfangen, MR #empfangene Daten
|
73 | uint8_t MR (uint8_t SlvAdd, uint8_t *Data, uint8_t lenmax) {
|
74 | uint8_t len=1;
|
75 |
|
76 | TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); //sende start
|
77 | waitTWINT();
|
78 | if ((TW_STATUS != TW_START) && (TW_STATUS != TW_REP_START)){ // chk Start | repeated start
|
79 | goto ENDE;
|
80 | }
|
81 |
|
82 | TWDR = SlvAdd + TW_READ; //Addresse des Slaves angeben, SLA+r
|
83 | TWCR = _BV(TWINT) | _BV(TWEN); // sende sla_r
|
84 | waitTWINT();
|
85 | if (TW_STATUS != TW_MR_SLA_ACK) { // chk sla_ack
|
86 | goto STOP;
|
87 | }
|
88 |
|
89 | while (1) { // endlos, verlassen via break in if TW_Status
|
90 | if (len<lenmax) {
|
91 | TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //receive, ACK,
|
92 | } else {
|
93 | TWCR = _BV(TWEN) | _BV(TWINT); //receive, NACK,
|
94 | }
|
95 | waitTWINT();
|
96 | if (TW_STATUS != TW_MR_DATA_ACK) break; // LOOP VERLASSEN
|
97 | *Data++ = TWDR; len++; // Daten verarbeitet
|
98 | }
|
99 |
|
100 | if (TW_STATUS == TW_MR_DATA_NACK) {
|
101 | *Data++ = TWDR; len++; // Daten verarbeitet
|
102 | goto STOP;
|
103 | }
|
104 |
|
105 | STOP:
|
106 | TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); // sende stop, kein warten auf TWINT
|
107 | ENDE:
|
108 | return len-1;
|
109 | }
|
110 |
|
111 |
|
112 | // *********** SlaveReceiver *************
|
113 | // empfangene Daten nach *Data, Speicher muss bereitgestellt sein,
|
114 | // lenmax #Daten empfangen, SR #empfangene Daten
|
115 | uint8_t SR (uint8_t *Data, uint8_t lenmax) {
|
116 | uint8_t len=1; // lenmax >= 1, min ein Byte empfangen!
|
117 |
|
118 | // auf SLA warten
|
119 | while (bit_is_clear(TWCR, TWINT)); // beliebig lange warten oder pollen
|
120 |
|
121 | // jetzt geht's los
|
122 | if (TW_STATUS != TW_SR_SLA_ACK) { // chk SLA+W
|
123 | goto STOP;
|
124 | }
|
125 |
|
126 | while (1) { // endlos, verlassen via break in if TW_Status
|
127 | if (len<lenmax) {
|
128 | TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > ACK,
|
129 | } else {
|
130 | TWCR = _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > NACK,
|
131 | }
|
132 | waitTWINT();
|
133 | if (TW_STATUS != TW_SR_DATA_ACK) break; // LOOP VERLASSEN
|
134 | *Data++ = TWDR; len++; // Daten verarbeitet
|
135 | }
|
136 |
|
137 | if (TW_STATUS == TW_SR_DATA_NACK) { // Datum mit NACK beantwortet
|
138 | *Data = TWDR; len++; // im Prinzip noch ein Datum verfügbar
|
139 | }
|
140 |
|
141 | STOP: // (TW_STATUS == TW_SR_STOP) einzig anderer möglicher Status, von ARBs abgesehen
|
142 | TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > ACK,
|
143 | return len-1;
|
144 | }
|
145 |
|
146 | // *********** SlaveTransmitter *************
|
147 | // Daten in *Data, lenmax #Daten senden, ST #gesendete Daten
|
148 | uint8_t ST (uint8_t *Data, uint8_t lenmax) {
|
149 | uint8_t len=0; // lenmax >= 1, min ein Byte senden!
|
150 |
|
151 | // auf SLA warten
|
152 | while (bit_is_clear(TWCR, TWINT)); // beliebig lange warten oder pollen
|
153 |
|
154 | // jetzt geht's los
|
155 | if (TW_STATUS != TW_ST_SLA_ACK) { // chk SLA+R
|
156 | goto STOP;
|
157 | }
|
158 |
|
159 | do {
|
160 | TWDR = *Data++; len++;
|
161 | if (len<lenmax) {
|
162 | TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT);
|
163 | } else {
|
164 | TWCR = _BV(TWEN) | _BV(TWINT);
|
165 | }
|
166 | waitTWINT();
|
167 | } while (TW_STATUS == TW_ST_DATA_ACK);
|
168 |
|
169 | STOP:
|
170 | TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWINT); //slave receive, TWEA > ACK,
|
171 | return len;
|
172 | }
|
173 |
|
174 | #endif
|