Forum: Mikrocontroller und Digitale Elektronik Seltsames Verhalten bei TWI Slave


von Stephan K. (dustpuppy)


Lesenswert?

Hi,
ich habe ein komisches Verhalten bei TWI Slaves. Wenn ich einem Atmega8 
als Slave im Interrupt Modus laufen lasse, dann kann ich ganz normal auf 
die zugewiesene Adresse zugreifen. Allerding ist ebenfalls die naechste 
Adresse vorhanden, die ich gar nicht vergeben habe. Dieser "virtuelle" 
Slave ist auch nicht beschreibbar.
Hier der Code, den ich verwende:
1
#include <util/twi.h>                 // Bezeichnungen fuer Statuscodes in TWSR
2
#include <avr/interrupt.h>               // behandlung der Interrupts
3
#include <stdint.h>                 // definiert Datentyp uint8_t
4
#include "twislave.h"                 
5
6
//#################################### Macros
7
//ACK nach empfangenen Daten senden/ ACK nach gesendeten Daten erwarten
8
#define TWCR_ACK   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);  
9
//NACK nach empfangenen Daten senden/ NACK nach gesendeten Daten erwarten     
10
#define TWCR_NACK   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(0<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);
11
//switched to the non adressed slave mode...
12
#define TWCR_RESET   TWCR = (1<<TWEN)|(1<<TWIE)|(1<<TWINT)|(1<<TWEA)|(0<<TWSTA)|(0<<TWSTO)|(0<<TWWC);  
13
//########################################################################################## init_twi_slave 
14
void init_twi_slave(uint8_t adr)
15
{
16
  TWAR= adr; //Adresse setzen
17
  TWCR &= ~(1<<TWSTA)|(1<<TWSTO);
18
  TWCR|= (1<<TWEA) | (1<<TWEN)|(1<<TWIE);   
19
  buffer_adr=0xFF;  
20
  sei();
21
}
22
23
//########################################################################################## 
24
//ISR (TWI_vect) 
25
//ISR, die bei einem Ereignis auf dem Bus ausgeloest wird. Im Register TWSR befindet sich dann 
26
//ein Statuscode, anhand dessen die Situation festgestellt werden kann.
27
ISR (TWI_vect)  
28
{
29
  uint8_t data=0;
30
  switch (TW_STATUS)
31
  {
32
    case TW_SR_SLA_ACK:
33
      TWCR_ACK;
34
      buffer_adr=0xFF;
35
      break;
36
37
      case TW_SR_DATA_ACK:
38
       data=TWDR;
39
       if (buffer_adr == 0xFF)
40
       {
41
         if(data<=buffer_size)
42
         {
43
          buffer_adr= data;
44
         }
45
         else
46
         {
47
           buffer_adr=0;
48
         }        
49
         TWCR_ACK;
50
       }
51
       else
52
       {
53
         rxbuffer[buffer_adr]=data;
54
         buffer_adr++;
55
         if(buffer_adr<(buffer_size-1))
56
         {
57
           TWCR_ACK;
58
         }
59
         else
60
         {
61
           TWCR_NACK;
62
         }
63
       }
64
       break;
65
66
      case TW_ST_SLA_ACK:
67
      case TW_ST_DATA_ACK:
68
        if (buffer_adr == 0xFF)
69
        {
70
          buffer_adr=0;
71
        }
72
        TWDR = txbuffer[buffer_adr];
73
        buffer_adr++;
74
        if(buffer_adr<(buffer_size-1))
75
        {
76
          TWCR_ACK;
77
        }
78
        else
79
        {
80
          TWCR_NACK;
81
        }
82
        break;
83
      case TW_ST_DATA_NACK:
84
      case TW_SR_DATA_NACK:
85
      case TW_ST_LAST_DATA:
86
      case TW_SR_STOP:
87
        default:   
88
        TWCR_RESET;
89
        break;  
90
    } //end.switch (TW_STATUS)
91
} //end.ISR(TWI_vect)

Die Ausgabe sieht dann so aus:
1
root@atmega8>twi poll
2
Address       : 0x32
3
Board type    : 0x00 (Servo Controller)
4
Board Version : 01.00.00
5
Data          : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
6
Address       : 0x33
7
Board type    : 0x34 (unknown)
8
Board Version : 34.34.34
9
Data          : 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34 34

Kann mir Jemand sagen, wo mein Fehler liegt und wo dieser zweite Slave 
herkommt?

Als Master verwende ich die Lib von Peter Fleury.

Gruesse

Dusty

von (prx) A. K. (prx)


Lesenswert?

Das unterste Bit einer 8-Bit I2C-Adresse ist das R/W-Bit, keine Adresse.

von Stephan K. (dustpuppy)


Lesenswert?

Ich hab's auch probiert mit TWAR= (adr << 1) um die Adresse nach oben zu 
verschieben. Das Komische ist, dann kann ich die Adresse nicht korrekt 
ansprechen, sondern aus Adresse 100 wird Adresse 201, die ich ansprechen 
kann mit lesen und schreiben. Als haette ich 255 Adressen zur 
verfuegung.

von (prx) A. K. (prx)


Lesenswert?

Es gibt bei I2C zwei Konventionen. Die einen betrachten die Adresse als 
8-Bit Wert, 2,4,6,8,...,254 und die anderen als 7-Bit Wert 
1,2,3,4,...,127, der in der Software irgendwo um ein Bit nach links 
geschoben wird. Wirst dich entscheiden müssen welche dir persönlich mehr 
liegt.

Nur solltest du drauf verzichten, bei der 8-Bit Version das untere Bit 
hoch zu zählen und bei der 7-Bit Variante über 127 hinaus zu gehen.

von Stephan K. (dustpuppy)


Lesenswert?

Das erklaert aber den zweiten Slave an der folgenden Adresse nicht.

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.