Forum: Mikrocontroller und Digitale Elektronik TWI Status Register


von lars (Gast)


Lesenswert?

Guten Abend.

Ich versuche gerade Werte vom HMC5883L zu bekommen.
Dabei scheitert bereits die Verbindung.
Kann mir vielleicht jemand ratschläge geben, wie ich da am besten 
vorgehe?

Bei meinem Fehler läuft erstmal alles reibungslos.
Dann wird aber durch die letzte if-Abfrage:
if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) )
abgebrochen.

Ich stehe gerade auf dem Schlauch.

Hier der Code:
1
unsigned char i2c_start(unsigned char address)
2
{
3
    uint8_t   twst;
4
5
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
6
7
  while(!(TWCR & (1<<TWINT)));
8
9
  // check value of TWI Status Register. Mask prescaler bits.
10
  twst = TW_STATUS & 0xF8;
11
  if ( (twst != TW_START) && (twst != TW_REP_START)) { return 1; }
12
13
14
  TWDR = address;
15
  TWCR = (1<<TWINT) | (1<<TWEN);
16
17
  // wail until transmission completed and ACK/NACK has been received
18
  while(!(TWCR & (1<<TWINT)));
19
20
  // check value of TWI Status Register. Mask prescaler bits.
21
  twst = TW_STATUS & 0xF8;
22
  if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) 
23
  { 
24
     /* Durch diese Abfrage wird abgebrochen. twst hat den Wert 32 */
25
     return 1;
26
  }
27
28
  return 0;
29
30
}

Grüße ars

von lars (Gast)


Lesenswert?

Tach auch!

Hat da echt niemand einde Idee woran es liegen kann?

von Karl H. (kbuchegg)


Lesenswert?

Es wäre gut gewesen, wenn du dazu gesagt hättest, dass du die 
TWI-Routinen vom Peter Fleury nimmst, denn dann geht man gleich ganz 
anders an die Sache rann. Denn die funktionieren zumindest bei mir 
problemlos.

Verschaltung zeigen. Rest vom Programm zeigen. Die von dir benutzte 
Adresse stimmt?

von lars (Gast)


Angehängte Dateien:

Lesenswert?

Danke für deine Antwort!

> TWI-Routinen vom Peter Fleury nimmst

Ja, das wäre wohl schlauer gewesen.


> Verschaltung zeigen

Als Master benutze ich den STK500, die IMU ist der 10DOF von drotek.fr
( http://www.drotek.fr/shop/en/62-imu-10dof-mpu6050-hmc5883-ms5611.html 
).
Ich habe im Anhang mal ein Screenshot von der Schematic.pdf gemacht.

Vom Code gibt es ja nicht besonders viel zu sehen, da schon beim 
i2c_start() ein Fehler auftritt. Trotzdem habe ich hier die Fehlerzeilen 
mit der Ausgabe:
1
#define F_CPU 12000000UL
2
#define SCL_CLOCK  100000L
3
#define BAUD 4800UL
4
5
#define COMPASS_READ 0x3D
6
#define COMPASS_WRITE 0x3C
7
8
9
unsigned char i2c_start(unsigned char address)
10
{
11
    uint8_t   twst;
12
  uart_puts("i2c_start\n");
13
  // send START condition
14
  TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
15
16
  // wait until transmission completed
17
  while(!(TWCR & (1<<TWINT)));
18
19
  // check value of TWI Status Register. Mask prescaler bits.
20
  twst = TW_STATUS & 0xF8;
21
  if ( (twst != TW_START) && (twst != TW_REP_START)) { uart_puts("Fehler_1!!!\n"); return 1; }
22
23
  // send device address
24
  TWDR = address;
25
  TWCR = (1<<TWINT) | (1<<TWEN);
26
27
  // wail until transmission completed and ACK/NACK has been received
28
  while(!(TWCR & (1<<TWINT)));
29
30
  // check value of TWI Status Register. Mask prescaler bits.
31
  twst = TW_STATUS & 0xF8;
32
  if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) { uart_puts("Fehler_2!!!\n"); return twst; };
33
34
  return 0;
35
}
36
37
38
39
40
unsigned char compass_init(void)
41
{
42
  unsigned char tmp;
43
  
44
  i2c_init();
45
  delay_ms(25);
46
  
47
  tmp = i2c_start(COMPASS_WRITE);
48
  
49
  char send[255];
50
  int n = sprintf(send, "\n>>>> %d <<<<\n",tmp);
51
  for(int i=0;i<n;i++) { uart_putc((unsigned char)send[i]); }
52
53
  if(tmp != 0)
54
  {
55
    i2c_stop();
56
    if(tmp == 1) { uart_puts("\ncompass_init (start) failed: tmp == 1\n"); }
57
    if(tmp == 2) { uart_puts("\ncompass init (start) failed: tmp == 2\n"); }
58
    return 0;
59
  }
60
  
61
  tmp = i2c_write(0x02);
62
  if(tmp != 0)
63
  {
64
    i2c_stop();
65
    uart_puts("\ncompass_init (write2) failed!\n");
66
    return 0;
67
  }
68
  
69
  tmp = i2c_write(0x00);
70
  if(tmp!=0)
71
  {
72
    i2c_stop();
73
    uart_puts("\ncompass_init (write0) failed!\n");
74
    return 0;
75
  }
76
  i2c_stop();
77
  return 1;
78
}
79
80
81
int main(void)
82
{
83
  DDRA = 0xff; // LEDs zum Debug neben UART
84
  
85
    delay_ms(1000);
86
    
87
    uart_init();
88
    delay_ms(100);
89
  
90
    if(compass_init() == 1)
91
  {
92
      uart_puts("\nAlles Erfolgreich!!!\n");
93
    }
94
  else
95
  {
96
    uart_puts("\nImmernoch der Fehler!!!\n");
97
  }
98
}

Hier die Fehlerausgabe:
1
…i2c_init
2
i2c_start
3
Fehler_2!!!
4
5
>>>> 32 <<<<
6
7
Immernoch der Fehler!!!

Ich weiß echt nicht wo der Wurm begraben ist. Hatte jemand hier schonmal 
ein ähnliches Problem?

PS: Die Adresse steht so im Datenblatt.

von Karl H. (kbuchegg)


Lesenswert?

lars schrieb:


> Als Master benutze ich den STK500, die IMU ist der 10DOF von drotek.fr
> ( http://www.drotek.fr/shop/en/62-imu-10dof-mpu6050-hmc5883-ms5611.html
> ).

Hmm. Ich komm da nicht drann.
Kannst du mal einen Link aufs Datenblatt posten oder das Datenblatt 
direkt als Attachment anhängen?

von lars (Gast)


Angehängte Dateien:

Lesenswert?

Klar. Das Datasheet befindet sich im Anhang.
Hätte ich auch drann denken können. Entschuldige.

von lars (Gast)


Lesenswert?

Merkwürdig. Ich kann den Anhang von mir selbst nicht öffnen.
Hier nochmal der Download-Link des Datasheets:
http://media.digikey.com/PDF/Data%20Sheets/Honeywell%20PDFs/HMC5883L.pdf

Ansonsten nach HMC5883L googlen. Der erste Treffer dürfte es sein :)

von Marco S (Gast)


Lesenswert?

I2C-Addresse vielleicht 0x1E?

von lars (Gast)


Lesenswert?

Die hatte ich auch schon ausprobiert.

Also: 0x1E, 0x3D, 0x3C

Entschuldigt, dass ich den Fehler nicht genauer beschreiben kann.
Ich weiß es aber auch selbst nicht.
Im Grund kann es überall drann liegen - weiter isolieren kann ich das 
hier nicht mehr.

Ich werde jetzt erstmal zur Uni fahren und gucken, ob der 
Spannungsregler seine arbeit tut. Vielleicht ist mein C-Code doch 
ausnahmsweiße korrekt und der Fehler liegt im IMU (was ich nicht glaube, 
aber naja ... was soll ich sonst noch tun?).

von lars (Gast)


Lesenswert?

Ich habe jetzt gerade die Spannungen am Spannungsregler gemessen und da 
passt alles. Also ich bin mit meinem Latein am Ende ;)
Sonst noch Ideen?

von lars (Gast)


Lesenswert?

Also ihr habt auch keine Ideen mehr, oder?
Ich stehe einfach voll auf dem Schlauch und komme nicht weiter :(

Gruß,
Lars.

von Borsty B. (mantabernd)


Lesenswert?

Hi,

trag mal die Adresse direkt hier binär ein, also statt dem hier:
1
TWDR = address;
2
TWCR = (1<<TWINT) | (1<<TWEN);

das da:
1
TWDR = 0b00111100; 
2
TWCR = (1<<TWINT) | (1<<TWEN);


Gibt es tatsächlich kein ACK? Hast du ein Oszi zum checken der SDA 
Leitung? Eventuell stimmt auch deine Maskierung bzw. die Prüfung von 
deinen Statusbits nicht. Kann es vielleicht sein dass du dezimal mit hex 
vergleichen willst? 32 Dezimal wären nämlich 0x20, also ein NACK. 
Eventuell liegt hier der Hund begraben??

Gruß
Bernhard

von lars (Gast)


Lesenswert?

Hallo,

danke fürs durchlesen und für die Vorschläge.
Ich habe mal die Adresse direkt binär eingegeben.
0b00111100 (0x3C) und 0b00011110 (0x1E).
Leider bleibt alles gleich. Daran liegt es wohl nicht.

> Gibt es tatsächlich kein ACK? Hast du ein Oszi zum checken der SDA
> Leitung?

Also soweit ich feststellen kann nicht.
An ein Oszi könnte ich morgen wohl kommen.
Wie soll ich da vorgehen? SDA und GND anschließen und immer wenn die 
Rechteckspannung auf 0 liegt habe ich ein ACK? Wenn es eine "Linie 
bleibt" (also immer High) kann der Sensor nicht angesprochen werden?
Ich habe noch nie mit einem Oszi gearbeitet, werde es aber versuchen.

>32 Dezimal wären nämlich 0x20, also ein NACK.

hmm, es sollte ja auch ein ACK sein?! Demnach passen die Fehler ja auch, 
oder sehe ich das falsch?

Ich bekomme auch Daten rein. Woher diese wirklich stammen weiß ich 
jedoch nicht. Sinn ergibt es jedenfalls nicht; zudem ändern sich die 
Werte nie. Selbst wenn ich mich mit dem Sensor im Raum bewege (ein 
Magnet in der Nähe ist es also nicht).

Das wiederholt sich (nach den Fehlermeldungen) immer wieder:
1
X: 32239
2
Y: -8706
3
Z: -2337
4
5
compass1 read failed

Sticht da sonst noch irgendwas ins Auge?
Ansonsten würde ich morgen einfach mal versuchen SDA mit einem Oszi 
auszulesen und zu gucken was da so passiert :)

Gruß,
Lars.

von Borsty B. (mantabernd)


Lesenswert?

Hi,

hier wiederspricht sich was:

lars schrieb:
> Ich bekomme auch Daten rein.


lars schrieb:
> Ich habe mal die Adresse direkt binär eingegeben.
> 0b00111100 (0x3C) und 0b00011110 (0x1E).
> Leider bleibt alles gleich. Daran liegt es wohl nicht.

Adresse 0x3C ist die Schreibadresse und 0x1E ist m.M. nach falsch (was 
willst du damit machen). Die Leseadresse wäre 0b00111101 (0x3D).

Oszi ist hier sehr hilfreich, achte beim messen darauf dass der TWI 
Befehl in einer Dauerschleife und möglichst schnell hintereinander läuft 
sonst siehst du am Oszi nur einen kurzen Balken vorbeihuschen und tust 
dir schwer das Nutzsignal einzufangen. Sehr sinnvoll ist es auch mit dem 
2. Kanal die SCL Leitung einblenden zu lassen, so tut man sich leichter 
beim Abzählen der Bits.

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.