AVR Embedded Tutorial - I²C, TWI/de
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.
Anmerkung: Wenn die Slave-Adresse falsch ist, bleibt das Programm in der TWIRead-Funktion hängen.
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 (16 * Baud) - 1;
begin
UBRR0 := Teiler;
UCSR0A := (0 shl U2X0);
UCSR0B := (1 shl TXEN0) or (1 shl RXEN0) or (1 shl RXCIE0);
UCSR0C := (%011 shl UCSZ0);
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
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); // 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;
var
Data: integer;
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
???00011: SPS Bit [7:5]
Bit | SPS |
---|---|
000 | 8 |
001 | 16 |
010 | 32 |
011 | 64 |
100 | 128 |
101 | 250 |
110 | 475 |
111 | 860 (default) |
High: 11000011
1???0011: Kanal (Multiplex) Bit [14:12]
Bit | Kanal |
---|---|
100 | 0 (default) |
101 | 1 |
110 | 2 |
111 | 3 |
1100???1: Gain Bit [11:9] (Volt)
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 |