Ich bin sehr neu in der Verwendung der CUBE- und HAL_libraries von STM. Ich verwende einen STM32F0-Mikrocontroller mit 32 Pins. Der Schaltplan für I2C ist korrekt. Also brauche ich hier ein wenig Hilfe.
Ich habe einen kapazitiven Sensor ( FDC1004 ), der I2C-Kommunikation verwendet. Ich muss diese Register schreiben, um die Daten zu lesen.
Wie könnte ich die START-Anfrage vom Master korrekt an den Slave senden (Slave-Adresse ist A0)?
Wie setze ich den Zeiger auf das 0x0C-Register?
Aber ich weiß nicht, ob ich die richtigen Register anspreche! Denn ich bekomme keine Daten vom Sensor zurück!
Hier ist mein Code:
int I2Ccomm ()
{
HAL_I2C_Master_Transmit(&hi2c1,0xA1,0x0C, 10, 100); //start bit and pointer to register
HAL_Delay(50);
HAL_I2C_Master_Transmit(&hi2c1,0xA1,0x054, 10, 100); // setting the register
HAL_Delay(50);
HAL_I2C_Master_Receive(&hi2c1, 0xA0, 0x0C, 10, 100); //read from this register
HAL_Delay(50);
HAL_I2C_Master_Receive(&hi2c1, 0xA0, 0x02, 10, 100); //read data from register
return ReadREG[1];
}
Beginnen wir mit der HAL_I2C_Master_Transmit()
Funktion. Wenn Sie seine Deklaration überprüfen:
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
Kleineres Problem mit dem 2. Parameter, der Slave-Geräteadresse. Die Slave-Geräteadresse lautet, b1010000
wenn wir sie im 8-Bit-Format vervollständigen 0xA0
, genau wie Sie sagten. Wenn Sie dies nun an HAL_I2C_Master_Transmit()
Sie weitergeben, müssen Sie das R/W-Bit nicht manuell setzen, HAL erledigt dies für Sie. Wenn Sie also HAL_I2C_Master_Transmit()
das übertragene R/W-Bit aufrufen, ist es automatisch 0, was einen Schreibvorgang anzeigt, und wenn Sie das übertragen, HAL_I2C_Master_Receive()
ist das übertragene R/W-Bit automatisch 1, was einen Schreibvorgang anzeigt . Sie haben die R / W-Werte gemischt, aber ich denke, es handelt sich um ein irrelevantes Bit für die Funktion, sodass es sich nicht um einen tatsächlichen Fehler in Ihrem Code handelt.
Der 3. Parameter ( uint8_t *pData
) ist ein Zeiger auf einen Puffer , der die zu sendenden Daten enthält . Nun, in Ihrem Aufruf ist der 3. Parameter 0x0C
Ihre eigentlichen Daten, die Registeradresse. Das Problem ist, dass es als Zeiger (von HAL_I2C_Master_Transmit()
) auf einen Speicherort interpretiert wird, an dem einige undefinierte Daten zu finden sind.
Der 4. Parameter ist die Größe des Puffers , die Anzahl der zu sendenden Bytes. Wenn Sie ein einzelnes Byte senden möchten, sollte dieser Parameter 1 und nicht 10 sein.
Beim Arbeiten mit Am besten besorgen Sie sich das Datenblatt des Slave-Geräts und schlagen in der Dokumentation der Schreib- und Leseoperationen nach.
Hier ist das entsprechende Diagramm aus dem Datenblatt.
Nach dem Senden der Slave-Adresse an den Bus sollten also drei weitere Bytes übertragen werden: Registerzeiger , MSB-Byte , LSB-Byte . Eine allgemeine Implementierung mit HAL, die 16-Bit-Register schreibt:
void write_register(uint8_t register_pointer, uint16_t register_value)
{
uint8_t data[3];
data[0] = register_pointer; // 0x0C in your example
data[1] = register_value>>8; // MSB byte of 16bit data
data[2] = register_value; // LSB byte of 16bit data
HAL_I2C_Master_Transmit(&hi2c1, 0xA0, data, 3, 100); // data is the start pointer of our array
}
Beispiel mit deinen Werten:write_register(0x0C, 0x0054);
Alternativ kann auch eine HAL-definierte Registerschreibfunktion verwendet werden, die zusätzliche Parameter zum Übergeben von Registeradresse und Adressgröße hat.
void write_register(uint8_t register_pointer, uint16_t register_value)
{
HAL_StatusTypeDef status = HAL_OK;
status = HAL_I2C_Mem_Write(&hi2c1, 0xA0, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, (uint8_t*)(®ister_value), 2, 100);
/* Check the communication status */
if(status != HAL_OK)
{
// Error handling, for example re-initialization of the I2C peripheral
}
}
Jetzt ist die HAL_I2C_Master_Receive()
Funktion fast die gleiche wie die andere.
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
Der einzige Unterschied besteht darin, dass der 3. Parameter ein Zeiger auf den Puffer ist, in dem die empfangenen Daten gespeichert werden. Es ist 0x02
in Ihrem Code und ich weiß nicht, was Sie damit bezweckt haben, aber es wird als Zeiger interpretiert (leider auf einen zufälligen Speicherort).
Um ein Register zu lesen, muss es mit einem ausgewählt werden Schreibvorgang durch Senden des entsprechenden Registerzeigers (Beachten Sie, dass Sie, wenn Sie dieses Register direkt vor dem Lesen geschrieben haben, seine Adresse nicht erneut an das Zeigerregister senden müssen, da Sie sie bereits während des Schreibens festgelegt haben). Dann mit einem Lesevorgang, lesen Sie die 16-Bit-Daten zurück.
void read_register(uint8_t register_pointer, uint8_t* receive_buffer)
{
// first set the register pointer to the register wanted to be read
HAL_I2C_Master_Transmit(&hi2c1, 0xA0, ®ister_pointer, 1, 100); // note the & operator which gives us the address of the register_pointer variable
// receive the 2 x 8bit data into the receive buffer
HAL_I2C_Master_Receive(&hi2c1, 0xA0, receive_buffer, 2, 100);
}
Beispiel:
uint8_t reg_ptr = 0x0C;
uint8_t buffer[2];
read_register(reg_ptr, buffer);
// the register content available in the buffer
Es gibt auch eine HAL-definierte Register-Lesefunktion, die hat.
uint16_t read_register(uint8_t register_pointer)
{
HAL_StatusTypeDef status = HAL_OK;
uint16_t return_value = 0;
status = HAL_I2C_Mem_Read(&hi2c1, 0xA0, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, &return_value, 2, 100);
/* Check the communication status */
if(status != HAL_OK)
{
}
return return_value;
}
Lesen Sie Abschnitt 8.5 Programmierung des Datenblatts für weitere Einzelheiten.
Spannungsspitze
ja111
Spannungsspitze