mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik I²C Sensor antwortet nicht


Autor: Seb (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen,

Ich befasse mich die letzten Tage zum ersten Mal mit dem I²C Interface 
des MSP430f2617. Als Basis für meine Software dient mir eine Appnote von 
TI (SLAA382). Ich führe in einem bestimmten Intervall (Timer) eine 
Messung durch. Nun beobachte ich folgendes Verhalten:

So lange der Sensor nicht angeschlossen ist, sendet der MSP die korrekte 
Adresse des Sensors + Schreibbefehl, bekommt aber natürlich kein ACK 
(siehe Bild, leider schlechte Quali) vom Sensor. Sobald ich den Sensor 
jedoch an den MSP hänge, bleibt das Programm an folgender Funktion 
hängen:
unsigned char I2C_notready(){
  return (UCB0STAT & UCBBUSY);
}

Der Takt ist das auf HIGH und die Datenleitung auf LOW und nüscht tut 
sich mehr.

Vorher wird ein transmitinit ausgeführt (von TI übernommen):

P3SEL |= SDA_PIN + SCL_PIN;                 // Assign I2C pins to USCI_B0
  UCB0CTL1 = UCSWRST;                        // Enable SW reset
  UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;       // I2C Master, synchronous mode
  UCB0CTL1 = UCSSEL_2 + UCSWRST;              // Use SMCLK, keep SW reset
  UCB0BR0 = prescale;                         // set prescaler
  UCB0BR1 = 0;
  UCB0I2CSA = slave_address;                  // set slave address
  UCB0CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
  UCB0I2CIE = UCNACKIE;
  IE2 = UCB0RXIE;                            // Enable RX interrupt



Vielleicht hat jemand von euch ein Idee wo das Problem liegen könnte. Da 
ich schon den ganzen Tag dran hänge, kann es sein, dass ich mich ein 
wenig kryptisch ausgedrückt habe. Für Fragen haben ich also ein offenes 
Ohr ;)

Grüße
Seb

Autor: GastXIV (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mach mal die Pullups auf 1k2 die Flanken sind alles andere als 
berauschend.

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann ich mal versuchen. Hatte laut Hersteller 10k genommen.

Kann man den Hänger im Programm denn darauf zurückführen? Bis dahin 
findet ja noch gar keine Kommunikation statt.

Gruß
Seb

Autor: Pete K. (pete77)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich verstehe vom dem Prozessor nix, aber vielleicht sollte es ja statt:
 return (UCB0STAT & UCBBUSY); (Bitweises UND)

eher
 return (UCB0STAT && UCBBUSY); (Nur wenn beide wahr, dann alles wahr)

heissen?

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Ablauf kommt mit etwas seltsam vor. Ich habe in Erinnerung, dass bei 
I2C üblicherweise SCL und SDA nicht gleichzeitig auf 0 gehen.

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Der Ablauf kommt mit etwas seltsam vor. Ich habe in Erinnerung, dass bei
> I2C üblicherweise SCL und SDA nicht gleichzeitig auf 0 gehen.
Mir ist nicht bekannt das das eine Rolle spielen sollte. Ausserdem 
dürfte der Hardware I2C vom MSP das wohl richtig machen :)

Seb schrieb:
>So lange der Sensor nicht angeschlossen ist, sendet der MSP die korrekte
>Adresse des Sensors + Schreibbefehl, bekommt aber natürlich kein ACK
>(siehe Bild, leider schlechte Quali) vom Sensor.
Wäre ein Bild der Kommunikation die nicht geht nicht vielleicht besser?

>Der Takt ist das auf HIGH und die Datenleitung auf LOW und nüscht tut
>sich mehr.
Bitte genauer erklären.

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pete K. schrieb:
> Ich verstehe vom dem Prozessor nix, aber vielleicht sollte es ja statt:
>  return (UCB0STAT & UCBBUSY); (Bitweises UND)
>
> eher
>  return (UCB0STAT && UCBBUSY); (Nur wenn beide wahr, dann alles wahr)
>
> heissen?
Nö, das ist schon richtig so. UCB0STAT ist das Register, UCBBUSY das Bit 
im Register.

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Der Ablauf kommt mit etwas seltsam vor. Ich habe in Erinnerung, dass bei
> I2C üblicherweise SCL und SDA nicht gleichzeitig auf 0 gehen.

Tun sie ja auch nicht. Der MSP generiert jeweils eine 
Start/Stop-Bedingung, welche die Kommunikation mit dem Slave einrahmen. 
Bei der Start-Bedingung geht der Datenleitung auf low während Takt noch 
high ist. Bei stop ists läuft es andersrum ab.

Jörg S. schrieb:
> Wäre ein Bild der Kommunikation die nicht geht nicht vielleicht besser?

Tja, genau da gibt es ja nicht viel zu sehen, da gar keine Kommunikation 
zustande kommt. Der Leitung wird als "busy" erkannt und das Programm 
bleibt in der Schleife bei der Statusabfrage hängen. Wenn ich das Oszi 
an den Takt halte ist dieser high und die Datenleitung liegt auf low.

Den anderen Beitrag werde ich mir direkt mal reinziehen. Schonam Danke 
für die Hilfe.

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ai ai, die Links klingen interessant. Werde ich morgen direkt mal 
ausprobieren.

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Abziehen des Programmier-Interfaces hat bei mir genauso wenig 
gebracht wie der vorgeschlagene zyklische Reset (UCB0CTL1 |= UCSWRST;), 
falls das busy-bit gesetzt ist.

Nun verfolge ich diese Lösung:

"Die Lösung lag darin, nach Power-On des Mikrocontrollers einfach einige
zig Takte auf SCL manuell zu erzeugen, während SDA=1 bleibt. Dadurch kam
die State-Machine im EEPROM wieder in den Tritt und der I2C Controller
im Mikrocontroller fand bei Erzeugung der Start-Bedingung den korrekten
Zustand SDA=1 vor!
"

Bin mir aber noch nicht sicher wie ichdas bewerkstelligen soll. Einfach 
den SCL-PIN mit der Erstfunktion (I/O) hoch- und runterziehen?

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Gewackel mit dem SCL-PIN habe ich nun auch hinter mir. Habe zu 
Beginn der main() 50 Takte auf die SCL-Leitung gegeben während SDA high 
war. Also eigentlich so wie es in dem anderen Forenbeitrag beschrieben 
wurde. Danach läuft das Programm trotzdem in die busy-Schleife.

Ich versuche jetzt mal kleinere Pullups. Vielleicht liegt es ja wirklich 
an den runden Flanken.

Autor: Michael L. (michaelx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Busy auf dem I2C-Bus bedeutet eigentlich nichts anderes, als dass der 
Master SDA auf Low sieht, obwohl er High erwartet. Jedoch tritt diese 
Bedingung normalerweise nur im Multimasterbetrieb auf.

Den MSP kenne ich nicht, und du schreibst nicht, mit welchem Sensor du 
getestet hast. - Hm.

Pullups 1,8k - 4,7k?
Welcher Sensor?
Konntest du Verdrahtungsfehler auschließen?
Test mit einem anderen I2C-Slave?
Welche Busgeschwindigkeit?
Wurde vor dem Busy-Zustand eine Startcondition gesendet?
Wenn ja, wie viele Takte wurden ausgegeben?

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael L. schrieb:
> Pullups 1,8k - 4,7k?
> Welcher Sensor?
> Konntest du Verdrahtungsfehler auschließen?
> Test mit einem anderen I2C-Slave?
> Welche Busgeschwindigkeit?
> Wurde vor dem Busy-Zustand eine Startcondition gesendet?
> Wenn ja, wie viele Takte wurden ausgegeben?

Hi Michael,

Danke dir jetzt schonmal für deine Hilfe. Nun zu deinen (berechtigten) 
Fragen:

1. Pullups hatte ich, wie weiter oben erwähnt, 10k. Seit ein paar 
Minuten sind erstmmals 4k7 drin gelandet. Die Flanken sehen nun etwas 
steiler als auf dem Bild da oben aus. An dem Problem hat sich jedoch 
nichts geändert.

2. Sensirion LG16 (Flusssensor)

3. Verdrahtungsfehler, da gerne begangen, konnte ich erstmal 
ausschließen. Habe die Durchkontaktierungen vom Sensor bis zum µC 
geprüft und außerdem auch sichergestellt, dass sich kein leitendes 
Material zwischen Daten-/Taktleitung und Masse verirrt hat.

4. Ich habe momentan nur baugleiche Sensoren, die ich über I²C testen 
könnte und bei denen ergibt sich das gleich Bild. Wie es mit anderen 
Slaves läuft weiß ich nicht.

5. Die Busgeschwindigkeit habe ich von den im Datenblatt als typisch 
angegebenen 100 kHz bis runter auf 20kHz und hoch auf 200 kHz variiert.

6+7. Weiter oben habe ich ja den Quelltext gepostet, welcher vor der 
Abfrage des Busy-Flags ausgeführt wird. Soweit ich das sehe, wird in der 
"transmitinit" keine Start-Condition gesetzt.

Autor: Pete K. (pete77)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du hast aber schon einen digitalen Sensor mit Endung -D ?

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Pete K. schrieb:
> Du hast aber schon einen digitalen Sensor mit Endung -D ?

Jupp.

Problem ist einfach, dass mir der Sensor die SDA-Leitung auf low zieht.

Autor: Michael L. (michaelx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du den MSP vom I2C-Bus abtrennst, nur den LG16 und die Pullups 
dran, wie sind dann die Pegel von SCL und SDA? Falls SDA auf Low liegt, 
versuchsweise ein paar Takte auf SCL geben und beobachten.

Kannst du evtl. doch ein Bild auf den Oszi bringen? (Mal die 
Busy-Abfrage auskommentieren oder ein kleines Testprogramm)

Versuche ggf. einen TCN75 als Alternative zu testen.

Autor: Jörg S. (joerg-s)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Seb schrieb:
> 6+7. Weiter oben habe ich ja den Quelltext gepostet, welcher vor der
> Abfrage des Busy-Flags ausgeführt wird. Soweit ich das sehe, wird in der
> "transmitinit" keine Start-Condition gesetzt.
Ach so, der Fehler kommt nach dem transmitinit und nicht nach einem 
Zugriffsversuch?

Autor: Seb (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So, vielleicht bin ich schon ein wenig weitergekommen.

Zu Beginn der Main gebe ich dem Sensor ein paar Takte auf die Leitung 
(siehe Bild). Dabei wird die SDA-Leitung hochgezogen.

Danach mache ich folgendes, um eine Messung zu starten:
  SENSIRION_transmitinit(SENSIRION_ADRESS);           // init transmitting the measurement start sequence
   
  while ( SENSIRION_notready() );                     // wait for bus to be free
  if ( SENSIRION_slave_present(SENSIRION_ADRESS) )    // flow sensor present?    
  { 
    SENSIRION_transmitinit(SENSIRION_ADRESS);           // init transmitting the measurement start sequence
    while ( SENSIRION_notready() );    
    SENSIRION_transmit(0x01,(unsigned char*)SENSIRION_flowMeas);      // Send start measurement command         
                            
    SENSIRION_receiveinit(SENSIRION_ADRESS);          // init receiving the measurement data
    while ( SENSIRION_notready() );                   // wait for bus to be free
    SENSIRION_receive(0x03,meas_data);                // start receiving the measurement data
    while ( SENSIRION_notready() );                   // wait for bus to be free  

Nach dem ersten Slave Present erscheint das zweite Bild. Heißt also 
schonmal, dass er nicht mehr in der ersten Busy-Schleife hängen bleibt. 
Der ACK sieht jedoch etwas verzögert aus (kleiner Peak).

Wenn ich nun schrittweise durchsteppe läuft das Programm. Sobal ich 
jedoch meine Breakpoints entferne, bleibt das die Sache schnell wieder 
in der busy-Schleife hängen. Vielleicht muss ich dem Sensor noch ein 
bisschen mehr Zeit zwischen den einzelnen Aktionen geben. Halte euch auf 
dem laufenden.

Gruß
Seb

Autor: Michael L. (michaelx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was machen eigentlich deine Funktionen SENSIRION_transmitinit, 
SENSIRION_transmit usw.? Es sieht m.E. nämlich so aus, dass du einzelne 
Bytes auf den Bus wirfst, aber keinen Daten-Transfer im eigentlichen 
Sinne der Spezifikation machst.

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie im Eingangspost erwähnt verwende ich die Appnote SLAA832 von TI. 
Soweit ich diese verstanden habe, kann man im Sinne von I2C Bytes 
verschicken und empfangen.

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PS: Die Funktionen sind auch aus der Appnote. In meinem Projekt tragen 
die nur den Namen des Sensors vorweg.

Autor: Michael L. (michaelx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na gut, die App-Note kenne ich nicht, wollte nur andeuten, dass Adress- 
und Datenbyte "in einem Rutsch" zu übertragen sind. Dazwischen darf 
keine Stop-Condition kommen.

Autor: Seb (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Michael: Jupp, da habe ich ein Auge drauf. Ich nähere mich so langsam 
dem Problem. Ich habe da an zwei Stellen Datentypen "missverstanden", 
welche in der Appnote übergeben werden.


...


Ich glaube ich habs! Nun zappeln die Daten über die Leitung und auf den 
ersten Blick sieht das sinnvoll aus. Die Messfunktion sieht nun so aus:

SENSIRION_transmitinit(SENSIRION_ADRESS);           // init transmitting the measurement start sequence
   
  while ( SENSIRION_notready() );                     // wait for bus to be free
  if ( SENSIRION_slave_present(SENSIRION_ADRESS) )    // flow sensor present?    
  { 
    SENSIRION_transmitinit(SENSIRION_ADRESS);         // init transmitting the measurement start sequence
    while ( SENSIRION_notready() );    
    SENSIRION_transmit(1,flowMeas);                   // Send start measurement command         
    while ( SENSIRION_notready() );                   // wait for bus to be free                        
    SENSIRION_receiveinit(SENSIRION_ADRESS);          // init receiving the measurement data    
    while ( SENSIRION_notready() );                   // wait for bus to be free
    SENSIRION_receive(3,meas_data);                   // start receiving the measurement data
    while ( SENSIRION_notready() );                   // wait for bus to be free  
  }



Punkte, welche zur Lösung beigetragen haben:

1. Sensor erstmal mit ein paar Takten füttern bevor etwas anderes 
gemacht wird.

2. Ich habe bei transmit und receive keine Felder übergeben. So war es 
jedoch in der Appnote gewollt.

3. Vor dem Receiveinit muss nochmal der Bus abgefragt werden, weil die 
Initialisierung zu flott kommt.

Jetzt muss ich das Bitgewackel noch in physikalische Werte umrechnen und 
dann bin ich hoffentlich glücklich.

Danke nochmal für all die Anregungen.

Gruß
Seb

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.