Sign in Join
Wiki copytemporary

AVR Embedded Tutorial - I²C, TWI/de: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11# I²C / TWI
22
33## Vorwort
44
55Dieser Code ist für einen Atmega328/Arduino mit 16MHz.
66
77Wie man die UART ansteuert, steht hier:
88
99- [[AVR Embedded Tutorial - UART/de|UART]] *UARTInit* und *UARTSendString(...*
1010
1111## Beschreibung
1212
1313Dieses Beispiel demonstriert die Kommunikation mit der I²C/TWI - Schnittstelle.
1414
1515Als Slave-Geräte werden 2 AD1115 A/D-Wandler verwendet. Diese sind sehr einfach in der Handhabung und sind auch sehr einfach erhältlich. Was sehr wichtig ist, dass man bei TWIStart die Adresse um ein Bit nach links verschiebt und anschließend mittels Write/Read mit **or** verknüpft. Es gibt viele Tutorials dazu. Dort sieht man das leider sehr schlecht.
1616
1717PulUp-Widerstände sind nicht nötig, da diese schon auf der Platine des ADS1115 verbaut sind.
1818
1919## I²C Funktionen
2020
2121### Konstanten
2222
2323``` pascal
2424const
2525 CPU_Clock = 16000000; // Taktfrequenz Arduino, default 16MHz.
2626 ADSaddr0 = $48; // Adresse Wandler 0
2727 ADSaddr1 = $49; // Adresse Wandler 1
2828 I2C_Takt = 400000; // I²C-Takt (400KHz)
2929 TWI_Write = 0;
3030 TWI_Read = 1;
3131```
3232
3333### I²C inizialisieren
3434
3535``` pascal
3636 procedure TWIInit;
3737 const
3838 TWBR_val = byte((CPU_Clock div I2C_Takt) - 16) div 2;
3939 begin
4040 TWSR := 0;
4141 TWBR := byte(TWBR_val);
4242 end;
4343```
4444
4545### I²C Senden/Empfangen starten
4646
4747``` pascal
4848 procedure TWIStart(addr: byte);
4949 begin
5050 // Senden/Empfangen einleiten
5151 TWCR := 0;
5252 TWCR := (1 shl TWINT) or (1 shl TWSTA) or (1 shl TWEN);
5353 while ((TWCR and (1 shl TWINT)) = 0) do begin
5454 end;
5555
5656 // Adresse des Endgerätes senden
5757 TWDR := addr;
5858 TWCR := (1 shl TWINT) or (1 shl TWEN);
5959 while ((TWCR and (1 shl TWINT)) = 0) do begin
6060 end;
6161 end;
6262```
6363
6464### I²C Senden/Empfang beendet
6565
6666``` pascal
6767 procedure TWIStop;
6868 begin
6969 TWCR := (1 shl TWINT) or (1 shl TWSTO) or (1 shl TWEN);
7070 end;
7171```
7272
7373### Zeichen Senden
7474
7575``` pascal
7676 procedure TWIWrite(u8data: byte);
7777 begin
7878 TWDR := u8data;
7979 TWCR := (1 shl TWINT) or (1 shl TWEN);
8080 while ((TWCR and (1 shl TWINT)) = 0) do begin
8181 end;
8282 end;
8383```
8484
8585### Zeichen Empfangen
8686
8787Bis auf das vorletzte Zeichen muss mit **TWIReadACK(...** gelesen werden. Das letzte Zeichen muss mit **TWIReadNACK(...** gelesen werden.
8888
8989``` pascal
9090 // Lesen bis zum vorletzten Zeichen.
9191 function TWIReadACK: byte;
9292 begin
9393 TWCR := (1 shl TWINT) or (1 shl TWEN) or (1 shl TWEA);
9494 while (TWCR and (1 shl TWINT)) = 0 do begin
9595 end;
9696 Result := TWDR;
9797 end;
9898
9999 // Letztes Zeichen lesen.
100100 function TWIReadNACK: byte;
101101 begin
102102 TWCR := (1 shl TWINT) or (1 shl TWEN);
103103 while (TWCR and (1 shl TWINT)) = 0 do begin
104104 end;
105105 Result := TWDR;
106106 end;
107107```
108108
109109> **Note:** Anmerkung: Diese Funktionen bleibt bei einem Hardware-Fehler, oder die Slave-Adresse falsch ist, hängen !
110110
111111### Zeichen Empfangen mit Fehlerabfrage
112112
113113Das diese Funktionen nicht hängen bleiben, muss man in der while-Schleife einen Zähler einbauen.
114114
115115Wen der Zähler 255 erreicht, wird die Schleife unterbrochen und ein Fehler ausgegeben.
116116
117117255 wird erreicht, wen an der I²C-Adresse kein Gerät gefunden wird.
118118
119119``` pascal
120120// Lesen bis zum vorletzten Zeichen.
121121function TWIReadACK_Error: byte;
122122var
123123 err:byte;
124124begin
125125 err := 0;
126126 TWCR := (1 shl TWINT) or (1 shl TWEN) or (1 shl TWEA);
127127 while ((TWCR and (1 shl TWINT)) = 0) and (err < 255) do begin
128128 Inc(err);
129129 end;
130130 if err = 255 then begin
131131 UARTSendString('I²C-Timeout');
132132 Result := 0;
133133 end else begin
134134 Result := TWDR;
135135 end;
136136end;
137137
138138// Letztes Zeichen lesen.
139139function TWIReadNACK_Error: byte;
140140var
141141 err:byte;
142142begin
143143 err := 0;
144144 TWCR := (1 shl TWINT) or (1 shl TWEN);
145145 while ((TWCR and (1 shl TWINT)) = 0) and (err < 255) do begin
146146 Inc(err);
147147 end;
148148 if err = 255 then begin
149149 UARTSendString('I²C-Timeout');
150150 Result := 0;
151151 end else begin
152152 Result := TWDR;
153153 end;
154154end;
155155```
156156
157157## ADS1115 spezifischen Code
158158
159159Dieser Code ist ADS1115 spezifischen, andere I²C-Geräte müssen im Datenblatt nachgeguckt werden.
160160
161161``` pascal
162162 // Parameter an ADS1115 schicken und Messen einleiten
163163 procedure WriteADS1115(addr: UInt16);
164164 begin
165165 TWIStart((addr shl 1) or TWI_Write);
166166 TWIWrite(1);
167167 TWIWrite(%11000011); // High
168168 TWIWrite(%11100011); // Low
169169 TWIStop;
170170 end;
171171
172172 // Messung von ADS1115 auslesen.
173173 function ReadADS1115(addr: UInt16): UInt16;
174174 begin
175175 TWIStart((addr shl 1) or TWI_Write);
176176 TWIWrite(0);
177177 TWIStop;
178178
179179 TWIStart((addr shl 1) or TWI_Read);
180180 Result := TWIReadACK * $100 + TWIReadNACK;
181181 TWIStop;
182182 end;
183183```
184184
185185## Beispiel
186186
187187``` pascal
188188var
189189 Data: Integer;
190190 s: ShortString;
191191
192192begin
193193 asm cli end; // Interrupt sperren.
194194 UARTInit;
195195 TWIInit;
196196 asm sei end; // Interrupt frei geben.
197197
198198 repeat
199199 WriteADS1115(ADSaddr0);
200200 Data := ReadADS1115(ADSaddr0);
201201
202202 str(Data: 6, s);
203203 UARTSendString('Kanal 0: ');
204204 UARTSendString(s);
205205
206206 WriteADS1115(ADSaddr1);
207207 Data := ReadADS1115(ADSaddr1);
208208
209209 str(Data: 6, s);
210210 UARTSendString(' Kanal 1: ');
211211 UARTSendString(s);
212212 UARTSendString(#13#10);
213213 until 1 = 2;
214214end.
215215```
216216
217217## Parameter ADS1115
218218
219219Eine Auflistung der Parameter des ADS1115. Mehr Infos im Datenblatt.
220220
221221**Bit-Belegung des ADS1115:**
222222
223223**Low:** 11100011 **High:** 11000011
224224
225-<table>
226225<thead>
227-<tr>
228-<th>Bit</th>
229-<th>Bezeichnung</th>
230-<th>Beschreibung</th>
231-</tr>
226+
232227</thead>
233228<tbody>
234-<tr>
235-<td>15</td>
236-<td><strong>OS:</strong> Operational status or single-shot conversion start</td>
237-<td><strong>0</strong> : no effect<br />
229+
238230<strong>1</strong> : Start a single conversion (when in power-down state)</td>
239-</tr>
240-<tr>
241-<td>14:12</td>
242-<td><strong>MUX[2:0]:</strong> Input multiplexer configuration (ADS1115 only)</td>
243-<td><strong>000</strong> : AINP = AIN0 and AINN = AIN1 (default)<br />
231+
244232<strong>001</strong> : AINP = AIN0 and AINN = AIN3<br />
245233<strong>010</strong> : AINP = AIN1 and AINN = AIN3<br />
246234<strong>011</strong> : AINP = AIN2 and AINN = AIN3<br />
247235<strong>100</strong> : AINP = AIN0 and AINN = GND<br />
248236<strong>101</strong> : AINP = AIN1 and AINN = GND<br />
249237<strong>110</strong> : AINP = AIN2 and AINN = GND<br />
250238<strong>111</strong> : AINP = AIN3 and AINN = GND</td>
251-</tr>
252-<tr>
253-<td>11:9</td>
254-<td><strong>PGA[2:0]:</strong>Programmable gain amplifier configuration</td>
255-<td><strong>000</strong> : FSR = ±6.144 V<br />
239+
256240<strong>001</strong> : FSR = ±4.096 V<br />
257241<strong>010</strong> : FSR = ±2.048 V (default)<br />
258242<strong>011</strong> : FSR = ±1.024 V<br />
259243<strong>100</strong> : FSR = ±0.512 V<br />
260244<strong>101</strong> : FSR = ±0.256 V<br />
261245<strong>110</strong> : FSR = ±0.256 V<br />
262246<strong>111</strong> : FSR = ±0.256 V<br />
263-</td>
264-</tr>
265-<tr>
266-<td>8</td>
267-<td><strong>MODE:</strong> Device operating mode</td>
268-<td><strong>0</strong> : Continuous-conversion mode<br />
247+
269248<strong>1</strong> : Single-shot mode or power-down state (default)</td>
270-</tr>
271-<tr>
272-<td>7:5</td>
273-<td><strong>DR[2:0]:</strong> Data rate</td>
274-<td><strong>000</strong> : 8 SPS<br />
249+
275250<strong>001</strong> : 16 SPS<br />
276251<strong>010</strong> : 32 SPS<br />
277252<strong>011</strong> : 64 SPS<br />
278253<strong>100</strong> : 128 SPS (default)<br />
279254<strong>101</strong> : 250 SPS<br />
280255<strong>110</strong> : 475 SPS<br />
281256<strong>111</strong> : 860 SPS<br />
282-</td>
283-</tr>
284-<tr>
285-<td>4</td>
286-<td><strong>COMP_MODE:</strong> Comparator mode</td>
287-<td><strong>0</strong> : Traditional comparator (default)<br />
257+
288258<strong>1</strong> : Window comparator</td>
289-</tr>
290-<tr>
291-<td>3</td>
292-<td><strong>COMP_POL:</strong> Comparator polarity</td>
293-<td><strong>0</strong> : Actice low (default)<br />
259+
294260<strong>1</strong> : Actice high</td>
295-</tr>
296-<tr>
297-<td>2</td>
298-<td><strong>COMP_LAT:</strong> Latching comparator</td>
299-<td><strong>0</strong> : Nonlatching comparator (default)<br />
261+
300262<strong>1</strong> : Latching comparator</td>
301-</tr>
302-<tr>
303-<td>1:0</td>
304-<td><strong>COMP_QUE[1:0]:</strong> Comparator queue and disable</td>
305-<td><strong>00</strong> : Assert after one conversion<br />
263+
306264<strong>01</strong> : Assert after two conversions<br />
307265<strong>10</strong> : Assert after four conversions<br />
308266<strong>11</strong> : Disable comparator and set ALERT/RDY pin to high-impedance (default)</td>
309-</tr>
267+
310268</tbody>
311-</table>
312269
313270# Siehe auch
314271
315272- Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]]
316273
317274Autor: Mathias
318275
319276---
320277*From the Free Pascal wiki, page "AVR Embedded Tutorial - I²C, TWI/de", as it stood on 2020-03-06 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history