Forum: Mikrocontroller und Digitale Elektronik Auswahl I2C Bus Adresse durch DIP umschaltbar


von Paul (Gast)


Lesenswert?

Hallo
Möchte mit abn einem Attiny 841 verschiedene I2C Bus Adressen mit 
Dip-Scaltern bzw. Steckbrücken umschalten können. Leider ist die Suche 
auf Google und anderen Kanälen sehr spärlich.

Hardware:
A0 - PA1 mit Widerstand nach Vcc
A1 - PA2 mit Widerstand nach Vcc
jeweils nach GND schaltbar
1
#define Adress_G        // Slave Adresse Auswahl
2
#define Adress_1  0x32    // Slave Adresse 1
3
#define Adress_2  0x34    // Slave Adresse 2
4
#define Adress_3  0x36    // Slave Adresse 1+2
5
6
if ( PORTA &=~(1<<PINA1)    // A0 auf GND
7
  {                
8
  Adress_G = Adress_1;    // 0x32
9
  }
10
11
if ( PORTA &=~(1<<PINA2)    // A1 auf GND
12
  {
13
  Adress_G = Adress_2;    // 0x34
14
  }
15
16
if ((PORTA &=~(1<<PINA1))&(PORTA &=~(1<<PINA1)))    // A0 und A1 auf GND
17
  {
18
  Adress_G = Adress_3;    // 0x36
19
  }
Habe drei Adressen angegeben die jeweils nach Stellung der Pins 
ausgewählt werden können. Die Abfrage der Adresse erfolgt bereits am 
Anfang des Programmes. Da mit 2 Pins 4 Adressen möglich sind fehlt novh 
die Kombination Adress_4 wenn beide Dip offen sind.
Könnte das so gehn oder kennt jemand eine bessere Lösung dazu?
LG Paul

von leo (Gast)


Lesenswert?

Paul schrieb:
> if ( PORTA &=~(1<<PINA1)    // A0 auf GND

Was jetzt A0 oder A1?

leo

von leo (Gast)


Lesenswert?

Paul schrieb:
> if ( PORTA &=~(1<<PINA1)

Ah ja, &= ist eine Zuweisumg, kein Vergleich.

leo

von Route_66 H. (route_66)


Lesenswert?

Paul schrieb:
> Könnte das so gehn oder kennt jemand eine bessere Lösung dazu?
> LG Paul

PORTA mit 0x03 maskieren(AND 0x03), mal zwei nehmen, dazu 0x30 addieren 
und Adress_G zuweisen.
Dann hast Du für Adress_G den Wert von 36h bis 30h (weil invertiert).

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> Könnte das so gehn oder kennt jemand eine bessere Lösung dazu?
1
#define S1 (1<<PINA1)
2
#define S2 (1<<PINA2)
3
 
4
uint8_t Schalter = PORTA & (S1 | S2);
5
6
switch Schalter 
7
{
8
  case  0:    ...;
9
  case S1:    ...;
10
  case S2:    ...;
11
  case S1|S2: ...;
12
}

von Wolfgang (Gast)


Lesenswert?

Route_66 H. schrieb:
> PORTA mit 0x03 maskieren(AND 0x03), mal zwei nehmen, dazu 0x30 addieren
> und Adress_G zuweisen.

Wie kommst du drauf, dass (1<<PINA1)|(1<<PINA2) gleich 0x03 ist?

von Theor (Gast)


Lesenswert?

@ Paul

Nun, zufällig ergeben die beiden Schalter an PA1 und PA2 gerade die 
Werte, 0, 2, 4 und 6. Das kann man nutzen, denn Deine Adressen haben 
genau diese Abstände.
1
uint8_t Adress_G; // NICHT #define Adress_G
2
3
Adress_G = 0x30 + (PINA & 0x06);

wobei der Sonderfall (PINA & 0x06) == 0 damit nicht abgedeckt ist. Aber 
Du hast auch nicht geschrieben, was dann geschehen soll.


Falls die Adressen völlig unregelmäßige Abstände haben, kann man 
trotzdem noch die Tatsache nutzen, dass die Eingangswerte konstante 
Abstände haben.
1
uint8_t Adress_G;
2
uint8_t AdressArray[4] = {0, 0x43, 0xa4, 0x8f};
3
4
Adress_G = AdressArray[(PINA & 0x06) >> 1];

Eigentlich total einfach, oder?

von Paul (Gast)


Lesenswert?

Route_66 H. schrieb:
> PORTA mit 0x03 maskieren(AND 0x03), mal zwei nehmen, dazu 0x30 addieren
> und Adress_G zuweisen.
> Dann hast Du für Adress_G den Wert von 36h bis 30h (weil invertiert).

Die Adressen werden durch #define im ersten Teil vergeben. Können also 
irgendwelche Werte annehmen. Mit A0 und A1 habe ich die Dip-Schalter 
bezeichnet und beziehen sich nicht auf die Pins. Das habe ich in der 
Hardware angegeben.
1
#define Adress_G        // Slave Adresse Auswahl
2
#define Adress_1  0x32    // Slave Adresse 1
3
#define Adress_2  0x34    // Slave Adresse 2
4
#define Adress_3  0x36    // Slave Adresse 1+2
5
#define Adress_4  0x38    // Slave Adresse nicht 1+2
6
7
if ( PORTA &=~(1<<PINA1)    // A0 auf GND Dip Schalter
8
  {                
9
  Adress_G = Adress_1;    // 0x32
10
  }
11
12
if ( PORTA &=~(1<<PINA2)    // A1 auf GND Dip Schalter
13
  {
14
  Adress_G = Adress_2;    // 0x34
15
  }
16
17
if (((PORTA &=~(1<<PINA1))&(PORTA &=~(1<<PINA1)))  // A0 und A1 auf GND DIP Schalter
18
  {
19
  Adress_G = Adress_3;    // 0x36
20
  }
21
22
if (((PORTA |=(1<<PINA1))&(PORTA |=(1<<PINA2)))     // A0 und A1 nicht auf GND Dip Schalter
23
  {
24
  Adress_G = Adress_4;    // 0x38
25
  }

Beitrag #6049631 wurde vom Autor gelöscht.
von Route_66 H. (route_66)


Lesenswert?

Wolfgang schrieb:
> Wie kommst du drauf, dass (1<<PINA1)|(1<<PINA2) gleich 0x03 ist?

O.K. ich habe erst mal nur A0 und A1 gelesen, so ist die Maske 0x06 und 
das mal zwei entfällt.

von Theor (Gast)


Lesenswert?

Ups. Mein Code, invertiert die Bedeutung der Bits und gibt nicht das 
identische Verhalten von Deinem Code.
1
uint8_t Adress_G; // NICHT #define Adress_G
2
3
Adress_G = 0x30 + (~PINA & 0x06);
1
uint8_t Adress_G;
2
uint8_t AdressArray[4] = {0, 0x43, 0xa4, 0x8f};
3
4
Adress_G = AdressArray[(~PINA & 0x06) >> 1];

Allerdings wäre es einfacher, einfach die Bedeutung der Schalterstellung 
umzudrehen.
Naja. Das wird vermutlich nur einmal im Leben (nach dem Reset( 
ausgeführt. Aber in bisschen Code frisst die Negation doch.


Ach ja. Das "&=" in Deinem Code ist falsch. Du willst - vermutlich - 
nicht das invertierte Resultat wieder dem Port zuweisen.

von Andre (Gast)


Lesenswert?

Sind das zwei aufeinander folgende Pins?
Dann könntest du sowas machen:
uint8_t select = (PINA & 0b00000110) >> 1;

Das pickt sich die zwei Bits für Pin A1/A2 raus und richtet sie am LSB 
aus.
Das Ergebnis davon kannst du mit Switch/Case auswerten, die 
Schalterstellung steht dann binär 00/01/10/11 in "select".
Funktioniert aber nicht universell.

von Paul (Gast)


Lesenswert?

Sorry, bekomme eine Fehlermeldung die ich nicht verstehe.

if ( PORTA &=~(1<<PINA1))    // A0 auf GND Dip Schalter
  {
    Adress_G = Adress_1;  // 0x32
  }
ergibt den Fehler:
expected expression before '=' token

von Paul (Gast)


Lesenswert?

ES wird was anderes von Adress_G erwartet?

von leo (Gast)


Lesenswert?

Paul schrieb:
> ergibt den Fehler:
> expected expression before '=' token

Vielleicht solltest du meine Posts lesen.

leo

von Klaus R. (klara)


Lesenswert?

Paul schrieb:
> Möchte mit abn einem Attiny 841 verschiedene I2C Bus Adressen mit
> Dip-Scaltern bzw. Steckbrücken umschalten können.

Ein I2C - Baustein bringt doch von Haus aus bis zu drei Adress - Pins 
mit. Wozu speicherst Du die DIP - Einstellung in einer Variable? Bei mir 
gehe ich direkt vom DIP auf die Adress - Pins und gut ist es.
mfg Klaus.

von Paul (Gast)


Lesenswert?

Als Slave verwende ich einen Attiny 841. Der hat von Hause aus keine 
Adressen vergeben und muss im Programm eingestellt werden.

von Ernst (Gast)


Lesenswert?

Paul schrieb:
> ES wird was anderes von Adress_G erwartet?
Du solltest Dir erstmal im klaren sein, in welcher Zeile sich der Fehler 
befindet.

leo schrieb:
> Vielleicht solltest du meine Posts lesen.
Dem stimme ich zu.

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> if ( PORTA &=~(1<<PINA1)    // A0 auf GND Dip Schalter
> ...

Dieses endlose IF-Gezuzel ist doch Käse.

Andre schrieb:
> Das Ergebnis davon kannst du mit Switch/Case auswerten, ...

Aaach, lies mal weiter vorne im Thread

Wolfgang schrieb:

von Einer K. (Gast)


Lesenswert?

leo schrieb:
> Vielleicht solltest du meine Posts lesen.
? ? ?

> #define Adress_G        // Slave Adresse Auswahl
> Adress_G = Adress_4;


> ergibt den Fehler:
> expected expression before '=' token

Natürlich!
Ein solches, per define erzeugtes, ist ein Nichts, aus Sicht des 
Compilers.
Es kann kein Ziel einer Zuweisung sein.
Es ist kein lvalue und hat auch keine Chance jemals eins zu werden..

von Peter D. (peda)


Lesenswert?

Paul schrieb:
> if ( PORTA &=~(1<<PINA1)    // A0 auf GND

Mindestens 2 Fehler:
- Du wertest eine Zuweisung aus.
- Das Ausgangsregister (PORTA) wird nicht von den Eingangspins 
beeinflußt.

von Paul (Gast)


Lesenswert?

Habe es jetzt so gemacht:
1
uint8_t I2C_SLAVE_ADDRESS;  
2
void adresswahl()
3
  {  
4
    if (PORTA &=~(1<<PINA1))    // A0 auf GND Dip Schalter
5
      {                
6
        I2C_SLAVE_ADDRESS = Adress_1;
7
    }
8
    if ( PORTA &=~(1<<PINA2))    // A1 auf GND Dip Schalter
9
      {
10
      I2C_SLAVE_ADDRESS = Adress_2;    // 0x34
11
      }
12
    if ((PORTA &=~(1<<PINA1))&(PORTA &=~(1<<PINA1)))  // A0 und A1 auf GND DIP Schalter
13
      {
14
      I2C_SLAVE_ADDRESS = Adress_3;    // 0x36
15
      }
16
    if ((PORTA |=(1<<PINA1))&(PORTA |=(1<<PINA2)))     // A0 und A1 nicht auf GND Dip Schalter
17
      {
18
      I2C_SLAVE_ADDRESS = Adress_4;    // 0x38
19
      }
20
  }
Gehe da von aus, wenn der Dip-Schalter den PIN A1 auf GND legt die 
Bedingung erfüllt ist und if=1 ist.

von Einer K. (Gast)


Lesenswert?

Paul schrieb:
> if ((PORTA &=~(1<<PINA1))&(PORTA &=~(1<<PINA1)))

Was tust du da?
Mir fehlt dafür jegliches Verständnis.
Mit Dip-Schalter auslesen hat das doch nichts zu tun, oder?

von Egonwalter M. (heiner1234)


Lesenswert?

Hallo Paul

Du solltest den Beitrag von Peter.D (peda)

Peter D. schrieb:
> Paul schrieb:
>> if ( PORTA &=~(1<<PINA1)    // A0 auf GND
>
> Mindestens 2 Fehler:
> - Du wertest eine Zuweisung aus.
> - Das Ausgangsregister (PORTA) wird nicht von den Eingangspins
> beeinflußt.

mal überdenken.

Außerdem die Sache mit den Bit-Operationen (ebenfalls Beitrag von peda - 
siehe "Taster entprellen")

Hast Du das von Dir geschriebene schon mal am "lebendigen Objekt" 
getestet??

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

Ja, habe das Programm auf der Hardware zu laufen.
Einen Fehler habe ich gefunden. Hatte die Reihenfolge von

adresswahl();
I2C_init();

falsch herum drin

von Paul (Gast)


Lesenswert?

Vergesst den ersten Teil. Keine Ahnung wie ich das falsch gemacht habe
1
uint8_t I2C_SLAVE_ADDRESS;  
2
void adresswahl()
3
  {  
4
  if (!(PINA & (1<<PINA1)))    // A0 auf GND Dip Schalter
5
      {                
6
        I2C_SLAVE_ADDRESS = Adress_1;    // 0x32
7
    }
8
    if (!(PINA & (1<<PINA2)))    // A1 auf GND Dip Schalter
9
      {
10
      I2C_SLAVE_ADDRESS = Adress_2;    // 0x34
11
      }  
12
  if (!((PINA & (1<<PINA1))&(PINA & (1<<PINA2))))// A0 und A1 auf GND DIP Schalter
13
      {
14
      I2C_SLAVE_ADDRESS = Adress_3;    // 0x36
15
      }  
16
  if ((PINA & (1<<PINA1))&(PINA & (1<<PINA2)))  // A0 und A1 nicht auf GND Dip Schalter
17
      {
18
      I2C_SLAVE_ADDRESS = Adress_4;    // 0x38
19
      }
20
  }
damit wird die Busaderesse 0x34 und 0x36 erkannt

von leo (Gast)


Lesenswert?

Paul schrieb:
> if ((PINA & (1<<PINA1))&(PINA & (1<<PINA2)))

So, jetzt kannst du noch den Unterschied von logischen und binaeren 
Operatoren nachschlagen und anwenden.

leo

von Peter D. (peda)


Lesenswert?

Wolfgang schrieb:
> #define S1 (1<<PINA1)
> #define S2 (1<<PINA2)
>
> uint8_t Schalter = PORTA & (S1 | S2);
>
> switch Schalter
> {
>   case  0:    ...;
>   case S1:    ...;
>   case S2:    ...;
>   case S1|S2: ...;
> }

Fast richtig.
1
#define S1 (1<<PINA1)
2
#define S2 (1<<PINA2)
3
 
4
uint8_t Schalter = PINA & (S1 | S2);
5
6
switch Schalter 
7
{
8
  case  0:    ...;
9
  case S1:    ...;
10
  case S2:    ...;
11
  case S1|S2: ...;
12
}

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> damit wird die Busaderesse 0x34 und 0x36 erkannt

Man muss auch mal Glück haben, aber verstanden hast du wohl nicht, was 
du hier geschrieben hast:

> if (!((PINA & (1<<PINA1))&(PINA & (1<<PINA2))))// A0 und A1 auf GND
> DIP Schalter

von Paul (Gast)


Lesenswert?

Wolfgang schrieb:
> if (!((PINA & (1<<PINA1))&(PINA & (1<<PINA2))))

Damit will ich PINA1 "und" PINA2 negieren. Wenn beide auf GND liegen 
soll if schalten

von Wolfgang (Gast)


Lesenswert?

Peter D. schrieb:
> Fast richtig.

Stimmt, die break -Befehle sollten nicht fehlen

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> Wenn beide auf GND liegen soll if schalten

Auch wenn nicht beide auf Gnd liegen, kommt bei
(PINA & (1<<PINA1))&(PINA & (1<<PINA2)) ein 0x00 raus.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Paul schrieb:
> Da mit 2 Pins 4 Adressen möglich sind fehlt novh die Kombination
> Adress_4 wenn beide Dip offen sind.
> Könnte das so gehn oder kennt jemand eine bessere Lösung dazu?
Wenn die beiden Bits so geschickt nebeneinander liegen, dann lese ich 
die parallel ein und addiere den ermittelten Wert zum Offset 0x30:
1
 uint8_t adresse = 0x30 + (PINA & 0x6);
Das ergibt je nach Schalterstellung die Adressen 0x30, 0x32, 0x34 oder 
0x36 und man muss letztlich nur noch die entsprechende Doku so 
schreiben, dass sie zu den Schalterstellungen passt.

Wenn die Doku leider vorher schon ohne über die Hardware nachzudenken 
geschrieben wurde, ist das echt "Pech" und man muss den passenden 
programmtechnischen Eiertanz machen. Daraus kann man für die Zukunft 
lernen...

von Eric B. (beric)


Lesenswert?

Peter D. schrieb:
> switch Schalter

Fast richtig ;-)
1
switch(Schalter)

von Wolfgang (Gast)


Lesenswert?

Eric B. schrieb:
> Fast richtig ;-)

Das sollte Pseudo-Code sein, kein C ;-)

von Paul (Gast)


Lesenswert?

Mit diesem Code kann ich die 4 möglichen Adressen einstellen.
1
uint8_t I2C_SLAVE_ADDRESS;  
2
void adresswahl()
3
  {  
4
  if (!(PINA & (1<<PINA1)))      // A0 auf GND Dip Schalter
5
      {                
6
        I2C_SLAVE_ADDRESS = Adress_1;  // 0x32
7
    }
8
    if (!(PINA & (1<<PINA2)))      // A1 auf GND Dip Schalter
9
      {
10
      I2C_SLAVE_ADDRESS = Adress_2;  // 0x34
11
      }  
12
    
13
  if ((!(PINA & (1<<PINA1))) && (!(PINA & (1<<PINA2))))// A0 und A1 auf GND DIP Schalter
14
      {
15
      I2C_SLAVE_ADDRESS = Adress_3;  // 0x36
16
      }  
17
    
18
  if ((PINA & (1<<PINA1)) && (PINA & (1<<PINA2)))  // A0 und A1 nicht auf GND Dip Schalter
19
      {
20
      I2C_SLAVE_ADDRESS = Adress_4;  // 0x38
21
      }  
22
  }
Versuchen wir noch die zweite Version

von Karl M. (Gast)


Lesenswert?

Hallo Code soll auch lesbar und somit auch einfach kontrollierbar, für 
andere sein.
Somit bleibt nur diese Variante der Kodierung übrig.
Peter D. schrieb:
> #define S1 (1<<PINA1)
> #define S2 (1<<PINA2)
>
> uint8_t Schalter = PINA & (S1 | S2);
>
> switch (Schalter)
> { // S[2,1] betrachtet die Eingangsmenge der Schalterstellung(en) von S2 und S1
>   case  0:    ...; // S[2,1] == 0b00
>     break;
>   case S1:    ...; // S[2,1] == 0b01
>     break;
>   case S2:    ...; // S[2,1] == 0b10
>     break;
>   case S1|S2: ...; // S[2,1] == 0b11
>     break;
> }

Man kann natürlich beim lesen von PINA, dessen Werte mit NOT (in C: !) 
negieren.

von leo (Gast)


Lesenswert?

Karl M. schrieb:
> PINA, dessen Werte mit NOT (in C: !)
> negieren.

Kann man, ist aber falsch. Der naechste, der sich den Unterschied von 
logischen und binaeren Operatoren aneignen sollte.

leo

von Wolfgang (Gast)


Lesenswert?

Karl M. schrieb:
>   case S1:    ...; // S[2,1] == 0b01
> ...
Deine Kommentare stimmen nicht mehr, sobald die Schalter auf anderen 
Bits liegen - schon wieder so eine Kommentarfalle.

von Paul (Gast)


Lesenswert?

Haeb die Auswahl für die Adresse auf 3 Schalter erweitert und kann somit 
zwischen 8 Busadressen auswählen.

von Paul (Gast)


Lesenswert?

Habe die Sache mit switch umgesetzt. Ist aber noch ein Denkfehler drin.
1
void auswahl_sw()
2
{
3
 uint8_t Schalter = PINA & (S1 | S2);
4
5
 switch (Schalter)
6
   {              // betrachtet die Eingangsmenge der Schalterstellung(en) von S1 und S2
7
     case  0:    I2C_SLAVE_ADDRESS = Adress_1;    // Adresse 0x22 A0 auf GND
8
       break;
9
     case S1:    I2C_SLAVE_ADDRESS = Adress_2;    // Adresse 0x24 A1 auf GND
10
       break;
11
     case S2:    I2C_SLAVE_ADDRESS = Adress_3;    // Adresse 0x26
12
       break;
13
     case S1|S2: I2C_SLAVE_ADDRESS = Adress_4;    // Adresse 0x28 A0 + A1 auf GND
14
       break;
15
   }
16
}
Es ergeben sich nicht die gewünschten Adressen mit den beiden S1 und S2. 
Die Ergebnisse habe ich als Kommentar angegeben.

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> Die Ergebnisse habe ich als Kommentar angegeben.

Versteh' ich nicht. Sind deine Adressen immer noch die selben?
Zeig mal das komplette Programm.

Paul schrieb:
> #define Adress_1  0x32    // Slave Adresse 1
> #define Adress_2  0x34    // Slave Adresse 2
> #define Adress_3  0x36    // Slave Adresse 1+2

von Paul (Gast)


Lesenswert?

Hatte vorher mit if auf 8 Adressen erweitert. Jetzt sieht es so aus:
1
#define Adress_1  0x22    // Slave Adresse 1
2
#define Adress_2  0x24    // Slave Adresse 2
3
#define Adress_3  0x26    // Slave Adresse 3
4
#define Adress_4  0x28    // Slave Adresse 1+2
5
6
uint8_t I2C_SLAVE_ADDRESS;  
7
8
#define S1 (1<<PINA1)
9
 #define S2 (1<<PINA2)
10
11
void auswahl_sw()
12
{
13
 uint8_t Schalter = PINA & (S1 | S2);
14
15
 switch (Schalter)
16
   {              // betrachtet die Eingangsmenge der Schalterstellung(en) von S1 und S2
17
     case  0:    I2C_SLAVE_ADDRESS = Adress_1;    // Adresse 0x22 A0 auf GND
18
       break;
19
     case S1:    I2C_SLAVE_ADDRESS = Adress_2;    // Adresse 0x24 A1 auf GND
20
       break;
21
     case S2:    I2C_SLAVE_ADDRESS = Adress_3;    // Adresse 0x26
22
       break;
23
     case S1|S2: I2C_SLAVE_ADDRESS = Adress_4;    // Adresse 0x28 A0 + A1 auf GND
24
       break;
25
   }
26
}
27
28
auswahl_sw();
29
I2C_init();
habe nur die Adressen geändert. Eine Auswahl erfolgt ja, nur eben 
falsch.
Habe die Teile hier nicht drin die funktionieren z.B. Timer und ISR.

von Paul (Gast)


Lesenswert?

1
#define Adress_1  0x22    // Slave Adresse 1
2
#define Adress_2  0x24    // Slave Adresse 2
3
#define Adress_3  0x26    // Slave Adresse 3
4
#define Adress_4  0x28    // Slave Adresse 1+2
5
#define Adress_5  0x30    // Slave Adresse 1+3
6
#define Adress_6  0x32    // Slave Adresse 2+3
7
#define Adress_7  0x34    // Slave Adresse 1+2+3
8
#define Adress_8  0x36    // Slave Adresse nicht 1+2+3
9
10
switch (Schalter)
11
   {              // betrachtet die Eingangsmenge der Schalterstellung(en) von S1 und S2
12
     case  0:    I2C_SLAVE_ADDRESS = Adress_1;    // Adresse 0x22 A0 auf GND
13
       break;
14
     case S1:    I2C_SLAVE_ADDRESS = Adress_2;    // Adresse 0x24 A1 auf GND
15
       break;
16
     case S2:    I2C_SLAVE_ADDRESS = Adress_3;    // Adresse 0x36 bei A0 und A1 auf Vcc (offen)
17
       break;
18
     case S1|S2: I2C_SLAVE_ADDRESS = Adress_4;    // Adresse 0x28 A0 + A1 auf GND
19
       break;
20
   }
alle verwendeten Adressen
bei Adresse 3 ergibt sich 0x36

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> Habe die Teile hier nicht drin die funktionieren z.B. Timer und ISR.

Wenigstens die Programmstruktur sollte sichtbar sein.

Lass dir am Ende von der Funktion auswahl_sw() die Werte für Schalter 
und I2C_SLAVE_ADDRESS mal ausgeben, am besten in Hex.

Deine Kommentare bzg. dem Wert von A0 und A1 passen so gar nicht.

von Paul (Gast)


Lesenswert?

Es fehlen nur wenige Zeilen. In der kompletten Version stecken ca. 2 
Seiten mit auskommentierten Teilen.
1
#define F_CPU 8000000        // CPU clock in Hz
2
3
#include <avr/interrupt.h>  // dient zur Behandlung der Interrupts
4
#include <avr/io.h>         // Integer-Definitionen
5
6
#define I2C_DATA_INTERRUPT      0x80  // 0x80
7
#define I2C_BUS_COLLISION       0x08  // 0x08
8
#define I2C_ADDRESS_STOP_MATCH  0x40  // 0x40
9
10
volatile uint8_t command;
11
volatile uint8_t tx_buf[2];  // 4
12
volatile uint8_t tx_buff = 11;  // 4
13
volatile uint8_t tx_buf_index = 0;
14
15
#define Adress_1  0x22    // Slave Adresse 1
16
#define Adress_2  0x24    // Slave Adresse 2
17
#define Adress_3  0x26    // Slave Adresse 3
18
#define Adress_4  0x28    // Slave Adresse 1+2
19
#define Adress_5  0x30    // Slave Adresse 1+3
20
#define Adress_6  0x32    // Slave Adresse 2+3
21
#define Adress_7  0x34    // Slave Adresse 1+2+3
22
#define Adress_8  0x36    // Slave Adresse nicht 1+2+3
23
24
uint8_t I2C_SLAVE_ADDRESS;  
25
26
 #define S1 (1<<PINA1)
27
 #define S2 (1<<PINA2)
28
29
void auswahl_sw()
30
{
31
 uint8_t Schalter = PINA & (S1 | S2);
32
33
 switch (Schalter)
34
   {              // betrachtet die Eingangsmenge der Schalterstellung(en) von S1 und S2
35
     case  0:    I2C_SLAVE_ADDRESS = Adress_1;    // Adresse 0x22 A0 auf GND
36
       break;
37
     case S1:    I2C_SLAVE_ADDRESS = Adress_2;    // Adresse 0x24 A1 auf GND
38
       break;
39
     case S2:    I2C_SLAVE_ADDRESS = Adress_3;    // Adresse 0x36 bei A0 und A1 auf Vcc (offen)
40
       break;
41
     case S1|S2: I2C_SLAVE_ADDRESS = Adress_4;    // Adresse 0x28 A0 + A1 auf GND
42
       break;
43
   }
44
}
45
46
int main(void)
47
  {  
48
  DDRA=0b00000000;      // Port A auf Ausgang schalten
49
  PORTA=0b00000000;      // Port A auf aus 
50
  DDRB=0b00000011;      // Port A auf Ausgang schalten
51
  PORTB=0b00000011;      // Port A auf aus  
52
    
53
  auswahl_sw();
54
  I2C_init();
55
  
56
  
57
  while(1)
58
    {
59
    if (command != 42)           // Taster T2 PD0
60
     {                    // Wenn T1 gedrückt...
61
       PORTA &=~(1<<PINA1);        // LED 2 ein  
62
     }
63
     else
64
    {                    // wenn nicht
65
       PORTA |=(1<<PINA1);          // LED 2 ein ??
66
    }  
67
     if (command != 43)           // Taster T2 PD0
68
    {                    // Wenn T1 gedrückt...
69
      PORTA &=~(1<<PINA0);        // LED 2 aein
70
    }
71
     else
72
    {                    // wenn nicht  
73
      PORTA |=(1<<PINA0);          // LED 2 ein ??
74
    }   
75
    
76
    {
77
    
78
      {
79
        
80
        
81
    // ========>> TASTENEINGABEN T3
82
    if (!(PINA & (1<<PINA7)) )            // Taster T 3
83
      {                  // Wenn T3 gedrückt...
84
      tx_buff = 5;  // 4
85
      }
86
    
87
    // ========>> TASTENEINGABEN T2
88
    if (!(PINB & (1<<PINB2)) )            // Taster T 3
89
      {                  // Wenn T3 gedrückt...
90
      tx_buff = 3;  // 4
91
      }    
92
      }
93
    }   
94
    }
95
  }
Den Timer und den I2C init ist nicht drin. In der Version mit if 
funktioniert es ohne Probleme. A0 und A1 können nicht passen, da sie 
keine Pins bezeichnen sondern die Dip Schalter sind zum schalten der 
Adresse.
Bei dieser Hardware habe ich kein Display dran. Das Auslesen der I2C 
Adresse erfolgt mit dem Bus und wird am Master durch einen Bus Scanner 
angezeigt.

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> A0 und A1 können nicht passen, da sie
> keine Pins bezeichnen sondern die Dip Schalter sind zum schalten der
> Adresse.

Das meine ich nicht.

Es kann nicht sein, das die Variable Schalter den Wert 0 annimmt, wenn 
nur A0 auf Gnd liegt.
Genauso wenig kann es sein, das Schalter == S1|S2 wird, wenn A0 und A1 
auf Gnd liegen.

von Joachim B. (jar)


Lesenswert?

Paul schrieb:
> #define Adress_1  0x22    // Slave Adresse 1
>
> switch (Schalter)
>    {              // betrachtet die Eingangsmenge der
> Schalterstellung(en) von S1 und S2
>      case  0:    I2C_SLAVE_ADDRESS = Adress_1;    // Adresse 0x22 A0 auf
> GND
>        break;

warum dass denn?
#define Adress_1  0x22    // Slave Adresse 1

ist doch sowas von unnötig, kannst auch gleich schreiben
case 0x22:    I2C_SLAVE_ADDRESS = 0x22;    // Adresse 0x22 A0 auf
break;
usw.

so mache ich das
1
#if (ARDUINO>0)
2
  DEBUG_PRINTLN(F(" -> Scanning..."));
3
4
#if defined (I2C_TASTATUR_8574) || defined (I2C_TASTATUR_8574A)
5
  char _i2c_key=0;
6
#endif
7
  byte error, address;
8
  int nDevices=0;
9
  for(address = 1; address < 127; address++ ) 
10
  { // The i2c_scanner uses the return value of
11
    // the Write.endTransmisstion to see if
12
    // a device did acknowledge to the address.
13
    Wire.beginTransmission(address);
14
    error = Wire.endTransmission();
15
16
    if (error == 0)
17
    { DEBUG_PRINT(F("I2C device found at address 0x"));
18
      if (address<16) 
19
        DEBUG_PRINT(F("0"));
20
      DEBUG_PRINT_DEC_HEX(address,HEX);
21
      DEBUG_PRINT(F("; "));
22
      if (address<64) 
23
        DEBUG_PRINT(F("0"));
24
      DEBUG_PRINT_DEC_HEX(address,BIN);
25
      DEBUG_PRINT(F("x; << 0x"));
26
      DEBUG_PRINT_DEC_HEX((address<<1),HEX);
27
      DEBUG_PRINT(F("; "));
28
      if ((address<<1)<128) 
29
        DEBUG_PRINT(F("0"));
30
      DEBUG_PRINT_DEC_HEX((address<<1),BIN);
31
      
32
      switch(address<<1)
33
      {
34
        case 0x40:
35
#ifdef I2C_TASTATUR_8574
36
          i2c_test_flags|=(1<<I2C_TASTATUR_8574);
37
//          i2c_test_flags|=(1<<I2C_TASTATUR);
38
//          _i2c_key=' ';
39
#endif // #ifdef I2C_TASTATUR_8574
40
          DEBUG_PRINTLN(F(" PCF8574  Tastatur"));
41
          break;
42
        case 0x70:
43
#ifdef I2C_TASTATUR_8574A
44
          i2c_test_flags|=(1<<I2C_TASTATUR_8574A);
45
//          i2c_test_flags|=(1<<I2C_TASTATUR);
46
//          _i2c_key='A';
47
#endif // #ifdef I2C_TASTATUR_8574A
48
          DEBUG_PRINTLN(F(" PCF8574A Tastatur"));
49
          break;
50
        case 0xA0:
51
          DEBUG_PRINTLN(F(" I2C EEPROM       "));
52
          i2c_test_flags|=(1<<I2C_EEPROM);          
53
          break;
54
        case 0xD0:
55
          //Wire.beginTransmission(DS1307_ID);
56
          //printIIC(0x3F);
57
          /*(Wire.endTransmission()) ?*/ i2c_test_flags|=(1<<I2C_RTC_3231) /*: i2c_test_flags|=(1<<I2C_RTC_1307)*/;
58
          #ifdef DEBUG
59
          if(i2c_test_flags&(1<<I2C_RTC_3231)) 
60
            Serial.println(F(" DS3231 RTC "));
61
          #endif
62
          break;
63
        default:
64
          DEBUG_PRINTLN(F(""));
65
          break;
66
      }
67
      nDevices++;
68
    }
69
    else if (error==4) 
70
    { DEBUG_PRINT(F("Unknow error at address 0x"));
71
      if (address<16) 
72
        DEBUG_PRINT(F("0"));
73
      DEBUG_PRINTLN_DEC_HEX(address,HEX);
74
    }    
75
  }
76
  if (nDevices == 0)
77
    DEBUG_PRINTLN(F("No I2C devices found"));
78
  else
79
    DEBUG_PRINTLN(F("done"));
80
  DEBUG_PRINTLN(F(""));
81
#endif

muss nur erweitert werden auf alle möglichen switch Adressen

: Bearbeitet durch User
von Paul (Gast)


Lesenswert?

Paul schrieb:
> switch (Schalter)
>    {              // betrachtet die Eingangsmenge der
> Schalterstellung(en) von S1 und S2
>      case  0:    I2C_SLAVE_ADDRESS = Adress_1;    // Adresse 0x22 A0 auf
> GND
>        break;
>      case S1:    I2C_SLAVE_ADDRESS = Adress_2;    // Adresse 0x24 A1 auf
> GND
>        break;
>      case S2:    I2C_SLAVE_ADDRESS = Adress_3;    // Adresse 0x36 bei A0
> und A1 auf Vcc (offen)
>        break;
>      case S1|S2: I2C_SLAVE_ADDRESS = Adress_4;    // Adresse 0x28 A0 +
> A1 auf GND
>        break;
>    }

Habe es so übernommen wie es als Hinweis von Peter und dir drin waren.
So wie du es schreibst geb ich dir Recht.
Wie kann ich es den besser machen?

von Eric B. (beric)


Lesenswert?

Paul schrieb:
> Wie kann ich es den besser machen?

Angenommen die DIP-switches liegen an PINA2, PINA1 und PINA0:
1
uint8_t i2c_addresses[] = {
2
  //       A2|A1|A0 - DIP switches
3
  0x22, //  0  0  0        0 = GND
4
  0x24, //  0  0  1        1 = Vcc
5
  0x26, //  0  1  0
6
  0x28, //  0  1  1
7
  0x30, //  1  0  0
8
  0x32, //  1  0  1
9
  0x34, //  1  1  0
10
  0x36, //  1  1  1
11
};
12
13
void auswahl_sw()
14
{
15
  I2C_SLAVE_ADRESS = i2c_addresses[PINA & 0x07];
16
}

Und sicher stellen, dass du auch wirklich diese Pins benutzt! Deine 
Kommentare und der Code widersprechen sich (A0/A1 vs A!/A2).
Und wie willst du an diesen Portpins (A0-A2) sowohl die switches 
auslesen als auch gleichzeitig eine LED leuchten lassen?

von Paul (Gast)


Lesenswert?

Eric B. schrieb:
> Und wie willst du an diesen Portpins (A0-A2) sowohl die switches
> auslesen als auch gleichzeitig eine LED leuchten lassen?

Hast du da was verwechselt?
Ich verwende nur die PINS PA1 - A0, PA2 - A1, PA2 - A2 als Eingang. 
Dabei sind A0, A1 und A2 die Dip Schalter auf der Platine um die I2C 
Adresse einzustellen. PA1, PA2 und PA3 sind die Pins am Attiny 841 und 
werden nur als Eingang benutzt, nicht als Ausgang. Dabei sind die PINS 
PA1, PA2 und PA2 mit Widerständen nach Vcc (5V) gelegt und werden durch 
die Dips auf GND gelegt und sollen damit erkannt werden.
Weiter oben habe ich den Code drin, mit if (..). der sehr gut 
funktioniert. Auf Vorschlag von Peter wollte ich das ganze nocht mit 
switch machen, da es einfacher sein soll (wenn es funktioniert).
LG Paul

von Wolfgang (Gast)


Lesenswert?

Paul schrieb:
> Wie kann ich es den besser machen?

Die Kommentare passen nicht zum Wert von der Variablen Schalter (case 
..)
Den I²C-Adressen geht es meglicherweise nicht besser, je nachdem, ob 
deine Erwartungshalten sich auf den Programmcode oder auf die Kommentare 
stützt.

von Paul (Gast)


Lesenswert?

Noch mal, die Bezeichnungen A0, A1 und A2 beziehen sich nur auf die Dip 
Schalter um die Adressen einzustellen. Das wird auch bei anderen ICs 
verwendet z.B. PCF usw. Diese Bezeichnzngen haben nichts mit den 
Eingangspins oder Ports zu tun.
Habe es jetzt auf 3 Dip Schalter erweitert und noch mal alle 
Kombinationen durchgestet. Dabei ist das rausgekommen.
1
#define S1 (1<<PINA1)
2
 #define S2 (1<<PINA2)
3
 #define S3 (1<<PINA3)
4
5
void auswahl_sw()
6
  {
7
    uint8_t Schalter = PINA & (S1 | S2 | S3);
8
    switch (Schalter)
9
      {              // betrachtet die Eingangsmenge der Schalterstellung(en) von S1 und S2 und S3
10
      case  0:    I2C_SLAVE_ADDRESS = Adress_1;    // Adresse 0x22, A0 und A1 und A2 auf GND, keiner offen
11
        break;
12
      case S1:    I2C_SLAVE_ADDRESS = Adress_2;    // Adresse 0x24, A1 und A2 auf GND, A1 offen
13
        break;
14
      case S2:    I2C_SLAVE_ADDRESS = Adress_3;    // Adresse 0x26, A0 und A2 auf GND, A1 offen
15
        break;
16
      case S3:    I2C_SLAVE_ADDRESS = Adress_4;    // Adresse 0x28, A0 und A1 auf GND, A2 offen
17
        break;
18
      case S1|S2:    I2C_SLAVE_ADDRESS = Adress_5;    // Adresse 0x30, A2 auf GND, A0 + A1 offen 
19
        break; 
20
      case S2|S3:    I2C_SLAVE_ADDRESS = Adress_6;    // Adresse 0x32, A0 und A1 auf GND, A1 + A2 offen
21
        break;
22
      case S1|S3:    I2C_SLAVE_ADDRESS = Adress_7;    // Adresse 0x34, A1 auf GND, A0 und A2 offen
23
        break;      
24
      case S1|S2|S3: I2C_SLAVE_ADDRESS = Adress_8;    // Adresse 0x36, A0 + A1 + A2 auf Vcc, alle offen
25
        break;
26
      }
27
  }
wenn ich mir die Busadressen dabei anschaue, sind sie nur verkehrt herum 
(negiert).
Einfach die Schalter negieren?

Beitrag #6055100 wurde vom Autor gelöscht.
von Eric B. (beric)


Lesenswert?

Paul schrieb:
> Ich verwende nur die PINS PA1 - A0, PA2 - A1, PA2 - A2 als Eingang.

Und auch un die LEDs anzusteuern. In deiner main()-Funktion steht doch:

Paul schrieb:
> if (command != 42)           // Taster T2 PD0
>      {                    // Wenn T1 gedrückt...
>        PORTA &=~(1<<PINA1);        // LED 2 ein
>      }
>      else
>     {                    // wenn nicht
>        PORTA |=(1<<PINA1);          // LED 2 ein ??
>     }
>      if (command != 43)           // Taster T2 PD0
>     {                    // Wenn T1 gedrückt...
>       PORTA &=~(1<<PINA0);        // LED 2 aein
>     }
>      else
>     {                    // wenn nicht
>       PORTA |=(1<<PINA0);          // LED 2 ein ??
>     }

von Paul (Gast)


Lesenswert?

Dein zitierter Teil ist vollkommen falsch. Es stammt aus einem anderen 
Programm und wird hier überhaupt nicht(mehr) verwendet. Es geht hierbei 
nur um die Abfrage der gesetzten Dip Schalter um die I2C Bus Adresse zu 
erkennen.
Hatte aber mehrfach darauf hingewiesen.

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.