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


von Martin (Gast)


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_information/Sample_Code_humidity_sensor_SHTxx.pdf 
ist folgender Code (für einen 80C51) zum Schreiben eines Bytes zu 
finden:
1
char s_write_byte(unsigned char value) 
2
{  
3
  unsigned char i,error=0;   
4
  for (i=0x80;i>0;i/=2)             //shift bit for masking 
5
  { if (i & value) DATA=1;          //masking value with i , write to SENSI-BUS 
6
    else DATA=0;                         
7
    _nop_();                        //observe setup time 
8
    SCK=1;                          //clk for SENSI-BUS 
9
    _nop_();_nop_();_nop_();        //pulswith approx. 5 us    
10
    SCK=0; 
11
    _nop_();                         //observe hold time 
12
  } 
13
  DATA=1;                           //release DATA-line 
14
  _nop_();                          //observe setup time 
15
  SCK=1;                            //clk #9 for ack  
16
  error=DATA;                       //check ack (DATA will be pulled down by SHT11) 
17
  SCK=0;         
18
  return error;                     //error=1 in case of no acknowledge 
19
}

Für den MSP, wollte ich den Code so hier umschreiben (DATA hängt dabei 
an P5.1, SCK an P5.2):
1
#define SHT75_SET_DATA_AS_OUTPUT()  P5DIR |= BIT1
2
#define SHT75_SET_DATA_AS_INPUT()   P5DIR &= ~BIT1
3
#define SHT75_SET_DATA_HIGH()       P5OUT |= BIT1
4
#define SHT75_SET_DATA_LOW()        P5OUT &= ~BIT1
5
#define SHT75_DATA_IS_HIGH()        P5OUT & BIT1
6
7
#define SHT75_SCK_LOW()     P5OUT &= ~BIT2;
8
#define SHT75_SCK_HIGH()    P5OUT |=  BIT2;
9
10
char s_write_byte(unsigned char value)
11
{
12
  unsigned char i, error = 0;
13
14
  for (i=0x80;i>0;i/=2) {         
15
      if (i & value) {
16
          SHT75_SET_DATA_HIGH();       
17
      }
18
      else {
19
          SHT75_SET_DATA_LOW();
20
      }
21
      _nop_();                        
22
      SHT75_SCK_HIGH;                 
23
      _nop_();_nop_();_nop_();        
24
      SHT_75_SCK_LOW();
25
      _nop_();                        
26
  }
27
  SHT75_SET_DATA_HIGH;                
28
  _nop_();                          
29
  SHT75_SCK_HIGH();                 
30
  SHT75_SET_DATA_AS_INPUT();
31
  if(SHT75_DATA_IS_HIGH()) {
32
      error = 1;
33
  }                     
34
  SHT75_SCK_LOW();
35
  return error;                     
36
}
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_information/Datasheet-humidity-sensor-SHT7x.pdf)Seite 
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!

von Tobi (Gast)


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 :-))

von Martin (Gast)


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
1
  ...
2
  SHT75_SET_DATA_HIGH;                
3
  _nop_();                          
4
  SHT75_SCK_HIGH();                 
5
  SHT75_SET_DATA_AS_INPUT();
6
  if(SHT75_DATA_IS_HIGH()) {
7
      error = 1;
8
  }                     
9
  SHT75_SCK_LOW();
10
  return error;

folgendes schreiben:
1
  ...
2
  SHT75_SET_DATA_HIGH;                
3
  _nop_();                          
4
  SHT75_SET_DATA_AS_INPUT();
5
  SHT75_SCK_HIGH();                 
6
  if(SHT75_DATA_IS_HIGH()) {
7
      error = 1;
8
  }                     
9
  SHT75_SCK_LOW();
10
  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?

von Martin (Gast)


Lesenswert?

Entschuldige bitte den Namensdreher. :/

von Martin (Gast)


Lesenswert?

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

von Martin (Gast)


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?
1
unsigned char sht75_write_byte(unsigned char value)
2
{
3
  unsigned char i, error = 0;
4
5
  SHT75_SET_DATA_AS_OUTPUT;              //Data als Ausgang setzen
6
  for (i=0x80;i>0;i/=2) {               
7
      if (i & value) {
8
          SHT75_SET_DATA_AS_INPUT;       //High auf Bus setzen über Pull up
9
      }
10
      else {
11
          SHT75_SET_DATA_AS_OUTPUT;      //Low über Ausgang
12
          SHT75_SET_DATA_LOW;
13
      }
14
      NOP();                             //hier nicht relevant
15
      SHT75_SCK_HIGH;                    
16
      NOP();NOP();NOP();                 // "
17
      SHT_75_SCK_LOW;
18
      NOP();                             // "
19
  }
20
  SHT75_SET_DATA_AS_INPUT;               //High auf Bus setzen über Pull up = Bus Release
21
  NOP();                                 //hier nicht relevant
22
  SHT75_SCK_HIGH;                        
23
  if(SHT75_DATA_IS_HIGH) {
24
      error = 1;
25
  }
26
  SHT75_SCK_LOW;
27
  return error;                         
28
}

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.