www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Verständnisproblem: 2-Draht Bus + Umschaltung Input/Ouput = Kurzschluss?


Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich möchte einen SHT75 mittels MSP430F2618 abfragen. Der Sensor 
verwendet ein "proprietäres" 2-Draht Protokoll mit einer Takt- sowie 
einer Datenleitung (SCK und DATA). Dabei bin ich gerade auf ein 
Verständnisproblem gestossen.
In 
http://www.sensirion.com/en/pdf/product_informatio... 
ist folgender Code (für einen 80C51) zum Schreiben eines Bytes zu 
finden:
char s_write_byte(unsigned char value) 
{  
  unsigned char i,error=0;   
  for (i=0x80;i>0;i/=2)             //shift bit for masking 
  { if (i & value) DATA=1;          //masking value with i , write to SENSI-BUS 
    else DATA=0;                         
    _nop_();                        //observe setup time 
    SCK=1;                          //clk for SENSI-BUS 
    _nop_();_nop_();_nop_();        //pulswith approx. 5 us    
    SCK=0; 
    _nop_();                         //observe hold time 
  } 
  DATA=1;                           //release DATA-line 
  _nop_();                          //observe setup time 
  SCK=1;                            //clk #9 for ack  
  error=DATA;                       //check ack (DATA will be pulled down by SHT11) 
  SCK=0;         
  return error;                     //error=1 in case of no acknowledge 
} 

Für den MSP, wollte ich den Code so hier umschreiben (DATA hängt dabei 
an P5.1, SCK an P5.2):
#define SHT75_SET_DATA_AS_OUTPUT()  P5DIR |= BIT1
#define SHT75_SET_DATA_AS_INPUT()   P5DIR &= ~BIT1
#define SHT75_SET_DATA_HIGH()       P5OUT |= BIT1
#define SHT75_SET_DATA_LOW()        P5OUT &= ~BIT1
#define SHT75_DATA_IS_HIGH()        P5OUT & BIT1

#define SHT75_SCK_LOW()     P5OUT &= ~BIT2;
#define SHT75_SCK_HIGH()    P5OUT |=  BIT2;

char s_write_byte(unsigned char value)
{
  unsigned char i, error = 0;

  for (i=0x80;i>0;i/=2) {         
      if (i & value) {
          SHT75_SET_DATA_HIGH();       
      }
      else {
          SHT75_SET_DATA_LOW();
      }
      _nop_();                        
      SHT75_SCK_HIGH;                 
      _nop_();_nop_();_nop_();        
      SHT_75_SCK_LOW();
      _nop_();                        
  }
  SHT75_SET_DATA_HIGH;                
  _nop_();                          
  SHT75_SCK_HIGH();                 
  SHT75_SET_DATA_AS_INPUT();
  if(SHT75_DATA_IS_HIGH()) {
      error = 1;
  }                     
  SHT75_SCK_LOW();
  return error;                     
}
Meine Frage/Verständnisproblem:
DATA kann ja sowohl Eingang als auch Ausgang sein. In der ersten 
Funktion für den 80C51 scheint das wohl keine Rolle zu spielen 
(zumindest wird dort ja nirgends zwischen Ein- und Ausgang 
umgeschalten), dem MSP muss ich ja aber stets sagen, ob der Pin nun als 
Ein- oder Ausgang verwendet wird. Aus diesem Grund schalte ich mit 
SHT75_SET_DATA_AS_INPUT() den Pin 5.1 als Eingang, wenn ich auf ein ACK 
prüfen möchte.
Jetzt frage ich mich aber, ob ich das so machen kann. Denn wenn der 
Sensor eine 0 schickt (ACK) und ich schalte ein bisschen zu spät auf 
Eingang am MSP, dann habe ich immer noch eine 1 und damit doch einen 
Kurzschluss - oder?
Im Datenblatt 
(http://www.sensirion.com/en/pdf/product_informatio... 
7, Figure 12 sieht man genau so einen Fall. Oder muss das 
SHT75_SET_DATA_AS_INPUT() vor dem SHT75_SET_DATA_AS_INPUT() aufgerufen 
werden?

Ich danke sehr für eure Hilfe!

Autor: Tobi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst nur sicherstellen, dass VOR dem Schalten von SCK auf 1 der Pin 
DATA als input geschalten ist. Wenn SCK low ist, passiert ja noch nnix 
:-)

Andere Alternative: Pull Up mit Diode --> Quasi ein Open Collector:

           Vcc
            |
           | |  Pull Up, z.B. 10k
           | |
            |
Pin ----<|-----

       Diode

Dann kann nix mehr passieren :-))

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hey Toby,

danke für deine schnelle Antwort!

> Du musst nur sicherstellen, dass VOR dem Schalten von SCK auf 1 der Pin
> DATA als input geschalten ist. Wenn SCK low ist, passiert ja noch nnix
Das meinte ich mit meinem letzten Satz, da war ein Dreher drin, statt 
dem ersten SHT75_SET_DATA_AS_INPUT() sollte dort ein SHT75_SCK_HIGH() 
stehen.

Also sollte ich statt
  ...
  SHT75_SET_DATA_HIGH;                
  _nop_();                          
  SHT75_SCK_HIGH();                 
  SHT75_SET_DATA_AS_INPUT();
  if(SHT75_DATA_IS_HIGH()) {
      error = 1;
  }                     
  SHT75_SCK_LOW();
  return error; 

folgendes schreiben:
  ...
  SHT75_SET_DATA_HIGH;                
  _nop_();                          
  SHT75_SET_DATA_AS_INPUT();
  SHT75_SCK_HIGH();                 
  if(SHT75_DATA_IS_HIGH()) {
      error = 1;
  }                     
  SHT75_SCK_LOW();
  return error; 
Wenn ich es allerdings so mache, stellt sich mir eine andere Frage:
Wie bekommt der SHT dann aber überhaupt mit, dass ich nochmal DATA auf 
HIGH gelegt habe? Ohne Takt dürfte der doch gar nix machen - oder?

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entschuldige bitte den Namensdreher. :/

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder anders gefragt:
Welchen Sinn hat überhaupt, die Leitung wieder auf HIGH zu setzen?

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube ich hab mir die Frage selbst beantwortet. Im Datenblatt steht 
außerdem:

"To avoid signal contention the microcontroller must only
drive DATA low. An external pull-up resistor (e.g. 10 kΩ) is
required to pull the signal high"

Damit sollte ich also niemals DATA per "Hand" auf HIGH setzen. Deswegen 
habe ich den Code jetzt so geändert, dass er immer den Pin auf Eingang 
schaltet (es gibt ja keinen Tristate) wenn ich den Bus freigeben möchte. 
Damit müsste der Bus über den Pull up auf HIGH gezogen werden.
Folgender Code müsste es dann also tun. Richtig oder Falsch?
unsigned char sht75_write_byte(unsigned char value)
{
  unsigned char i, error = 0;

  SHT75_SET_DATA_AS_OUTPUT;              //Data als Ausgang setzen
  for (i=0x80;i>0;i/=2) {               
      if (i & value) {
          SHT75_SET_DATA_AS_INPUT;       //High auf Bus setzen über Pull up
      }
      else {
          SHT75_SET_DATA_AS_OUTPUT;      //Low über Ausgang
          SHT75_SET_DATA_LOW;
      }
      NOP();                             //hier nicht relevant
      SHT75_SCK_HIGH;                    
      NOP();NOP();NOP();                 // "
      SHT_75_SCK_LOW;
      NOP();                             // "
  }
  SHT75_SET_DATA_AS_INPUT;               //High auf Bus setzen über Pull up = Bus Release
  NOP();                                 //hier nicht relevant
  SHT75_SCK_HIGH;                        
  if(SHT75_DATA_IS_HIGH) {
      error = 1;
  }
  SHT75_SCK_LOW;
  return error;                         
}

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.