DS1631 I2C Ansteuerung - Interpretationsprobleme

Gast #5097241
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
}
Gast #5097265
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
Gast #5097313
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?
Gast #5097604
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.
Gast #5097613
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?
#5097693
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren