Beginnen wir mit der HAL_I2C_Master_Transmit()
Funktion. Wenn Sie die Erklärung überprüfen:
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
Kleines Problem mit dem 2. Parameter, der Slave-Geräteadresse. Die Adresse des Slave-Geräts lautet, b1010000
wenn wir sie im 8-Bit-Format vervollständigen 0xA0
, genau so, wie Sie es gesagt haben. Wenn HAL_I2C_Master_Transmit()
Sie dies jetzt an Sie übergeben, 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 dies automatisch 0, was eine Schreiboperation anzeigt, und wenn Sie HAL_I2C_Master_Receive()
das übertragene R / W-Bit aufrufen, ist es automatisch 1, was eine Schreiboperation anzeigt . Sie haben die R / W-Werte gemischt, aber ich denke, die Funktion ist mir egal, es handelt sich also nicht um einen tatsächlichen Fehler in Ihrem Code.
Der 3. Parameter ( uint8_t *pData
) ist ein Zeiger auf einen Puffer, der die zu sendenden Daten enthält . In Ihrem Aufruf ist der dritte Parameter, 0x0C
der Ihre tatsächlichen Daten sind, die Registeradresse. Das Problem ist, dass es als Zeiger (von der HAL_I2C_Master_Transmit()
) auf einen Speicherort interpretiert wird , an dem einige undefinierte Daten gefunden werden können.
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.
Wenn Sie mit am besten, das Datenblatt des Slave-Geräts abzurufen und die Dokumentation der Schreib- und Lesevorgänge nachzuschlagen.I2C
Register schreiben
Hier ist das entsprechende Diagramm aus dem Datenblatt.
Nach dem Senden der Slave-Adresse an den Bus sollten drei weitere Bytes übertragen werden: Registerzeiger , MSB-Byte , LSB-Byte . Eine allgemeine Implementierung mit HAL-16-Bit-Registern:
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 Ihren Werten: write_register(0x0C, 0x0054);
Alternativ kann auch eine HAL-definierte Registerschreibfunktion verwendet werden, die zusätzliche Parameter zum Übergeben der Registeradresse und der Adressgröße enthält.
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 dieselbe 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 befindet sich 0x02
in Ihrem Code und ich weiß nicht, was Ihr Zweck damit war, aber es wird als Zeiger interpretiert (leider auf einen zufälligen Speicherort).
Register lesen
Um ein Register zu lesen, muss es mit einer Schreiboperation durch Senden des entsprechenden Registerzeigers ausgewählt werden (Beachten Sie, dass Sie, wenn Sie dieses Register direkt vor dem Lesen geschrieben haben, seine Adresse nicht erneut an den Zeiger senden müssen registrieren, wie Sie es bereits beim Schreiben eingestellt haben). Lesen Sie dann mit einer Leseoperation die 16-Bit-Daten zurück.I2CI2C
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 Registerlesefunktion, 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 durch 8.5 Programmierung Abschnitt des Datenblatt für weitere Details.