TWI bei mega644 läuft nicht

Gast #1454031
Hallo zusammen,

Sitze jetzt schon einige Tage drann zwei mega 644 miteinander 
kommunizieren zu lassen.
Ich möchte zunächst einfach nur 1Byte vom Master zum Slave schicken..
Vll seht ihr schon den ein oder anderen Fehler im Quellcode?!

Master hat diesen Code:
1
#include "twi_com.h"
2

3

4
int slave = 0b0000111;
5

6
void twi_init(void) {
7
  TWBR = 0x11; //SCL auf 400KHz: 0x11 ; 200KHz: 0x2A ; 100KHz : 0x5C
8
  TWSR |= (1<<TWPS0) | (1<<TWPS1); //Prescale Bits - Teiler = 1
9
}
10

11
void twi_trans_value (void) {
12
    
13
  int value = 0b10101010;  
14

15
  TWCR = 0x00;
16

17
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);   //Start Condition senden
18

19
  while (!(TWCR & (1<<TWINT)));          //Warten ob erfolgreich
20
  
21
  TWDR = (slave<<1) | TW_WRITE; //Slave adresse + Zugriffsart (W) in Datenregister schreiben
22
  
23
  TWCR = (1<<TWINT) | (1<<TWEN); //TWDR senden
24

25
  while (!(TWCR & (1<<TWINT))); //Warten bis gesendet
26

27
  TWDR = value; //Daten in TWDR laden
28

29
  TWCR = (1<<TWINT) | (1<<TWEN); //Daten senden
30

31
  while (!(TWCR & (1<<TWINT)));  //Warten bis gesendet
32

33
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); //STOP senden
34

35

36
}

Der slave sieht folgendermaßen aus:
1
int SLAVEADR = 0b0000111;
2
void twi_init(void) {
3

4
  TWAR = (SLAVEADR<<1)|(1<<TWGCE) ; //Slaveadr.... Global Call Off
5
  TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWEA) | (1<<TWIE); //Global Interrupt off
6
}
7

8
void twi_get_data(void) {
9

10
  while(!(TWCR & (1<<TWINT))); //Warten bis der Slave angesprochen wurde
11
    
12
  twi_data = TWDR;
13
  TWCR |= (1<<TWINT);
14

15
}
16

17
ISR (TWI_vect) {
18
  twi_get_data();
19
}

Die funktionen werden nacheinander aufgerufen.. interrupts sind 
aktiviert.

Wäre super nett wenn hier mal einer rüberschaut.

Gruß
Jannik
Hallo,
als erstes kannst du mal versuchen, die I2C-Taktrate herunterzusetzen. 
dann könntest du versuchen, nach jedem Schritt eine LED aufleuchten zu 
lassen um rauszufinden ob dein programm hängt.
z.b. So:
1
  int value = 0b10101010;  
2

3
  TWCR = 0x00;
4

5
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);   //Start Condition senden
6

7
  while (!(TWCR & (1<<TWINT)));          //Warten ob erfolgreich
8

9
    LED1_an;
10
  
11
  TWDR = (slave<<1) | TW_WRITE; //Slave adresse + Zugriffsart (W) in Datenregister schreiben
12
  
13
  TWCR = (1<<TWINT) | (1<<TWEN); //TWDR senden
14

15
  while (!(TWCR & (1<<TWINT))); //Warten bis gesendet
16

17
     LED2_an;
18

19

20
usw.
Gast
So, ich habe nochmal ein wenig weiter geforscht.. Habe mir noch ein Jtag 
interface organisiert um der Sache auf den Grund zu gehen.
Hier ist der Wurm drinn :)
Jetzt wird der Slave schonmal unter der vergebenen Adresse angesprochen. 
Jedoch bekommt der Slave als Daten vom Master (im TWDR) die Slave 
adresse+Schreibbit ?!
Wie kann man das erklären? Ich bin recht ratlos wie diese 
Adresse+Schreibbit im TWDR des Slaves landet? Eigentlich verschicke ich 
ja ein ganz anderes Byte. Weiß wer weiter? Ich habe es ebenfalls im 
Quellcode kommentiert. Mein Gefühl sagt mir dass irgendwas im Slavecode 
nicht stimmt....

Hier nochmal der Master:
1
#include "twi_com.h"
2

3

4
int slave = 0b0100111;
5

6
void twi_init(void) {
7
  TWBR = 0x5C; //SCL auf 400KHz: 0x11 ; 200KHz: 0x2A ; 100KHz : 0x5C
8
  TWSR |= (1<<TWPS0) | (1<<TWPS1); //Prescale Bits - Teiler = 1
9
}
10

11
void twi_trans_value (void) {
12
    
13
  int value =127;  
14

15
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);   //Start Condition senden
16

17
  while (!(TWCR & (1<<TWINT)));          //Warten ob erfolgreich
18
  
19
  TWDR = (slave<<1) | TW_WRITE; //Slave adresse + Zugriffsart (W) in Datenregister schreiben
20
  
21
  TWCR = (1<<TWINT) | (1<<TWEN); //TWDR senden
22

23
  while (!(TWCR & (1<<TWINT))); //Warten bis gesendet
24

25
  TWDR = value; //Daten in TWDR laden
26

27
  TWCR = (1<<TWINT) | (1<<TWEN); //Daten senden
28

29
  while (!(TWCR & (1<<TWINT)));  //Warten bis gesendet
30

31
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); //STOP senden
32

33

34
}


Und hier der Slave:
1
#include "Twi_com.h"
2
#include "mylcd.h"
3

4

5
int twi_data = 0;
6
int SLAVEADR = 0b0100111;
7

8
void twi_init(void) {
9

10
  TWAR = (SLAVEADR<<1)|(1<<TWGCE) ; //Slaveadr.... Global Call Off
11
  TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWEA) | (1<<TWIE); //Global Interrupt off
12
  lcd_set_cursor(0,LINE0);
13
  lcd_puts_p(small_font,PSTR("Slave init rdy")); //Kommt
14
}
15

16
void twi_get_data(void) {
17
  lcd_set_cursor(0,LINE1);
18
  lcd_puts_p(small_font,PSTR("Wait for rqst")); //Kommt
19
  
20
  while(!(TWCR & (1<<TWINT))); //Warten bis der Slave angesprochen wurde
21
  
22
  lcd_set_cursor(0,LINE2);
23
  lcd_puts_p(small_font,PSTR("Try to get data"));  //Kommt
24
  
25
  twi_data = TWDR;
26
  lcd_draw_line(0,LINE5,twi_data/2,LINE5,BLACK);
27

28
  if (twi_data == 78) { // Slavadr+Schreibbit als Dezimal. Was macht das im TWDR?! Hilfe!
29
    lcd_set_cursor(0,LINE3);
30
    lcd_puts_p(small_font,PSTR("DATA OKAY")); // Kommt
31
  }
32

33
  TWCR |= (1<<TWINT);
34
  
35
  lcd_set_cursor(0,LINE4);
36
  lcd_puts_p(small_font,PSTR("Get Data rdy")); //Kommt
37
}
38

39
ISR (TWI_vect) {
40

41
  twi_get_data();
42
}
Gast
Wieder ein wenig weiter....

Habe mal ein Bild von der Übertragen vom Master aus angehängt. SCL liegt 
bei ca. 1KHz. Daten sehen recht sauber aus. Habe es mal mit Bleistift 
makiert wo die Adresse und das Datenbyte gesendet wird. Hoffe man 
erkennt es einigermaßen. Was ich jetzt sehe ist, dass der Slave kein Ack 
zurückgibt sondern ein NotAck (SDA ist im neunten Bit auf "1" und nicht 
auf "0".

Woran kann das liegen? Die Startkondition sowie Slaveadresse+Write kommt 
ja genau richtig an - das sieht man ja nun auf dem Oszi. Wieso sendet 
der Slave kein Ack?

Hier nochmal die zwei Zeilen aus dem Slave (die ja eigentlich für ein 
Ack nach der Adresse ausreichen sollten, oder etwa nicht?!)
1
int SLAVEADR = 0b0100111;
2

3
void twi_init(void) {
4

5
  TWAR = (SLAVEADR<<1)|(1<<TWGCE) ; //Slaveadr.... 
6
  TWCR = (1<<TWEN) | (1<<TWINT) | (1<<TWEA) | (1<<TWIE); //Global Interrupt on
7
 
8
}

Müsen die Pins SDA und SCL als Dateneingang oder Ausgang definiert sein? 
Für SCL macht ja Slaveseitig ein Eingang sinn. Nur bei SDA wird ja 
emfangen und gesendet (für Ack/NotAck. Hierzu finde ich nichts im 
Datenblatt. Regelt die TWI Hardware die SCL und SDA Datenrichtungen 
automatisch?

Vielen Dank!
Angehängte Dateien:

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.