Forum: Compiler & IDEs TWI Slave Programmieren


von TWI (Gast)


Lesenswert?

Hallo.

Mein Ziel ist es eine Kommunikation zwischen 2 Atmegas über das TWI 
Interface herzustellen. Für den Master verwende ich die Library von 
Peter Fleury. Damit bin ich eigentlich recht zufrieden.
Nun ist die Programmierung des Slave Bausteins an der Reihe. Mit dem 
Master möchte ich immer so etwas senden, was dann vom Slave ausgewertet 
werden soll:
1
i2c_start_wait(0x00+I2C_WRITE);
2
i2c_write(byte0);
3
i2c_write(byte1);
4
i2c_write(byte2);
5
i2c_write(byte3);
6
i2c_write(byte4);
7
i2c_stop();

Dazu habe ich jetzt ein paar allgemeine Fragen, wie man das am besten 
realisiert. Zum einen erst einmal prüfen und auswerten von TWSR in der 
ISR, oder in einer externen Funktion?
Eigentlich sollte man die ISRs ja so kurz wie möglich halten. Aber ich 
habe im Datenblatt keine Möglichkeit gesehen, die Signalisiert, dass ein 
neues Byte da ist. Hat da einer eine Idee?

Die nächste Frage ist, wie realisiert man die Auswertung. Ich würde die 
ganzen Bytes jetzt einfach in ein Array schreiben, was eben mit der 
Start Condition gelöscht wird, und nach der stop ausgewertet wird.

von TWI (Gast)


Lesenswert?

Fehlen noch Infos meinerseits, oder hat keiner von euch eine Idee?

von Stefan B. (stefan) Benutzerseite


Lesenswert?


von TWI (Gast)


Lesenswert?

Hallo.

die Dokumente habe ich mir schon angesehen. Aber ich finde da nirgends 
Code, nur Funktionsnamen. Das einzige, was ich erst einmal machen möchte 
ist ein paar Bytes empfangen und auszuwerten.

von TWI (Gast)


Lesenswert?

OK. Den Code habe ich jetzt gefunden. Leider ist der etwas komplex und 
deckt wesentlich mehr ab, als ich brauche.

von Florian M. (flomll)


Lesenswert?

Ich finde den Code nicht! Kann mir jemand den genauen Link posten?

von ... (Gast)


Lesenswert?


von Kurt H. (Firma: KHTronik) (kurtharders)


Lesenswert?

Dieser Code sollte als Basis reichen:
1
/*
2
 * Beispielprogramm eines TWI (I2C) Slave. Getestet mit ATMega8
3
 *
4
 * Die gesamte Behandlung der TWI-Zustände erfolgt in der Interrupt-Routine. Das Hauptprogramm tut nichts.
5
 * Wenn die Daten nicht direkt in der Interruptroutine bearbeitet werden können, muss man am Ende den Interrupt ausschalten
6
 * und nach der Verarbeitung im Haptprogramm wieder einschalten. Aber Achtung: wenn der Prozessor nicht auf TWI-Adressanfragen reagiert,
7
 * gibt es einen SLA_NACK beim Sender.
8
 *
9
 */
10
11
#include "util/delay.h"
12
#include "avr/interrupt.h"
13
#include "util/twi.h"
14
15
static uint8_t data[64];    // Datenpuffer
16
volatile uint8_t ind;      // Index in den Datenpuffer
17
volatile uint8_t max;      // Anzahl der zu sendenden Bytes bei Slave-Transmitter-Betrieb
18
19
/*
20
 * Die einzelnen Zustände der TWI-State-machine findet man in der Atmel Dokumentation.
21
 * Der Kommentar gibt die Ursache des Interrupts an.
22
 */
23
ISR(TWI_vect) {
24
  switch (TWSR & TW_STATUS_MASK) {
25
  // TW_SR.... Slave Receiver
26
  // Erkennung der eigene Adresse nach verschiedenen Startbedingungen
27
  case TW_SR_ARB_LOST_SLA_ACK:
28
  case TW_SR_ARB_LOST_GCALL_ACK:
29
  case TW_SR_GCALL_ACK:
30
  case TW_SR_SLA_ACK:
31
    ind = 0;
32
    // Adresse quittieren
33
    TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
34
    break;
35
  // Datenbyte erkannt und mit ACK quittiert
36
  case TW_SR_GCALL_DATA_ACK:
37
  case TW_SR_DATA_ACK:
38
    // Noch Platz im Puffer?
39
    if (ind < sizeof data) {
40
      data[ind++] = TWDR;
41
    }
42
    // Quittieren und nächstes Byte anfordern
43
    TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
44
    break;
45
  // NACK im Receiver-Mode führt zum Rücksetzen des TWI-Interfaces
46
  case TW_SR_GCALL_DATA_NACK:
47
  case TW_SR_DATA_NACK:
48
    TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
49
    ind = 0;
50
    break;
51
  // STOP erkannt: TWI-Interface in Grundstellung bringen.
52
  case TW_SR_STOP:
53
    TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
54
    ind = 0;
55
    break;
56
  // TW_ST.... Slave Transmitter
57
  // Adresse erkannt, erstes Byte (Länge) senden
58
  case TW_ST_ARB_LOST_SLA_ACK:
59
  case TW_ST_SLA_ACK:
60
    ind = 0;
61
    max = 8;    // Länge des Sendetelegramms
62
    TWDR = max;
63
    TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
64
    break;
65
  // Byte wurde quittiert, nächstes Byte ist angefordert
66
  case TW_ST_DATA_ACK:
67
    if (ind < max) {
68
      // Es sind noch Daten da, also ACK
69
      TWDR = data[32 + ind++];
70
      TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
71
    } else {
72
      // Zu viele Daten angefordert, also NACK
73
      TWCR = (1 << TWINT) | (0 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
74
    }
75
    break;
76
  // NACK bzw. ACK auf letztes Datenbyte erhalten: TWI-Interface in Grundstellung
77
  case TW_ST_DATA_NACK:
78
  case TW_ST_LAST_DATA:
79
    // hier die Daten verarbeiten. Z.B. umkopieren o.ä. Wenn es längere Aktionen sind, in das Hauptprogramm auslagern
80
    TWCR = (1 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
81
    ind = 0;
82
    break;
83
  }
84
}
85
86
int main(int argc, char** argv) {
87
  uint8_t i;
88
89
  DDRB = 0x00;
90
  PORTB = 0xff;
91
  DDRC = ((0 << DDC0) | (0 << DDC1) | (0 << DDC2) | (0 << DDC3) | (1 << DDC4) | (1 << DDC5));
92
  PORTC = ((1 << DDC0) | (1 << DDC1) | (1 << DDC2) | (1 << DDC3) | (0 << DDC4) | (0 << DDC5));
93
  DDRD = 0x00;
94
  PORTD = 0xff;
95
96
  for (i = 0; i < sizeof data; i++) {
97
    data[i] = i;
98
  }
99
100
  // Adressregister (TWAR) auf Adresse setzen. Achtung: 1x links schieben, da Bit 0 für Global call verwendet wird
101
  TWAR = (1 << 1);
102
  // Interrupt erlauben und ACK auf Adresse aktivieren
103
  TWCR = (0 << TWINT) | (1 << TWEA) | (0 << TWSTA) | (0 << TWSTO) | (1 << TWEN) | (1 << TWIE);
104
  sei();
105
106
  // alles läuft jetzt im Interrupt
107
  for (;;) {
108
  }
109
}
Grüße, Kurt

von XMEGA (Gast)


Lesenswert?

Hallo,

< TWI schrieb:
> Dazu habe ich jetzt ein paar allgemeine Fragen

schau dir mal die Seite an. Plus Beispieldateien!

http://www.kramann.info/73_COACH3/10_Ergaenzungen/02_I2C/index.php


Gruß XMEGA

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.