Forum: Mikrocontroller und Digitale Elektronik i2C uint8_t *data


von mark (Gast)


Lesenswert?

hallo

Ich mache hier mal einen neuen Thread auf, da ich denke, dass dies nicht 
mehr viel mit dem anderen Thema von mir zu tun hat.

Ich lese bei meinem Sensor DS1621 die Temperatur aus.
Laut Datenblatt bekomme ich 2Byte zurück geliefert. MSB first

Nun habe ich die Transmit- und die Receivefunktion vom I2C die folgend 
aufgebaut ist:

HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, 
uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);

HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, 
uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);


Beim Transmit gebe ich den Command, dass ich die Temperatur auswerten 
möchte heraus, das wäre dann die Angabe pData. Da ich nur den Command 
Read_Temp möchte, ist auch die Länge/Size 1Byte, also 1

Beim Receive dann aber -->
muss ich die Adresse angeben, wo er mir die Daten uint8_t Daten 
hinspeichern soll.
zB &rxData
die Grösse muss dann aber 2 Byte angegeben werden, also Size= 2

Jetzt kommt ja das MSB zuerst an, diese Werte können nun positiv aber 
auch negativ sein.
Wie erkenne ich das aber wenn in der Receive Funktion der pointer auf 
einen uint8_t zeigt???

Ausserdem was ich wissen möchte ist, wenn ich zB einen Pointer definiert 
habe ist ja, weil das MSB zuerst geschickt wird, der Wert vom pointer *p 
= MSB-Byte (irgend ein uint8_t Wert)

wenn ja, wie komme ich dann an das LSB-Byte?
ich habe das noch nicht so ganz verstanden... wie die Fkt. tickt..

Ich hätte jetzt einfach 2 Pointer gemacht uint8_t* p_rxDataH, p_rxDataL;
Aber ich habe keine Ahnung wie ich durch die einmalig aufzurufende Fkt 
Receive an 2 Werte komme, vor allem wie ich durch uint8_t auch negative 
Werte erhalte??

Ich hoffe es kann mir jemand weiterhelfen..

von Harry L. (mysth)


Lesenswert?


von Dirk B. (dirkb2)


Lesenswert?

Es gibt in C die Möglichkeit Mehrere Element desselben Datentyps 
zusammenhängend im Speicher zu halten. Das wird Array genannt.

Du kannst auch eine struct dafür anlegen.

Die Empfangenen Daten musst du dann entsprechen auswerten und passend 
zusammenbauen.

Wenn dein Rechner auch im Zweierkomplement rechnet geht das z.B so:
1
uint8_t ds_data[2];
2
... // Temperaturdaten empfangen
3
short Temp = ds_data[0] << 8 | ds_data[1];

von Joe F. (easylife)


Lesenswert?

pData ist ein array, und du übergibst der funktion einen Pointer auf das 
erste Arrayelemnt.

uint8_t pData[20];
 -> funtionsaufruf

MSB steht dann in pData[0], LSB in pData[1].

Danach kannst du MSB auf int8 casten, wenn dich das Vorzeichen 
interessiert.

int8_t temp_msb = (int8_t)pData[0];

von mark (Gast)


Lesenswert?

Joe F. schrieb:
> pData ist ein array, und du übergibst der funktion einen Pointer
> auf das
> erste Arrayelemnt.
>
> uint8_t pData[20];
>  -> funtionsaufruf
>
> MSB steht dann in pData[0], LSB in pData[1].
>
> Danach kannst du MSB auf int8 casten, wenn dich das Vorzeichen
> interessiert.
>
> int8_t temp_msb = (int8_t)pData[0];

achsooo, danke :)

ja ich frage deshalb so deppert, weil ich den Fehler schon mal gemacht 
habe und mich mit pointern vertan habe.
Ich habe diese Funktion hier geschrieben und verwende hier normale 
variablen statt pointern.

Wenn doch pData ein Array ist, wieso kann ich das dann direkt einer 
Variable übergeben??
zB an uint8_t var;
var = accessConfig(); ??
Weil es nehme ich an, ein 1Byte Array ist, also Size=1 nehme ich an.

Wenn ja, dann habe ich das jetzt nicht nur zu 99.9 % verstanden, sondern 
100.
1
uint8_t accessConfig(void) 
2
{ 
3
    uint8_t txData;                                                // sending dataarray for access_config command 
4
    static uint8_t rxData;                                         // receiving dataarray for access_config command 
5
                                                                   // static because of variable rxData validity only within the function
6
    txData = ACCESS_CONFIG; 
7
    
8
  
9
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10);    // Shift is necessary because of i2C function description 
10
    HAL_I2C_Master_Receive(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &rxData, sizeof(rxData), 10);     // Shift is necessary because of i2C function description 
11
    return rxData;
12
}

von mark (Gast)


Lesenswert?

Harry L. schrieb:
> Solltest du dringend mal lesen!
> http://cs.indstate.edu/~cbasavaraj/cs559/the_c_pro...

Ich klicke unbekannte Links an (Virengefahr). :P
Was ist das?

von Harry L. (mysth)


Lesenswert?

mark schrieb:
> Harry L. schrieb:
>> Solltest du dringend mal lesen!
>> http://cs.indstate.edu/~cbasavaraj/cs559/the_c_pro...
>
> Ich klicke unbekannte Links an (Virengefahr). :P
> Was ist das?

Der Link zu einem PDF

Das WWW basiert auf Links, und, wenn du hinter jedem Link etwas 
bösartiges vermutest, solltest du lieber nur lokal und ohne jede 
Verbindung zur Aussenwelt leben.

Wenn dir "gefühlte Sicherheit" so ungeheuer wichtig ist, nutz doch 
Linux!

Merke: der effektivste aller Viren-Scanner, der bei jeden "gratis" und 
"kostenlos" Alarm schlagen sollte, sitzt zwischen deine 2 Ohren ;)

Ohne den gesunden Menschenverstand, bist du jedoch mit jedem OS nur ein 
"Opfer"

: Bearbeitet durch User
von mark (Gast)


Lesenswert?

Harry L. schrieb:
> mark schrieb:
>> Harry L. schrieb:
>>> Solltest du dringend mal lesen!
>>> http://cs.indstate.edu/~cbasavaraj/cs559/the_c_pro...
>>
>> Ich klicke unbekannte Links an (Virengefahr). :P
>> Was ist das?
>
> Der Link zu einem PDF
>
> ....und wenn du so große Angst vor Viren hast (die dich blockiert)
> solltest du dringend einen Wechsel von Windows zu Linux überdenken.
>
> Merke: der effektivste aller Viren-Scanner, der bei jeden "gratis" und
> "kostenlos" Alarm schlagen sollte, sitzt zwischen deine 2 Ohren ;)

Scheiss auf Linux ;P
wegen so ner Frage schickst du mir sowas?
Das Ding hat ja 500 000 Seiten.. und trockenes English

von Harry L. (mysth)


Lesenswert?

Wenn du nicht in der Lage bist, sowas zu verstehen, empfehle ich dir, 
dir nen anderes Hobby zu suchen.

Für Digitaltechnik und Mikrocontroller scheint es dir an den 
erforderlichen Voraussetzungen zu mangeln.

: Bearbeitet durch User
von mark (Gast)


Lesenswert?

Harry L. schrieb:
> Wenn du nicht in der Lage bist, sowas zu verstehen, empfehle ich
> dir,
> dir nen anderes Hobby zu suchen.
>
> Für Digitaltechnik und Mikrocontroller scheint es dir an den
> erforderlichen Voraussetzungen zu mangeln.

ok, weil du es sagst, höre ich gleich morgen damit auf.
Aber davor mache ich noch meine Uebung fertig ;)

von mark (Gast)


Lesenswert?

Harry L. schrieb:
> Wenn du nicht in der Lage bist, sowas zu verstehen, empfehle ich
> dir,
> dir nen anderes Hobby zu suchen.
>
> Für Digitaltechnik und Mikrocontroller scheint es dir an den
> erforderlichen Voraussetzungen zu mangeln.

Ein letztes Wort: Einen Tipp habe ich für dich auch noch.
Wenn du kein Spass verstehst, dann bleib lieber zu Hause.

Und ja manchmal frage ich mich selbst, ob ich zu kompliziert denke und 
sehe es sogar ein.

Aber zum Glück gibt es so Leute, wie Joe F. oder DirkB, die Dinge, die 
ich zB und womöglich viele andere irgendwie tief im Inneren zwar wissen, 
zumindest annähernd, es aber doch noch nicht so ganz begriffen oder 
vielleicht Teile davon vergessen haben, trotzdem sehr gut erklären, ohne 
die Leute versuchen klein zu reden.

Wie es aber aussieht, scheint es dir aber wiederum dafür an den 
erforderlichen Voraussetzungen zu mangeln zu erkennen, dass man für 
gewisse Fragen nicht ein ganzes 258 seitiges Buch lesen muss, um die 
Lösung für das Problem zu finden und voran zu kommen und nicht jeder ein 
kompletter Idiot ist, wenn er vllt. auch mal etwas "blödere" Fragen 
stellt.

Aber ja, da bist du sicher anderer Meinung.
Gute Nacht..

von mark (Gast)


Lesenswert?

Joe F. schrieb:
> pData ist ein array, und du übergibst der funktion einen Pointer
> auf das
> erste Arrayelemnt.
>
> uint8_t pData[20];
>  -> funtionsaufruf
>
> MSB steht dann in pData[0], LSB in pData[1].
>
> Danach kannst du MSB auf int8 casten, wenn dich das Vorzeichen
> interessiert.
>
> int8_t temp_msb = (int8_t)pData[0];


So, die Fkt. ist zwar noch nicht ganz fertig, aber ich denke, so müsste 
es klappen.
1
uint8_t readTemperature(TEMP_RES res)
2
{  
3
    uint8_t txData = READ_TEMPERATURE;                           // sending dataarray for access_config command
4
    uint8_t rxData[2];
5
    uint8_t *p_rxDataH;                                          // pointer for MSB Byte 
6
    uint8_t *p_rxDataL;                                          // pointer for MSB Byte 
7
8
    struct Array
9
    {
10
      int8_t HByte;
11
      uint8_t LByte;  
12
    };
13
    
14
    struct Array ByteArray;
15
     
16
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10);    // Shift is necessary because of i2C function description 
17
    HAL_I2C_Master_Receive(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, rxData, sizeof(rxData), 10);     // Shift is necessary because of i2C function description 
18
    
19
    p_rxDataH = rxData;
20
    p_rxDataL = p_rxDataH++;
21
    
22
    ByteArray.HByte = (int8_t) *p_rxDataH;                       // must be casted from uint8_t to int8_t
23
    ByteArray.LByte = *p_rxDataH;                                // must not be casted, because always positive
24
}

von Joe F. (easylife)


Lesenswert?

mark schrieb:
> aber ich denke, so müsste
> es klappen.

Könnte so klappen, ist aber unnötig kompliziert.
Es spricht nichts dagegen die Größe der Buffer für den I2C Transfer 
größer zu machen, als sie für eine individuelle Transaktion benötigt 
wird.
Evtl. gibt es noch andere I2C Slaves, und dann kann man die Buffer 
wiederverwenden.

Vorschlag:
1
uint8_t txDataBuf[10]; 
2
uint8_t rxDataBuf[10];
3
4
uint8_t readTemperature(TEMP_RES res)
5
{  
6
    struct
7
    {
8
      int8_t  HByte;
9
      uint8_t LByte;  
10
    } ByteArray;
11
    
12
    txDataBuf[0] = READ_TEMPERATURE;
13
     
14
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, txDataBuf, 1, 10);
15
    HAL_I2C_Master_Receive (&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, rxDataBuf, 2, 10);
16
            
17
    ByteArray.HByte = (int8_t)rxDataBuf[0]; // der explizite cast auf int8_t ist hier eigentlich überflüssig, da ByteArray.HByte schon als int8_t definiert ist, aber schaden kann es nicht
18
    ByteArray.LByte = rxDataBuf[1];
19
    
20
    // ...
21
}

Wofür ist eigentlich das Argument "TEMP_RES res" in dieser Funktion?

Als Minimalist oder wenn einem das umkopieren der 3 Bytes zu 
zeitkritisch ist, kann man es auch so machen:
1
uint8_t readTemperature(TEMP_RES res)
2
{  
3
    uint8_t cmd = READ_TEMPERATURE;
4
    struct
5
    {
6
      int8_t  HByte;
7
      uint8_t LByte;  
8
    } ByteArray;
9
    
10
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &cmd, 1, 10);
11
    HAL_I2C_Master_Receive (&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, (uint8_t *)&ByteArray, 2, 10);
12
            
13
    // ...
14
}

Ich finde den ersten Code aber lesbarer.

: Bearbeitet durch User
von mark (Gast)


Lesenswert?

Joe F. schrieb:
> mark schrieb:
>> aber ich denke, so müsste
>> es klappen.
>
> Könnte so klappen, ist aber unnötig kompliziert.
> Es spricht nichts dagegen die Größe der Buffer für den I2C Transfer
> größer zu machen, als sie für eine individuelle Transaktion benötigt
> wird.
> Evtl. gibt es noch andere I2C Slaves, und dann kann man die Buffer
> wiederverwenden.
>
> Vorschlag:uint8_t txDataBuf[10];
> uint8_t rxDataBuf[10];
>
> uint8_t readTemperature(TEMP_RES res)
> {
>     struct
>     {
>       int8_t  HByte;
>       uint8_t LByte;
>     } ByteArray;
>
>     txDataBuf[0] = READ_TEMPERATURE;
>
>     HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT,
> txDataBuf, 1, 10);
>     HAL_I2C_Master_Receive (&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT,
> rxDataBuf, 2, 10);
>
>     ByteArray.HByte = (int8_t)rxDataBuf[0]; // der explizite cast auf
> int8_t ist hier eigentlich überflüssig, da ByteArray.HByte schon als
> int8_t definiert ist, aber schaden kann es nicht
>     ByteArray.LByte = rxDataBuf[1];
>
>     // ...
> }
>
> Wofür ist eigentlich das Argument "TEMP_RES res" in dieser Funktion?
>
> Als Minimalist oder wenn einem das umkopieren der 3 Bytes zu
> zeitkritisch ist, kann man es auch so machen:uint8_t
> readTemperature(TEMP_RES res)
> {
>     uint8_t cmd = READ_TEMPERATURE;
>     struct
>     {
>       int8_t  HByte;
>       uint8_t LByte;
>     } ByteArray;
>
>     HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT,
> &cmd, 1, 10);
>     HAL_I2C_Master_Receive (&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT,
> (uint8_t *)&ByteArray, 2, 10);
>
>     // ...
> }
>
> Ich finde den ersten Code aber lesbarer.

Ok, vielen Dank. Ich habe jetzt noch nicht alle Optimierungen von dir 
drinnen, aber soweit sieht es mal so wie unten aus. Jedoch habe ich ein 
paar Fragen, wenn auch manche wieder einmal c-technisch sind.

Also, so wie ich das verstehe ist, dass der Wert rxDataBuf bei deiner 
ersten Version in der Receive-Fkt ein vom Typ uint8_t. Von daher muss 
der Cast meiner Meinung nach schon stattfinden, weil ja im struct HByte 
vom Typ int8_t ist. Oder??

Warum muss ich eigentlich, wenn ich anstatt dem struct-Namen oben, unten 
die Listenbezeichnung angebe, kein Speicher alloziieren indem ich struct 
Name Variable; schreibe?
Was ist der Vorteil so wie du es gemacht hast. Dass ich eben nicht extra 
eine Variable definieren muss?

Du castest ja den struct ByteArray, wenn du diesen direkt der 
Receive-Fkt. übergibst, zu einem Pointer.
Kann man einen struct eigentlich nicht als pointer definieren?
Oder geht das nur für dessen einzelnen Elemente?

TEMP_RES res ist die wählbare resolution der Temperatur.

Hier der Code: (Er ist soweit fertig, nach der Optimierung werde ich ihn 
öffentlich zugänglich machen). Dann gibt es für den DS1621 auch etwas in 
der STM32 Variante und nicht nur AVR. Ich habe mal versucht so viele 
Funktionen zusammenzufassen wie nur geht und den Code klein zu halten.
Wäre gut, wenn Profis noch drüber schauen könnten, bevor ihn alle 
anderen kopieren.

c-file
1
#include "TempSensorDriver.h" 
2
3
  
4
/****************************************************************************** 
5
 ** Constants, macros and type definitions                                   ** 
6
 ******************************************************************************/ 
7
  
8
/****************************************************************************** 
9
 ** Variables                                                                ** 
10
 ******************************************************************************/ 
11
  
12
extern I2C_HandleTypeDef hi2c1; 
13
  
14
/****************************************************************************** 
15
 ** Functions                                                                ** 
16
 ******************************************************************************/ 
17
18
/**
19
  * @brief  ReadCommand(uint8_t command) gets all desired values of the 
20
            TempSensor which should be read (only 1Byte values) 
21
  * @param  It uses the parameter command
22
            command could be ACCESS_TH, ACCESS_TL, ACCESS_CONFIG           
23
            READ_COUNTER or READ_SLOPE          
24
  */
25
26
uint8_t ReadCommand(uint8_t command) 
27
{ 
28
    uint8_t txData;                                                // sending dataarray for access_config command 
29
    static uint8_t rxData;                                         // receiving dataarray for access_config command 
30
                                                                   // static because of variable rxData validity only within the function
31
    txData = command; 
32
    
33
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10);    // Shift is necessary because of i2C function description 
34
    HAL_I2C_Master_Receive(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &rxData, sizeof(rxData), 10);     // Shift is necessary because of i2C function description 
35
    return rxData;
36
} 
37
38
/**
39
  * @brief  WriteCommand(uint8_t command) gets all desired values of the 
40
            TempSensor which should be read (only 1Byte values) 
41
  * @param  It uses the parameter command
42
            command could be ACCESS_TH, ACCESS_TL, ACCESS_CONFIG, START_CONVERT_T
43
            or STOP_CONVERT_T
44
  */
45
46
void WriteCommand(uint8_t command) 
47
{ 
48
    uint8_t txData = command;                                            // sending dataarray for access_config command 
49
    
50
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10);    // Shift is necessary because of i2C function description 
51
} 
52
  
53
/**
54
  * @brief  init_TempSensor(TEMP_CONV mode, POLARITY pol) intializes the TempSensor
55
  * @param  takes the Conversion Mode mode out of the enum Temperature_conversion
56
  *         and the polartiy out of enum OutputPolarity POLARITY
57
  *         mode could be CONTINUOUS_MODE or ONE_SHOT_MODE  
58
  *         pol could be ACTIVE_LOW, ACTIVE_HIGH or NONE if not used
59
  */
60
61
void init_TempSensor(TEMP_CONV mode, OUT_POL pol) 
62
{ 
63
    // variables
64
    uint8_t txData; 
65
    
66
    txData = ReadCommand(ACCESS_CONFIG); 
67
  
68
    txData &= ~(   1<<ONE_SHOT |   1<<POL);                      // delete bits generally 
69
    txData |=  (mode<<ONE_SHOT | pol<<POL);                      // set Bits according to mode and pol
70
    
71
    //_delay_ms(12);                                             // wait for at least 10ms - better 12ms for config process
72
    
73
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10); 
74
}
75
76
/**
77
  * @brief  readTemperature(TEMP_RES res) reads the converted temperature of the sensor
78
  * @param  takes temperature resolution res out of TempResolution TEMP_RES
79
  *         resolution res could be  HALF_DEGREE, FULL_DEGREE, HIGH_RESOLUTION  
80
  *         pol could be ACTIVE_LOW, ACTIVE_HIGH or NONE if not used
81
  */
82
83
double readTemperature(TEMP_RES res)
84
{  
85
    uint8_t txData = READ_TEMPERATURE;                           // sending dataarray for access_config command
86
    uint8_t rxData[2];
87
    static double Degrees;
88
89
    struct
90
    {
91
      int8_t HByte;
92
      uint8_t LByte;  
93
    }ByteArray;
94
     
95
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10);    // Shift is necessary because of i2C function description 
96
    HAL_I2C_Master_Receive(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, (uint8_t*)&ByteArray, sizeof(rxData), 10);     // Shift is necessary because of i2C function description 
97
     
98
    uint8_t slope = ReadCommand(READ_SLOPE);
99
    uint8_t counter = ReadCommand(READ_COUNTER);
100
    
101
    switch(res)
102
    {
103
     case 0:                                                          // HALFDEGREE mode
104
           if((ByteArray.LByte != 0) & (ByteArray.HByte < 0) )          
105
          {
106
            Degrees = ByteArray.HByte - 0.5;
107
          }else if((ByteArray.LByte != 0) & (ByteArray.HByte > 0) ) 
108
            {
109
              Degrees = ByteArray.HByte + 0.5;
110
            }else
111
              {
112
                Degrees = ByteArray.HByte + 0.0;
113
              }
114
     break;
115
            
116
     case 1:                                                          // ONEDEGREE mode      
117
          Degrees = ByteArray.HByte;
118
     break;
119
            
120
     case 2:                                                          // HIGHRESOLUTION mode
121
           Degrees = ByteArray.HByte-0.25+((slope-counter)/slope);
122
     break;
123
    }
124
125
    return Degrees;
126
}
127
128
/**
129
  * @brief  checks the bits in the config Register of the TempSensor 
130
  * @param  takes the configBit out of the config Register CONV_REG 
131
  *         configBit could be ONE_SHOT, POL, NVB, TLF, THF or DONE   
132
  */
133
134
bool checkConfigRegisterFlag(CONV_REG configBit) 
135
{ 
136
    return ((ReadCommand(ACCESS_CONFIG) & (1 << configBit)) != 0);
137
}

h-file
1
#ifndef TEMPSENSORDRIVER_H_ 
2
#define TEMPSENSORDRIVER_H_ 
3
  
4
#include "stm32l4xx_hal.h" 
5
#include "stdbool.h" 
6
  
7
/****************************************************************************** 
8
 ** Constants, macros and type definitions                                   ** 
9
 ******************************************************************************/ 
10
  
11
 /* Commands to the TempSensor - Read or Write*/ 
12
 #define TEMP_SENSOR_ADRESS_7_BIT                                          0x48 
13
  
14
 #define READ_TEMPERATURE                                                  0xAA 
15
 #define ACCESS_TH                                                         0xA1 
16
 #define ACCESS_TL                                                         0xA2 
17
 #define ACCESS_CONFIG                                                     0xAC 
18
 #define READ_COUNTER                                                      0xA8 
19
 #define READ_SLOPE                                                        0xA9 
20
 #define START_CONVERT_T                                                   0xEE 
21
 #define STOP_CONVERT_T                                                    0x22 
22
 /* End of Commands to the TempSensor - Read or Write*/ 
23
  
24
 #define SHIFT                                                             0x01 
25
 
26
27
 // enum definitions
28
 enum Temperature_conversion 
29
 { 
30
     CONTINUOUS_MODE, 
31
     ONE_SHOT_MODE 
32
 }; 
33
 
34
 enum OutputPolarity 
35
 { 
36
     ACTIVE_LOW, 
37
     ACTIVE_HIGH,
38
     NONE
39
 }; 
40
 
41
 enum ConfigRegister 
42
 { 
43
     ONE_SHOT, 
44
     POL,
45
     NVB = 4U,
46
     TLF,
47
     THF,
48
     DONE   
49
 }; 
50
 
51
  enum TempResolution 
52
 { 
53
     HALF_DEGREE, 
54
     FULL_DEGREE,
55
     HIGH_RESOLUTION
56
 }; 
57
 
58
 
59
 // typedefs
60
 typedef enum Temperature_conversion TEMP_CONV;
61
 typedef enum OutputPolarity OUT_POL; 
62
 typedef enum ConfigRegister CONV_REG; 
63
 typedef enum TempResolution TEMP_RES; 
64
  
65
/****************************************************************************** 
66
 ** Variables                                                                ** 
67
 ******************************************************************************/ 
68
 
69
/****************************************************************************** 
70
 ** Functions                                                                ** 
71
 ******************************************************************************/ 
72
  
73
uint8_t ReadCommand(uint8_t command); 
74
void WriteCommand(uint8_t command);
75
void init_TempSensor(TEMP_CONV mode, OUT_POL pol); 
76
double readTemperature(TEMP_RES res);
77
78
// proofing flag functions
79
bool checkConfigRegisterFlag(CONV_REG configBit);
80
81
82
83
#endif // TEMPSENSORDRIVER_H_

von mark (Gast)


Lesenswert?

die Fkt. von readTemperature ist noch ein wenig lang.
Die restlichen Optimierungen nehme ich morgen noch vor. Dann sollte es 
soweit passen.

von mark (Gast)


Lesenswert?

1
#include "TempSensorDriver.h" 
2
3
  
4
/****************************************************************************** 
5
 ** Constants, macros and type definitions                                   ** 
6
 ******************************************************************************/ 
7
  
8
/****************************************************************************** 
9
 ** Variables                                                                ** 
10
 ******************************************************************************/ 
11
  
12
extern I2C_HandleTypeDef hi2c1; 
13
  
14
/****************************************************************************** 
15
 ** Functions                                                                ** 
16
 ******************************************************************************/ 
17
18
/**
19
  * @brief  ReadCommand(uint8_t command) gets all desired values of the 
20
            TempSensor which should be read (only 1Byte values) 
21
  * @param  It uses the parameter command
22
            command could be ACCESS_TH, ACCESS_TL, ACCESS_CONFIG           
23
            READ_COUNTER or READ_SLOPE          
24
  */
25
26
uint8_t ReadCommand(uint8_t command) 
27
{ 
28
    uint8_t txData;                                                // sending dataarray for access_config command 
29
    static uint8_t rxData;                                         // receiving dataarray for access_config command 
30
                                                                   // static because of variable rxData validity only within the function
31
    txData = command; 
32
    
33
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10);    // Shift is necessary because of i2C function description 
34
    HAL_I2C_Master_Receive(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &rxData, sizeof(rxData), 10);     // Shift is necessary because of i2C function description 
35
    return rxData;
36
} 
37
38
/**
39
  * @brief  WriteCommand(uint8_t command) writes all desired values of the 
40
            TempSensor which should be read (only 1Byte values) 
41
  * @param  It uses the parameter command
42
            command could be ACCESS_TH, ACCESS_TL, ACCESS_CONFIG, START_CONVERT_T
43
            or STOP_CONVERT_T
44
  */
45
46
void WriteCommand(uint8_t command) 
47
{ 
48
    uint8_t txData = command;                                            // sending dataarray for access_config command 
49
    
50
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10);    // Shift is necessary because of i2C function description 
51
} 
52
  
53
/**
54
  * @brief  init_TempSensor(TEMP_CONV mode, POLARITY pol) intializes the TempSensor
55
  * @param  takes the Conversion Mode mode out of the enum Temperature_conversion
56
  *         and the polartiy out of enum OutputPolarity POLARITY
57
  *         mode could be CONTINUOUS_MODE or ONE_SHOT_MODE  
58
  *         pol could be ACTIVE_LOW, ACTIVE_HIGH or NONE if not used
59
  */
60
61
void init_TempSensor(TEMP_CONV mode, OUT_POL pol) 
62
{ 
63
    // variables
64
    uint8_t txData; 
65
    
66
    txData = ReadCommand(ACCESS_CONFIG); 
67
  
68
    txData &= ~(   1<<ONE_SHOT |   1<<POL);                      // delete bits generally 
69
    txData |=  (mode<<ONE_SHOT | pol<<POL);                      // set Bits according to mode and pol
70
    
71
    while(!checkConfigRegisterFlag(NVB));                        // wait until EEPROM is written
72
    
73
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10); 
74
}
75
76
/**
77
  * @brief  readTemperature(TEMP_RES res) reads the converted temperature of the sensor
78
  * @param  takes temperature resolution res out of TempResolution TEMP_RES
79
  *         resolution res could be  HALF_DEGREE, FULL_DEGREE, HIGH_RESOLUTION  
80
  */
81
82
double readTemperature(TEMP_RES res)
83
{  
84
    uint8_t txData = READ_TEMPERATURE;                           // sending dataarray for access_config command
85
    uint8_t rxData[2];
86
    static double Degrees;
87
88
    struct
89
    {
90
      int8_t HByte;
91
      uint8_t LByte;  
92
    }ByteArray;
93
     
94
    HAL_I2C_Master_Transmit(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, &txData, sizeof(txData), 10);    // Shift is necessary because of i2C function description 
95
    HAL_I2C_Master_Receive(&hi2c1, TEMP_SENSOR_ADRESS_7_BIT << SHIFT, (uint8_t*)&ByteArray, sizeof(rxData), 10);     // Shift is necessary because of i2C function description 
96
     
97
    uint8_t slope = ReadCommand(READ_SLOPE);
98
    uint8_t counter = ReadCommand(READ_COUNTER);
99
    
100
    switch(res)
101
    {
102
     case 0:                                                          // HALFDEGREE mode
103
           if((ByteArray.LByte != 0) & (ByteArray.HByte < 0) )          
104
          {
105
            Degrees = ByteArray.HByte - 0.5;
106
          }else if((ByteArray.LByte != 0) & (ByteArray.HByte > 0) ) 
107
            {
108
              Degrees = ByteArray.HByte + 0.5;
109
            }else
110
              {
111
                Degrees = ByteArray.HByte + 0.0;
112
              }
113
     break;
114
            
115
     case 1:                                                          // ONEDEGREE mode      
116
          Degrees = ByteArray.HByte;
117
     break;
118
            
119
     case 2:                                                          // HIGHRESOLUTION mode
120
           Degrees = ByteArray.HByte-0.25+((slope-counter)/slope);
121
     break;
122
    }
123
124
    return Degrees;
125
}
126
127
/**
128
  * @brief  checks the bits in the config Register of the TempSensor 
129
  * @param  takes the configBit out of the config Register CONV_REG 
130
  *         configBit could be ONE_SHOT, POL, NVB, TLF, THF or DONE   
131
  */
132
133
bool checkConfigRegisterFlag(CONV_REG configBit) 
134
{ 
135
    return ((ReadCommand(ACCESS_CONFIG) & (1 << configBit)) != 0);
136
}

von mark (Gast)


Lesenswert?

ohh mann ist schon später sorry, war zu schnell

ich habe noch die zeile mit dem delay von 12ms in der fkt.
init_TempSensor ersetzt durch das Prüfen des NVB flags..

so nun gute Nacht

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.