AVR Embedded Tutorial - I²C, TWI/de

From Free Pascal wiki
Revision as of 21:24, 28 October 2017 by Mathias (talk | contribs) (Created page with "===Beschreibung=== Dieses Beispiel demonstriert die Kominikation mit der I²C/TWI - Schnittstelle. Als Slave-Geräte werden 2 AD1115 A/D-Wandler verwendet, diese sind sehr ei...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Beschreibung

Dieses Beispiel demonstriert die Kominikation 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, das man bei TWIStart die Adresse un ein Bit nach links verschiebt und anschliessend mit mit Write/Read mit or verknüpft. Es gibt viele Tutorials, und dort sieht man das leider sehr schlecht.

Beispiel Code

program Project1;

const
  CPU_Clock = 16000000; // Taktfrequenz Arduino, default 16MHz.
  Baud      = 9600;     // Baudrate UART
  ADSaddr0  = $48;      // Adresse Wandler 0
  ADSaddr1  = $49;      // Adresse Wandler 1
  I2C_Takt  = 400000;   // I²C-Takt (400KHz)
  TWI_Write = 0;
  TWI_Read  = 1;
  UCSZ01    = 2;         // Gibt es nicht in der Unit Atmega328p.


  // === UART-Schnittstelle

  procedure UARTInit;
  const
    Teiler = CPU_Clock div (2 * Baud) - 1;
  begin
    UBRR0 := Teiler;
    UCSR0A := UCSR0A or (0 shl U2X0);
    UCSR0B := UCSR0B or (1 shl TXEN0) or (1 shl RXEN0);
    UCSR0C := UCSR0C or (1 shl UMSEL0) or (1 shl UCSZ01) or (1 shl UCSZ0);

    DDRD := DDRD or (1 shl 4);
  end;

  procedure UARTSendChar(c: char);
  begin
    while UCSR0A and (1 shl UDRE0) = 0 do begin
    end;
    UDR0 := byte(c);
  end;

  function UARTReadChar: char;
  begin
    while UCSR0A and (1 shl RXC0) = 0 do begin
    end;
    Result := char(UDR0);
  end;

  procedure UARTSendString(s: ShortString);
  var
    i: integer;
  begin
    for i := 1 to length(s) do begin
      UARTSendChar(s[i]);
    end;
  end;

  // === I2C Bus

var
  Data: integer;

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

  procedure TWIStart(addr: byte);
  begin
    // Senden 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;

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

  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;

  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;

  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;

  // === Ende I2C

  // Parameter an ADS1115 schicken und Messen einleiten
  procedure WriteADS1115(addr: UInt16);
  begin
    TWIStart((addr shl 1) or TWI_Write);
    TWIWrite(1);
    TWIWrite(%11000011);
    TWIWrite(%11100011);
    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;

var
  s: ShortString;
begin
  asm
           Cli
  end;
  UARTInit;
  TWIInit;
  asm
           Sei
  end;

  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 kleine Auflistung der wichtigsten Parameter des ADS1115. Mehr Infos im Datenblatt.

Low: 11100011 (default 860SPS)

???00011: SPS

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


High: 11000011 (default 2,048V )

1???0011: Kanal (Multiplex)

1100???1: Gain Bit [11:9] (Volt)

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