Difference between revisions of "AVR Embedded Tutorial - I²C, TWI/de"

From Lazarus wiki
Jump to navigationJump to search
m (Added page template; removed categories in template)
 
(10 intermediate revisions by 2 users not shown)
Line 1: Line 1:
 +
{{I2C}}
  
{{Translate}}
 
 
=I²C / TWI=
 
=I²C / TWI=
  
 
==Vorwort==
 
==Vorwort==
 +
 
Dieser Code ist für einen Atmega328/Arduino mit 16MHz.
 
Dieser Code ist für einen Atmega328/Arduino mit 16MHz.
 +
 
Wie man die UART ansteuert, steht hier:
 
Wie man die UART ansteuert, steht hier:
 +
 
* [[AVR Embedded Tutorial - UART/de|UART]] ''UARTInit'' und ''UARTSendString(...''
 
* [[AVR Embedded Tutorial - UART/de|UART]] ''UARTInit'' und ''UARTSendString(...''
  
 
==Beschreibung==
 
==Beschreibung==
 +
 
Dieses Beispiel demonstriert die Kommunikation mit der I²C/TWI - Schnittstelle.
 
Dieses Beispiel demonstriert die Kommunikation mit der I²C/TWI - Schnittstelle.
  
Line 15: Line 19:
  
 
PulUp-Widerstände sind nicht nötig, da diese schon auf der Platine des ADS1115 verbaut sind.
 
PulUp-Widerstände sind nicht nötig, da diese schon auf der Platine des ADS1115 verbaut sind.
 
{{Note|Anmerkung: Wenn die Slave-Adresse falsch ist, bleibt das Programm in der TWIRead-Funktion hängen !}}
 
  
 
== I²C Funktionen ==
 
== I²C Funktionen ==
  
 
=== Konstanten ===
 
=== Konstanten ===
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
const
 
const
Line 32: Line 35:
  
 
=== I²C inizialisieren ===
 
=== I²C inizialisieren ===
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
   procedure TWIInit;
 
   procedure TWIInit;
Line 43: Line 47:
  
 
=== I²C Senden/Empfangen starten ===
 
=== I²C Senden/Empfangen starten ===
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
   procedure TWIStart(addr: byte);
 
   procedure TWIStart(addr: byte);
Line 61: Line 66:
  
 
=== I²C Senden/Empfang beendet ===
 
=== I²C Senden/Empfang beendet ===
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
   procedure TWIStop;
 
   procedure TWIStop;
Line 69: Line 75:
  
 
=== Zeichen Senden ===
 
=== Zeichen Senden ===
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
   procedure TWIWrite(u8data: byte);
 
   procedure TWIWrite(u8data: byte);
Line 80: Line 87:
  
 
=== Zeichen Empfangen ===
 
=== Zeichen Empfangen ===
 +
 
Bis auf das vorletzte Zeichen muss mit '''TWIReadACK(...''' gelesen werden.
 
Bis auf das vorletzte Zeichen muss mit '''TWIReadACK(...''' gelesen werden.
 
Das letzte Zeichen muss  mit '''TWIReadNACK(...''' gelesen werden.  
 
Das letzte Zeichen muss  mit '''TWIReadNACK(...''' gelesen werden.  
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
 
   // Lesen bis zum vorletzten Zeichen.
 
   // Lesen bis zum vorletzten Zeichen.
 
   function TWIReadACK: byte;
 
   function TWIReadACK: byte;
Line 93: Line 101:
 
   end;
 
   end;
  
   // Letzten Zeichen lesen.
+
   // Letztes Zeichen lesen.
 
   function TWIReadNACK: byte;
 
   function TWIReadNACK: byte;
 
   begin
 
   begin
Line 101: Line 109:
 
     Result := TWDR;
 
     Result := TWDR;
 
   end;
 
   end;
 +
</syntaxhighlight>
 +
 +
{{Note|Anmerkung: Diese Funktionen bleibt bei einem Hardware-Fehler, oder die Slave-Adresse falsch ist, hängen !}}
 +
 +
=== Zeichen Empfangen mit Fehlerabfrage ===
 +
 +
Das diese Funktionen nicht hängen bleiben, muss man in der while-Schleife einen Zähler einbauen.
 +
 +
Wen der Zähler 255 erreicht, wird die Schleife unterbrochen und ein Fehler ausgegeben.
 +
 +
255 wird erreicht, wen an der I²C-Adresse kein Gerät gefunden wird.
 +
 +
<syntaxhighlight lang="pascal">
 +
// Lesen bis zum vorletzten Zeichen.
 +
function TWIReadACK_Error: byte;
 +
var
 +
  err:byte;
 +
begin
 +
  err := 0;
 +
  TWCR := (1 shl TWINT) or (1 shl TWEN) or (1 shl TWEA);
 +
  while ((TWCR and (1 shl TWINT)) = 0) and (err < 255) do begin
 +
    Inc(err);
 +
  end;
 +
  if err = 255 then begin
 +
    UARTSendString('I²C-Timeout');
 +
    Result := 0;
 +
  end else begin
 +
    Result := TWDR;
 +
  end;
 +
end;
 +
 +
// Letztes Zeichen lesen.
 +
function TWIReadNACK_Error: byte;
 +
var
 +
  err:byte;
 +
begin
 +
  err := 0;
 +
  TWCR := (1 shl TWINT) or (1 shl TWEN);
 +
  while ((TWCR and (1 shl TWINT)) = 0) and (err < 255) do begin
 +
    Inc(err);
 +
  end;
 +
  if err = 255 then begin
 +
    UARTSendString('I²C-Timeout');
 +
    Result := 0;
 +
  end else begin
 +
    Result := TWDR;
 +
  end;
 +
end;
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
== ADS1115 spezifischen Code ==
 
== ADS1115 spezifischen Code ==
 +
 
Dieser Code ist ADS1115 spezifischen, andere I²C-Geräte müssen im Datenblatt nachgeguckt werden.
 
Dieser Code ist ADS1115 spezifischen, andere I²C-Geräte müssen im Datenblatt nachgeguckt werden.
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
   // Parameter an ADS1115 schicken und Messen einleiten
 
   // Parameter an ADS1115 schicken und Messen einleiten
Line 130: Line 188:
  
 
== Beispiel ==
 
== Beispiel ==
 +
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
var
 
var
   Data: integer;
+
   Data: Integer;
   s: ShortString;
+
   s:   ShortString;
  
 
begin
 
begin
Line 161: Line 220:
  
 
==Parameter ADS1115==
 
==Parameter ADS1115==
Eine kleine Auflistung der wichtigsten Parameter des ADS1115.
+
 
 +
Eine Auflistung der Parameter des ADS1115.
 
Mehr Infos im Datenblatt.
 
Mehr Infos im Datenblatt.
 +
 +
'''Bit-Belegung des ADS1115:'''
  
 
'''Low:'''  11100011
 
'''Low:'''  11100011
 +
'''High:''' 11000011
  
???00011: SPS Bit [7:5]
 
 
{| class="wikitable"
 
{| class="wikitable"
 +
!Bit  !! Bezeichnung !! Beschreibung     
 
|-
 
|-
!Bit !! SPS
+
| 15    ||''' OS:''' Operational status or single-shot conversion start  ||
 +
'''0''' : no effect<br>
 +
'''1''' : Start a single conversion (when in power-down state)
 
|-
 
|-
|000 || 8
+
| 14:12 || '''MUX[2:0]:''' Input multiplexer configuration (ADS1115 only) ||  
 +
'''000''' : AINP = AIN0 and AINN = AIN1 (default)<br>
 +
'''001''' : AINP = AIN0 and AINN = AIN3<br>
 +
'''010''' : AINP = AIN1 and AINN = AIN3<br>
 +
'''011''' : AINP = AIN2 and AINN = AIN3<br>
 +
'''100''' : AINP = AIN0 and AINN = GND<br>
 +
'''101''' : AINP = AIN1 and AINN = GND<br>
 +
'''110''' : AINP = AIN2 and AINN = GND<br>
 +
'''111''' : AINP = AIN3 and AINN = GND
 
|-
 
|-
|001 || 16
+
| 11:9 || '''PGA[2:0]:'''Programmable gain amplifier configuration ||
 +
'''000''' : FSR = ±6.144 V<br>
 +
'''001''' : FSR = ±4.096 V<br>
 +
'''010''' : FSR = ±2.048 V (default)<br>
 +
'''011''' : FSR = ±1.024 V<br>
 +
'''100''' : FSR = ±0.512 V<br>
 +
'''101''' : FSR = ±0.256 V<br>
 +
'''110''' : FSR = ±0.256 V<br>
 +
'''111''' : FSR = ±0.256 V<br>
 
|-
 
|-
|010 || 32
+
| || '''MODE:''' Device operating mode  ||
 +
'''0''' : Continuous-conversion mode<br>
 +
'''1''' : Single-shot mode or power-down state (default)
 
|-
 
|-
|011 || 64
+
| 7:5 || '''DR[2:0]:''' Data rate ||
 +
'''000''' : 8 SPS<br>
 +
'''001''' : 16 SPS<br>
 +
'''010''' : 32 SPS<br>
 +
'''011''' : 64 SPS<br>
 +
'''100''' : 128 SPS (default)<br>
 +
'''101''' : 250 SPS<br>
 +
'''110''' : 475 SPS<br>
 +
'''111''' : 860 SPS<br>
 
|-
 
|-
|100 || 128
+
| || '''COMP_MODE:''' Comparator mode  ||
 +
'''0''' : Traditional comparator (default)<br>
 +
'''1''' : Window comparator
 
|-
 
|-
|101 || 250
+
| || '''COMP_POL:''' Comparator polarity  ||
 +
'''0''' : Actice low (default)<br>
 +
'''1''' : Actice high
 
|-
 
|-
|110 || 475
+
| || '''COMP_LAT:''' Latching comparator  ||
 +
'''0''' : Nonlatching comparator (default)<br>
 +
'''1''' : Latching comparator
 
|-
 
|-
|111 || 860 (default)
+
| 1:0  || '''COMP_QUE[1:0]:''' Comparator queue and disable ||
 +
'''00''' : Assert after one conversion<br>
 +
'''01''' : Assert after two conversions<br>
 +
'''10''' : Assert after four conversions<br>
 +
'''11''' : Disable comparator and set ALERT/RDY pin to high-impedance (default)
 
|}
 
|}
  
 +
= Siehe auch =
  
'''High:''' 11000011
+
* Übersichtseite [[AVR Embedded Tutorial/de|AVR Embedded Tutorial]]
 
 
1???0011: Kanal (Multiplex) Bit [14:12]
 
{| class="wikitable"
 
|-
 
!Bit !! Kanal
 
|-
 
|100 || 0 (default)
 
|-
 
|101 || 1
 
|-
 
|110 || 2
 
|-
 
|111 || 3
 
|}
 
 
 
 
 
1100???1: Gain  Bit [11:9]  (Volt)
 
 
 
{| class="wikitable"
 
|-
 
!Bit !! Volt
 
|-
 
|000 || FS = ±6.144
 
|-
 
|001 || FS = ±4.096
 
|-
 
|010 || FS = ±2.048 (default)
 
|-
 
|011 || FS = ±1.024
 
|-
 
|100 || FS = ±0.512
 
|-
 
|101 || FS = ±0.256
 
|-
 
|110 || FS = ±0.256
 
|-
 
|111 || FS = ±0.256
 
|}
 
 
 
== Siehe auch ==
 
* Übersichtseite [[AVR Embedded Tutorial/de]]
 
  
[[Category:Embedded]]
+
Autor: [[User:Mathias|Mathias]]
[[Category:AVR]]
 
[[Category:Arduino]]
 

Latest revision as of 08:20, 6 March 2020

Deutsch (de) English (en)

I²C / TWI

Vorwort

Dieser Code ist für einen Atmega328/Arduino mit 16MHz.

Wie man die UART ansteuert, steht hier:

  • UART UARTInit und UARTSendString(...

Beschreibung

Dieses Beispiel demonstriert die Kommunikation mit der I²C/TWI - Schnittstelle.

Als 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.

PulUp-Widerstände sind nicht nötig, da diese schon auf der Platine des ADS1115 verbaut sind.

I²C Funktionen

Konstanten

const
  CPU_Clock = 16000000; // Taktfrequenz Arduino, default 16MHz.
  ADSaddr0  = $48;      // Adresse Wandler 0
  ADSaddr1  = $49;      // Adresse Wandler 1
  I2C_Takt  = 400000;   // I²C-Takt (400KHz)
  TWI_Write = 0;
  TWI_Read  = 1;

I²C inizialisieren

  procedure TWIInit;
  const
    TWBR_val = byte((CPU_Clock div I2C_Takt) - 16) div 2;
  begin
    TWSR := 0;
    TWBR := byte(TWBR_val);
  end;

I²C Senden/Empfangen starten

  procedure TWIStart(addr: byte);
  begin
    // Senden/Empfangen einleiten
    TWCR := 0;
    TWCR := (1 shl TWINT) or (1 shl TWSTA) or (1 shl TWEN);
    while ((TWCR and (1 shl TWINT)) = 0) do begin
    end;

    // Adresse des Endgerätes senden
    TWDR := addr;
    TWCR := (1 shl TWINT) or (1 shl TWEN);
    while ((TWCR and (1 shl TWINT)) = 0) do begin
    end;
  end;

I²C Senden/Empfang beendet

  procedure TWIStop;
  begin
    TWCR := (1 shl TWINT) or (1 shl TWSTO) or (1 shl TWEN);
  end;

Zeichen Senden

  procedure TWIWrite(u8data: byte);
  begin
    TWDR := u8data;
    TWCR := (1 shl TWINT) or (1 shl TWEN);
    while ((TWCR and (1 shl TWINT)) = 0) do begin
    end;
  end;

Zeichen Empfangen

Bis auf das vorletzte Zeichen muss mit TWIReadACK(... gelesen werden. Das letzte Zeichen muss mit TWIReadNACK(... gelesen werden.

  // Lesen bis zum vorletzten Zeichen.
  function TWIReadACK: byte;
  begin
    TWCR := (1 shl TWINT) or (1 shl TWEN) or (1 shl TWEA);
    while (TWCR and (1 shl TWINT)) = 0 do begin
    end;
    Result := TWDR;
  end;

  // Letztes Zeichen lesen.
  function TWIReadNACK: byte;
  begin
    TWCR := (1 shl TWINT) or (1 shl TWEN);
    while (TWCR and (1 shl TWINT)) = 0 do begin
    end;
    Result := TWDR;
  end;
Light bulb  Hinweis: Anmerkung: Diese Funktionen bleibt bei einem Hardware-Fehler, oder die Slave-Adresse falsch ist, hängen !

Zeichen Empfangen mit Fehlerabfrage

Das diese Funktionen nicht hängen bleiben, muss man in der while-Schleife einen Zähler einbauen.

Wen der Zähler 255 erreicht, wird die Schleife unterbrochen und ein Fehler ausgegeben.

255 wird erreicht, wen an der I²C-Adresse kein Gerät gefunden wird.

// Lesen bis zum vorletzten Zeichen.
function TWIReadACK_Error: byte;
var
  err:byte;
begin
  err := 0;
  TWCR := (1 shl TWINT) or (1 shl TWEN) or (1 shl TWEA);
  while ((TWCR and (1 shl TWINT)) = 0) and (err < 255) do begin
    Inc(err);
  end;
  if err = 255 then begin
    UARTSendString('I²C-Timeout');
    Result := 0;
  end else begin
    Result := TWDR;
  end;
end;

// Letztes Zeichen lesen.
function TWIReadNACK_Error: byte;
var
  err:byte;
begin
  err := 0;
  TWCR := (1 shl TWINT) or (1 shl TWEN);
  while ((TWCR and (1 shl TWINT)) = 0) and (err < 255) do begin
    Inc(err);
  end;
  if err = 255 then begin
    UARTSendString('I²C-Timeout');
    Result := 0;
  end else begin
    Result := TWDR;
  end;
end;

ADS1115 spezifischen Code

Dieser Code ist ADS1115 spezifischen, andere I²C-Geräte müssen im Datenblatt nachgeguckt werden.

  // Parameter an ADS1115 schicken und Messen einleiten
  procedure WriteADS1115(addr: UInt16);
  begin
    TWIStart((addr shl 1) or TWI_Write);
    TWIWrite(1);
    TWIWrite(%11000011);  // High
    TWIWrite(%11100011);  // Low
    TWIStop;
  end;

  // Messung von ADS1115 auslesen.
  function ReadADS1115(addr: UInt16): UInt16;
  begin
    TWIStart((addr shl 1) or TWI_Write);
    TWIWrite(0);
    TWIStop;

    TWIStart((addr shl 1) or TWI_Read);
    Result := TWIReadACK * $100 + TWIReadNACK;
    TWIStop;
  end;

Beispiel

var
  Data: Integer;
  s:    ShortString;

begin
  asm cli end; // Interrupt sperren.
  UARTInit;
  TWIInit;
  asm sei end; // Interrupt frei geben.

  repeat
    WriteADS1115(ADSaddr0);
    Data := ReadADS1115(ADSaddr0);

    str(Data: 6, s);
    UARTSendString('Kanal 0: ');
    UARTSendString(s);

    WriteADS1115(ADSaddr1);
    Data := ReadADS1115(ADSaddr1);

    str(Data: 6, s);
    UARTSendString(' Kanal 1: ');
    UARTSendString(s);
    UARTSendString(#13#10);
  until 1 = 2;
end.

Parameter ADS1115

Eine Auflistung der Parameter des ADS1115. Mehr Infos im Datenblatt.

Bit-Belegung des ADS1115:

Low: 11100011 High: 11000011

Bit Bezeichnung Beschreibung
15 OS: Operational status or single-shot conversion start

0 : no effect
1 : Start a single conversion (when in power-down state)

14:12 MUX[2:0]: Input multiplexer configuration (ADS1115 only)

000 : AINP = AIN0 and AINN = AIN1 (default)
001 : AINP = AIN0 and AINN = AIN3
010 : AINP = AIN1 and AINN = AIN3
011 : AINP = AIN2 and AINN = AIN3
100 : AINP = AIN0 and AINN = GND
101 : AINP = AIN1 and AINN = GND
110 : AINP = AIN2 and AINN = GND
111 : AINP = AIN3 and AINN = GND

11:9 PGA[2:0]:Programmable gain amplifier configuration

000 : FSR = ±6.144 V
001 : FSR = ±4.096 V
010 : FSR = ±2.048 V (default)
011 : FSR = ±1.024 V
100 : FSR = ±0.512 V
101 : FSR = ±0.256 V
110 : FSR = ±0.256 V
111 : FSR = ±0.256 V

8 MODE: Device operating mode

0 : Continuous-conversion mode
1 : Single-shot mode or power-down state (default)

7:5 DR[2:0]: Data rate

000 : 8 SPS
001 : 16 SPS
010 : 32 SPS
011 : 64 SPS
100 : 128 SPS (default)
101 : 250 SPS
110 : 475 SPS
111 : 860 SPS

4 COMP_MODE: Comparator mode

0 : Traditional comparator (default)
1 : Window comparator

3 COMP_POL: Comparator polarity

0 : Actice low (default)
1 : Actice high

2 COMP_LAT: Latching comparator

0 : Nonlatching comparator (default)
1 : Latching comparator

1:0 COMP_QUE[1:0]: Comparator queue and disable

00 : Assert after one conversion
01 : Assert after two conversions
10 : Assert after four conversions
11 : Disable comparator and set ALERT/RDY pin to high-impedance (default)

Siehe auch

Autor: Mathias