Forum: Mikrocontroller und Digitale Elektronik DS1631 I2C Ansteuerung - Interpretationsprobleme


von Teddy (Gast)


Lesenswert?

Hallo,
wie einige wissen, beschäftige ich mich Zurzeit mit I2C. Das 
Grundprinzip scheine ich verstanden zu haben.
Da ich mit MCP23017 weniger Glück hatte, habe ich mich mit dem DS1631 
beschäftigt.

Ich habe zur Zeit Probleme mit der Datenverarbeitung.
Habe die MSB Bytes und LSB Bytes ausgelesen. Die MSB Bytes müsste ich 
nur auf das Vorzeichen prüfen.

Wie gehe ich mit dem LSB Byte um? Beim LSB Byte geht es ja um die 
Nachkommastellen.
Im Grunde müsste ich die Bits, die gesetzt sind überprüfen und diese 
dann mit dem MSB Bytes verrechnen, aber ich komme nicht klar wie.
1
void DS1631_Temperatur_Read(void)
2
{
3
  uint8_t temp_MSB;
4
  uint8_t temp_LSB;
5
      
6
  I2C_Startbit();
7
  I2C_Slave_RW(I2C_Schreiben);
8
  I2C_Send_Data(Temperatur_Ablesen);
9
  I2C_Startbit();
10
  I2C_Slave_RW(I2C_Lesen);
11
  temp_MSB=I2C_Receive_Data();
12
  temp_LSB=I2C_Receive_Data();
13
  I2C_Stopbit();
14
  
15
  //USART_Transmit_Strings("Die Temperatur betraegt\n");
16
  USART_Transmit(temp_MSB);
17
  //USART_Transmit_Strings(" °C");
18
  
19
}


Dann habe ich noch ein merkwürdiges Problem. Die Funktion
lasse ich in einer While(1) schleife laufen. Leider wird mir nur eine 
Temperatur ausgegeben. Danach hört die Schleife auf.
Das konnte ich durch eine Diode überprüfen. Der Code sieht wie folg aus.
1
#include <avr/io.h>
2
#include "DS1631.h"
3
#include "USART.h"
4
#include "I2C.h"
5
#include <util/delay.h>
6
7
8
int main(void)
9
{  
10
  DDRB=0x00;
11
  PORTB=0x01;
12
  
13
  USART_Init(MYUBRR);
14
  I2C_Init();
15
  DS1631_Config(0x0C);
16
  DS1631_Start_Convert();
17
  while(1)
18
  {
19
      DS1631_Temperatur_Read();    //Temp auslesen
20
      PORTB^=PORTB;                //LED toggeln
21
      _delay_ms(2000);             //ca 2sekunden warten
22
  }
23
24
25
}

von spess53 (Gast)


Lesenswert?

Hi

>  I2C_Slave_RW(I2C_Lesen);
>  temp_MSB=I2C_Receive_Data();
>  temp_LSB=I2C_Receive_Data();  <<<<<<<
>  I2C_Stopbit();

Zwischenfrage: Beim Lesen des letzten Bytes muss der Master ein NACK 
schicken. Das vermisse ich hier.

MfG Spess

von Teddy (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>>  I2C_Slave_RW(I2C_Lesen);
>>  temp_MSB=I2C_Receive_Data();
>>  temp_LSB=I2C_Receive_Data();  <<<<<<<
>>  I2C_Stopbit();
>
> Zwischenfrage: Beim Lesen des letzten Bytes muss der Master ein NACK
> schicken. Das vermisse ich hier.
>
> MfG Spess

My bad.
Tatsächlich läufts es jetzt.

Wie könnte ich mit dem LSB Byte angehen?
Wie gesagt. Zu Fuß würde ich so vorgehen, dass ich jedes Bit überprüfe, 
ob diese gesetzt sind, dann würde ich dementsprechend rechnen.
Die ersten 4 Bits (0 bis 3) sind 0.
Ist zb das 4. gesetzt, dann rechne ich 2^(-4) dazu, bei 3. Bit 2^(-3) 
usw.
Kennt ihr ne elegantere Lösung?

von Teddy (Gast)


Lesenswert?

PUSH.

Folgendes:

Mein Code für den LSB Byte sieht wie folgt aus, zwar nicht elegant, aber 
sollte funktionieren.
1
void DS1631_Temperatur_Read(void)
2
{
3
  uint8_t temp_MSB;
4
  uint8_t temp_LSB;
5
  float zahl = 0;  
6
  char buffer[30];
7
8
  I2C_Startbit();
9
  I2C_Slave_RW(I2C_Schreiben);
10
  I2C_Send_Data(Temperatur_Ablesen);
11
  I2C_Startbit();
12
  I2C_Slave_RW(I2C_Lesen);
13
  temp_MSB=I2C_Receive_Data();
14
  temp_LSB=I2C_Receive_Data();
15
  I2C_NACKbit();
16
  I2C_Stopbit();
17
  
18
  if(temp_LSB & 0x80)
19
  {
20
    zahl = 0.5 + zahl;
21
  }
22
  if(temp_LSB & 0x40)
23
  {
24
    zahl = 0.25 + zahl;
25
  }
26
  if(temp_LSB & 0x20)
27
  {
28
    zahl = 0.125 + zahl;
29
  }
30
  if(temp_LSB & 0x10)
31
  {
32
    zahl = 0.0625 + zahl;
33
  }
34
  
35
  zahl = zahl + (float) temp_MSB;
36
  
37
  sprintf(buffer, "%f", zahl);
38
  
39
  //USART_Transmit_Strings("Die Temperatur betraegt\n");
40
  USART_Transmit_Strings(buffer);
41
  //USART_Transmit_Strings(" °C");
42
}

Statt dem Temperaturwert bei buffer wird bei mir nur ?????? (Arduino 
Serieller Monitor) bzw. HTerm.exe ausgegeben.

von Auweia (Gast)


Lesenswert?

Teddy schrieb:
> if(temp_LSB & 0x80)
>   {
>     zahl = 0.5 + zahl;
>   ...
>     zahl = 0.0625 + zahl;
> }
>
>   zahl = zahl + (float) temp_MSB;

Das ist jetzt nicht wahr, oder?

Was hieltest du davon, das LSB so zu nehmen wie es ist und z.B. mit 
(1/256.0) gewichtet zu deinem MSB hinzu zu addieren?

von Auweia (Gast)


Lesenswert?

p.s.
Die Tücke dieser Handpulerei liegt bei der 0.
Wenn du aus MSB und LSB zunächst einen 16-Bit signed int machst und den 
dann mit (1/256.0) multiplizierst, passt alles automatisch.

von Klaus R. (klara)


Lesenswert?

Teddy schrieb:
> Mein Code für den LSB Byte sieht wie folgt aus, zwar nicht elegant, aber
> sollte funktionieren.

Hier ist meiner.
1
       Dim cRxDaten As String = USB.RXDaten
2
        '---------------------
3
        Dim iWert As Int32 = 0
4
        Dim iWert0 As Int32 = 0
5
        Dim iWert1 As Int32 = 0
6
7
        iWert0 = Asc(cRxDaten.Substring(1, 1))
8
        iWert1 = Asc(cRxDaten.Substring(2, 1))
9
10
        Try
11
            If CBool(iWert0 And &H80) Then
12
                iWert = (128 - (iWert0 And &H7F))       'alt: iWert0 & &H7F
13
                iWert = iWert * (-10000)
14
            Else
15
                iWert = iWert0
16
                iWert = iWert * 10000
17
            End If
18
            iWert = CInt(iWert + ((iWert1 / (2 ^ 4)) * 625)) ' data2 shr 4
19
            Return iWert
20
        Catch Ex As Exception
21
            Log.File.WriteHandledException(Ex)
22
            iStatus = I2C_Integer_Ueberlauf
23
            Return 0
24
        End Try

von eProfi (Gast)


Lesenswert?


von Teddy (Gast)


Lesenswert?

Danke Jungs, aber ich kann euren Code leider nicht lesen.
Ich habe jetzt so gemacht, wie hier im Thread:

Beitrag "Re: I2C DS1631 nur NACK"

Ganz unten. Klappt auch, ich muss mir nur die Umrechnung mal anschauen.

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.