Forum: Mikrocontroller und Digitale Elektronik Abfrage Taster durch USI vom Slave mit zwei AVR


von Peer (Gast)


Lesenswert?

Hallo
In einer kleinen Schaltung verwende ich einen Atmega 128 als Master. 
Dabei sind die Pins PC5 und PC6 mit LEDs beschaltet.
Als Slave benutze ich einen Attiny2313. Bei ihm ist der Pin PD0 mit 
einem Taster belegt. Zur Kontrolle erfogt ein schalten einer LED an PD5.
Das senden von Daten vom Master zum Slave klappt ohne Probleme.
Aber vom Slave zum Master erfogt keine Anzeige.
Im Slave verwende ich das:
1
if (PIND & (1<<PIND0))           // Taster T2 PD0
2
      {                    // Wenn T1 gedrückt...
3
      byte3=40;              // setze byte3 auf 40
4
      PORTD |=(1<<PIND3);          // LED 4 D5 aus  
5
      }
6
    else
7
      {
8
      PORTD &=~(1<<PIND3);        // LED 4 D5 ein
9
      byte4=30;              // setze byte4 auf 30
10
      }
11
    txbuffer[0]=byte3;            // byte10 in den Sendepuffer auf [0]
12
    txbuffer[1]=byte4;
Vom Master erfolgt die Abfrage ob Taster gedrückt wird damit:
1
void s_read1()                // lese Slave1
2
    {
3
      i2c_start(slave_adresse);        // Start Bus schreiben
4
      i2c_write(0x00);          
5
      i2c_rep_start(slave_adresse);        // starte Slave lesen
6
      byte3=i2c_readAck();          // 2. Byte lesen und in "gelesen" ablegen
7
      byte4=i2c_readNak();          // letztes Byte lesen, darum kein ACK
8
      i2c_stop();                // Zugriff beenden  
9
    }
und damit die Auswertung und Anzeige:
1
s_read1();    
2
      
3
        if (byte4 == 30)        
4
          {                  // Wenn Wert 30 gelesen wurde...
5
            PORTC &= ~( (1<<PINC5));    // schalte Port A6  
6
        PORTC |=(1<<PINC6);        // wenn nicht lösche Port A6  
7
          }
8
        else
9
          {  
10
          PORTC |=(1<<PINC5);        // wenn nicht lösche Port A6
11
        PORTC &= ~( (1<<PINC6));    // schalte Port A6  
12
          }
Als Slave Adresse benutze ich 50, Ein- und Ausgäne sind frei gegeben bzw 
eingestellt.
Es erfogt keine Auswertung des Tasters auf dem Slave und damit keine 
Anzeige bzw. keine Umschaltung.
Leider kann ich meinen Fehler nicht finden.
LG Peer

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Peer schrieb:
> if (PIND & (1<<PIND0))           // Taster T2 PD0
>       {                    // Wenn T1 gedrückt...
>       byte3=40;              // setze byte3 auf 40

Hast Du Dir mal Deine Kommentare angesehen?

von Peer (Gast)


Lesenswert?

Vergiss bitte die Kommentare. Die stimmen gar nicht und muss sie noch 
mal überarbeiten

von Peer (Gast)


Lesenswert?

Kann mir jemand helfen?

von Max D. (max_d)


Lesenswert?

Hast du einen logic-analyzer? (für i2c tut ein 10€ saleae-klon mit 
pulseview)

Außerdem: ganzen Code anhängen. uc.net bietet die Option mehrere Dateien 
anzuhängen (auch sourcen).

von Peter D. (peda)


Lesenswert?

Peer schrieb:
> Leider kann ich meinen Fehler nicht finden.

Dann gehe systematisch bei der Fehlersuche vor.
Laß den Slave konstante Daten senden und gib sie vom Master über die 
UART oder auf ein LCD aus.
Und gibt erstmal aus, ob den Master überhaupt den Slave adressiert.
Immer schön Schritt für Schritt debuggen.

Aus dem Zusammenhang herausgerissene Schnipselchen mit falschen 
Kommentaren kannst Du Dir sparen. Wer soll damit was anfangen können?
Wenn Du Code postest, dann so vollständig, daß er compiliert und keine 
Warnungen wirft.
Wenn Du Warnungen nicht deuten kannst, dann poste sie vollständig und 
exakt (C&P).

von Peer (Gast)


Lesenswert?

ok - die Kommentare sind falsch. Die werde ich erst mal rausstreichen. 
Der Master erkennt den Slave ganz korrekt. Habe zu Anfang auch eine 
Abfrage drin die mir Anzeig ob der Slave auf dieser Adresse exestiert. 
Ausgabe erfolgt auf einem LCD. Beim kompilieren werden keinerlei 
Fehlermeldungen angezeigt. Der Code für den Master und den Slave kann 
korrekt übertragen werden. Die Steuerung vom Master zum Slave geht ohne 
Probleme.
Der Fehler liegt in der übertragung vom Slave zum Master.

von Peer (Gast)


Lesenswert?

Der komplette Code vom Slave:
1
#define F_CPU 16000000UL
2
#include <stdlib.h>                
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <avr/pgmspace.h>
6
#include "usiTwiSlave.h"
7
8
#define slave_adresse 0x52            // Adresse Slave
9
10
uint8_t  byte1, byte2, byte3, byte4;
11
uint16_t buffer;
12
13
int main(void) 
14
  {
15
  cli();                    
16
  usiTwiSlaveInit(slave_adresse);        
17
  sei();          
18
  
19
  DDRD=0b00111000;                    
20
  
21
  PORTD|=0b00111000;            
22
23
  
24
  while(1) 
25
    {    
26
    byte1 = rxbuffer[0];          
27
    byte2 = rxbuffer[1];
28
  ///////////////////////////////////////////////////////////////////////  
29
    if (byte1==43)              
30
      {                  
31
      PORTD &=~(1<<PIND5);        
32
      PORTD |=(1<<PIND4);          
33
      }
34
    if (byte1==42)              
35
      {                    // wenn dann ...
36
      PORTD &=~(1<<PIND4);        
37
      PORTD |=(1<<PIND5);          
38
      }
39
  //////////////////////////////////////////////////////////////////////  
40
    if (PIND & (1<<PIND0))           
41
      {                    
42
      byte3=40;              
43
      PORTD |=(1<<PIND3);          
44
      }
45
    else
46
      {
47
      PORTD &=~(1<<PIND3);        
48
      byte4=30;            
49
      }
50
    txbuffer[0]=byte3;            
51
    txbuffer[1]=byte4;
52
    }                      // end.while
53
    }                      // end.main
Zu dem anderen Teil komme ich erst heute abend. Werde das mit dem LCD 
machen.

von Peter D. (peda)


Lesenswert?

Peer schrieb:
> Der komplette Code vom Slave:

Dann kann es ja nicht funktionieren, es fehlt der I2C-Code.

von Peer (Gast)


Lesenswert?

Peer schrieb:
> #include "usiTwiSlave.h"

Peer schrieb:
> usiTwiSlaveInit(slave_adresse);

In diesen beiden Sachen steckt der I2C Bus. Im ori ist es von Jtronk

von Max B. (citgo)


Lesenswert?

Also ich suche mir die Sachen jetzt nicht im Netz zusammen.

Du sagst erst Slave hat die Adresse 50 und im Code steht 52!?

Ich weiß auch nicht was txbuffer[] macht.

von Peter D. (peda)


Lesenswert?

Peer schrieb:
> In diesen beiden Sachen steckt der I2C Bus.

Wenn Du den vollständigen Code von Master und Slave nicht zeigen willst, 
dann sag das doch gleich.

von Peer (Gast)


Angehängte Dateien:

Lesenswert?

Das ist der vollständige Code vom Slave

Peer schrieb:
> #include "usiTwiSlave.h"

kann gern auch diese Datei einstellen.
Master kommt ebenfalls noch

von Peer (Gast)


Lesenswert?

Stimmt, die Adresse ist 52

von Peer (Gast)


Lesenswert?

Der komplette Code vom Master
1
/* I2C-Master-Routinen von Peter Fleury verwenden siehe: http://homepage.hispeed.ch/peterfleury/avr-software.html#libs */
2
/*  Abgestimmt auf meine Hardware P30, D2, P52, NT2, 2xP20
3
    Bedienung: 
4
  Slave - Port B Anzeige welche LED, T2 Umschaltung der Sende byte, L2 und L4 Anzeige der Sende byte
5
  Master - T1 und T3 sende byte zum Slave, T2 hole byte vom Slave, Anzeige am Port A    */  
6
    
7
    #include <stdbool.h>
8
    #include <avr/pgmspace.h>
9
    #include "main.h"
10
    #include <util/delay.h>
11
    #include "i2clcd.h"
12
    #include "i2cmaster.h"
13
    #include "avr/io.h"
14
    #include "util/delay.h"
15
    #include "avr/interrupt.h"
16
    
17
    #define slave_adresse 0x52        // Slave Adresse schreiben
18
    #define slave_adresse_r 0x53        // Slave Adresse lesen
19
    
20
    uint8_t ret;                     // Kontrollvariable ob Slave vorhanden
21
    uint8_t byte1, byte2;              // Daten zum Senden vom Master zu Slave
22
    uint8_t byte3, byte4;
23
    uint8_t byte10;              // Daten zum holen vom Slave zu Master
24
///////////////////////////////////////////////////////////////////////////////////////////////////
25
  void startanzeige()              // Titelbild
26
    {
27
    lcd_command(LCD_CLEAR);              // Leere Display
28
    _delay_ms(2);                  // Warte 2ms
29
    lcd_printlc(1,2,"USI Bus M-Prg1");       // Zeile 1
30
    lcd_printlc(2,2,"Verbindung von");    // Zeile 2
31
    lcd_printlc(3,2,"Prz ueber I2C ");    // Zeile 3
32
    lcd_printlc(4,2,"(by P.)");    // Zeile 4
33
    _delay_ms(3000);                 // Warte 5000ms
34
    }
35
///////////////////////////////////////////////////////////////////////////////////////////////////
36
  void slavetest()              // Abfrage Slave, Fehlermeldung und Anzeige
37
    {                      // Abfarge ob Slave vorhanden ist
38
    ret = i2c_start(slave_adresse);      // Start i2C mit Adresse Slave
39
    i2c_write(0x00);            // Sende Daten
40
    i2c_stop();                // I2C Stop
41
    if (ret == 0)              // Bus ok - 0, kein Bus 1
42
      {                           // Anzeige Slave ok
43
      lcd_command(LCD_CLEAR);        // Leere Display
44
      _delay_ms(2);                // Warte 2ms
45
      lcd_printlc(2,4,"Slave ist ");    // Ausgabe Text
46
      lcd_printlc(3,5,"OK !!!!!");    // Slave OK
47
      _delay_ms(2000);              // Warte 2s
48
      }
49
    else                  // Fehlermeldung
50
      {                                // Anzeige Slave nicht ok
51
      lcd_command(LCD_CLEAR);        // Leere Display
52
      _delay_ms(2);                // Warte 2ms
53
      lcd_printlc(2,5,"Slave ist");    // Ausgabe Schrift
54
      lcd_printlc(3,5,"Nicht OK");    // Slave Nicht O
55
      _delay_ms(1000);              // Warte 2s
56
      }
57
    } 
58
/////////////////////////////////////////////////////////////////////////////////////////////////////  
59
  void s_write1 (void)            // schreibe Daten 1 von Master zu Slave
60
    {
61
    i2c_start(slave_adresse);        // Slave ist bereit zum Schreiben
62
    i2c_write(0x00);                        // Buffer Startadresse setzen
63
    i2c_write(42);                          // Drei Bytes schreiben...
64
    i2c_stop();                             // Zugriff beenden  
65
     }
66
//////////////////////////////////////////////////////////////////////////////////////////  
67
  void s_write2 (void)            // schreibe Daten 2 von Master zu Slave
68
    {
69
      i2c_start(slave_adresse);        // Slave ist bereit zum Schreiben
70
    i2c_write(0x00);                        // Buffer Startadresse setzen
71
    i2c_write(43);                          // Drei Bytes schreiben...
72
    i2c_stop();                             // Zugriff beenden
73
    } 
74
/////////////////////////////////////////////////////////////////////////////////////////////////
75
  void s_read1()                // lese Slave1
76
    {
77
      i2c_start(slave_adresse);        // Start Bus schreiben
78
      i2c_write(0x00);          
79
      i2c_rep_start(slave_adresse);        // starte Slave lesen
80
      byte3=i2c_readAck();          // 2. Byte lesen und in "gelesen" ablegen
81
      byte4=i2c_readNak();          // letztes Byte lesen, darum kein ACK
82
      i2c_stop();                // Zugriff beenden  
83
    }
84
//////////////////////////////////////////////////////////////////////////   
85
  int main(void)
86
    {
87
    cli();                             // Interrupts deaktiviert
88
    i2c_init();                        // Starte I2C Bus
89
    lcd_init();                        // Starte I2CLCD    
90
    // Display Befehle
91
    lcd_command(LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKINGOFF);
92
    lcd_light(0);              // Licht an
93
    startanzeige();
94
    lcd_command(LCD_CLEAR);            // Leere Display
95
    _delay_ms(2);                  // Warte 2ms
96
    slavetest();
97
    _delay_ms(2);
98
    
99
    DDRC=0b01100000;    //Taster    // setzt Port C auf Ausgang, PC5 und PC6
100
    //DDRA=0b11111111;      //LED    // setzt Port A auf Ausgang, PC5 und PC6
101
      
102
    PORTC|=0b01001111;    //Taster    // Deaktiviere Ports C5-6 (LEDs aus)
103
    //PORTA|=0b11111111;    //LED      // Deaktiviere Pins A0-7 (LEDs aus)
104
    
105
    while(1)
106
      {
107
        // ========>> AUF GELESENE DATEN REAGIEREN
108
      s_read1();    
109
      
110
        if (byte4 == 30)        
111
          {                  // Wenn Wert 30 gelesen wurde...
112
            PORTC &= ~( (1<<PINC5));    // schalte Port A6  
113
        PORTC |=(1<<PINC6);        // wenn nicht lösche Port A6  
114
          }
115
        else
116
          {  
117
          PORTC |=(1<<PINC5);        // wenn nicht lösche Port A6
118
        PORTC &= ~( (1<<PINC6));    // schalte Port A6  
119
          }
120
  ///////////////////////////////////////////////////////////////////////////////////////////////    
121
        // ========>> TASTENEINGABEN
122
        if (!(PINC & (1<<PINC2)) )      // Taster T1
123
          {                  // Wenn T1 gedrückt...
124
          PORTA &=~(1<<PINA1);      // LED 2 A1 ein
125
          s_write1();            // Schreib 1 Funktion aufrufen
126
          }
127
        else
128
          {
129
            PORTA |=(1<<PINA1);        // sonst LED 2 A1 aus
130
          }
131
        // ========>> TASTENEINGABEN
132
        if (!(PINC & (1<<PINC4)) )      // Taster T 3
133
          {                  // Wenn T1 gedrückt...
134
          PORTA &=~(1<<PINA2);      // LED 3 A2 ein
135
          s_write2();            // Schreib 2 Funktion aufrufen
136
          }
137
        else
138
          {
139
          PORTA |=(1<<PINA2);        // sonst LED 3 aus
140
          }
141
  
142
        }
143
        }
Habe den Code so weit möglich aufgeräumt. Bitte die Kommentare 
vorsichtig betrachten, sind noch Fehler drin.

von Peer (Gast)


Lesenswert?

Die Werte zum Quarz und Adresse des Displays befinden sich in der main.h

von Peer (Gast)


Lesenswert?

Könnte jemand sich die Sache ansehen und mit helfen?

von Peter D. (peda)


Lesenswert?

Peer schrieb:
> Könnte jemand sich die Sache ansehen

So jetzt üben wir das nochmal.
Mache 2 Verzeichnisse, eins mit dem kompletten Mastercode und eins mit 
dem kompletten Slavecode. Und dann zippe es und poste es als Anhang.

Hast Du es denn schonmal mal mit systematischer Fehlersuche probiert?
D.h. konstante Daten an Master senden, mit UART ausgeben, konstante 
Daten an Slave senden, mit UART ausgeben.

: Bearbeitet durch User
von Peer (Gast)


Lesenswert?

Hallo Peter
hatte es wie geschrieben mit einer Ausgabe zur Kontrolle auf dem Display 
gemacht. Werte die vom Master gesendet werden kann ich anzeigen. Werte 
die vom Master gelesen werden sollen kommen nicht auf das LCD.
Hatte dazu konstante Werte genommen.
Mit dem zippen habe ich das wohl falsch verstanden. Einige haben es 
gezippt und andere haben sich beschwert wer es den entzippen soll. Da 
gehen die Meinungen etwas auseinander.
Mache mich ans zip.

von Peer (Gast)


Angehängte Dateien:

Lesenswert?

Habe alle Datein jeweils für Master und Slave als zip reingestellt. Es 
sind alle Datein dabei. Die Kommentare sind nicht überarbeitet und 
teilweise falsch

von Peer (Gast)


Lesenswert?

Kann mir einer helfen?

von Peer (Gast)


Lesenswert?

Hat jemand eine Idee?

von Stefan F. (Gast)


Lesenswert?

Gehe systematisch vor. Reduziere das Programm auf weniger Baustellen.

Besorge Dir einen PCF8574, und eine Hand voll LEDs mit 1kΩ 
Vorwiderständen. Und besorge Dir einen Logic Analyzer (z.B. diese 
billigen (8ch 25MHz Dinger von Amazon).

Jetzt hängst du an den I²C Bus und an die 8 Ausgänge des PCF8574 jeweils 
eine LED:
1
AVR                                        PCF8574
2
3
            +---[===]---------o 5V
4
            |
5
            +---[===]---|<|---o 5V
6
            |
7
SCL o-------+------------------------------o SCL
8
9
SDA o-------+------------------------------o SDA
10
            |
11
            +---[===]---|<|---o 5V           P0 o---[===]---|<|---o 5V
12
            |                                P1 o---[===]---|<|---o 5V
13
            +---[===]---------o 5V           P2 o---[===]---|<|---o 5V
14
                                             P3 o---[===]---|<|---o 5V
15
                                             P4 o---[===]---|<|---o 5V
16
                                             P5 o---[===]---|<|---o 5V
17
                                             P6 o---[===]---|<|---o 5V
18
                                             P7 o---[===]---|<|---o 5V

Jetzt versuchst du nur die LEDs am Ausgang des PCF8574 leuchten zu 
lassen. Sonst nichts. Kein zweiter µC, kein LCD Display, keine Taster. 
Wenn das klappt, programmiere ein Lauflicht.

Damit prüfst du deinen I²C Master.
Analysiere die I²C Kommunikation mit Hilfe der beiden Leuchtdioden und 
dem Logic Analysator. Berichte, was dabei heraus kam.

Als nächsten Schritt ersetzt du den PCF8574 durch deinen Slave µC und 
programmierst ihn so, dass er ebenfalls einfach nur das empfangene Byte 
mit den LEDs anzeigt. Alles sonstigen Schnickschnack lässt du erstmal 
weg.

Analysiere erneut die I²C Kommunikation mit Hilfe der beiden 
Leuchtdioden und dem Logic Analysator. Berichte, was dabei heraus kam.

Dann sehen wir weiter.

von Peer (Gast)


Lesenswert?

Hallo Stefanus
das mit 8574 geht alles. Verwende auch noch ca. 20 andere Bausteine am 
Bus. Auch die Widerstände sind drin.
Beim Start des Atmega erfolgt eine Abfrage ob ein Slave mit der 
eingestellte Adresse vorhanden ist. Ist er nicht dran erfolgt auf dem 
display eine Anzeige das der Slave nicht ok ist und das Programm stopt. 
Ist der Slave dran und die Adresse korrekt erfolgt die Anzeige das der 
Bus ok ist.
Auf dem Master habe ich mehrere Taster. Wenn ich diese betätige erfolgt 
das wechsel seitige schalten von 2 LEDs auf dem Slave. Damit erfolgt 
eine korrekte übertragung der Daten vom Master zum Slave. Habe 
zusätzlich noch ein paar LEDs am Master zu laufen die mir das zur 
Kontrolle anzeigen.
Es geht um die Abfrage des Slaves durch den Masters und die Anzeige 
dazu.
LG Peer

von Stefan F. (Gast)


Lesenswert?

Dann würde ich jetzt als Nächstes die Kommunikation zum Slave mit dem 
Logic-Analyzer untersuchen.

Sendet der Master, was er soll?
Antwortet der Slave, wie er soll?

Kannst du serielle Debug Meldungen ausgeben, um die Inhalte von 
Variablen (z.B. byte3 und byte4) zu kontrollieren?

von Peer (Gast)


Lesenswert?

Der Master sendet in Abhängigkeit der gedrückten Taster zwei 
unterschiedliche Werte. Die Betätigung der Tasten und die zu senden 
bytes lasse ich mir anzeigen. Da der Slave auf die Sicherheitsabfrage 
reagiert und Antwortet erfolgt ein Kommunikation vom Master zum Slave 
und Antwort. Alles wie er soll.
Die Abfrage vom Master zum Slave und die Antwort des Slave kommen nicht.
Als Slave Adresse habe ich 50 (52) eingestellt. Das ist doch die 
Schreibadresse. Muss ich beim Ati 2313 auch eine Leseadresse angeben 
oder einstellen?

Stefanus F. schrieb:
> Kannst du serielle Debug Meldungen ausgeben, um die Inhalte von
> Variablen (z.B. byte3 und byte4) zu kontrollieren?

Es soll der Zustand einer LED ausgelesen werden, leuchtet oder nicht.
Versuche gerade das zu machen. Welche Werte kommen oder gelesen werden, 
ob überhaupt gelesen wird.

von Stefan F. (Gast)


Lesenswert?

Nochmal: Analysiere die Kommunikation mit einem Logic Analyzer und 
schaue in deine Variablen rein.

Deine wiederholte Bitte, die Problemursache zu erraten, bringt nichts 
gutes.

Zur Adresse: I²C Device haben eine Adresse. Es gibt nicht eine 
Schreib-Adresse und eine Lese-Adresse. Es gibt nur eine Adresse mit 7 
bits. Nach der Adresse wird das r/w Bit übertragen, welches aber nicht 
Bestandteil der Adresse ist.

von Peter D. (peda)


Lesenswert?

Peer schrieb:
> Die Abfrage vom Master zum Slave und die Antwort des Slave kommen nicht.

Was heißt "kommen nicht"?
Irgendwas liest der Master und genau das gib aufs LCD oder die UART aus.

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.