Cominciamo con la HAL_I2C_Master_Transmit()
funzione. Se controlli la sua dichiarazione:
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
Problema minore con il 2o parametro, l'indirizzo del dispositivo slave. L'indirizzo del dispositivo slave è b1010000
se lo completiamo nel formato 8 bit, sarà 0xA0
, proprio come hai detto. Ora quando passi questo HAL_I2C_Master_Transmit()
non devi impostare manualmente il bit R / W, HAL lo farà per te. Quindi quando si chiama HAL_I2C_Master_Transmit()
il bit R / W trasmesso sarà automaticamente 0 che indica l'operazione di scrittura e quando si chiama HAL_I2C_Master_Receive()
il bit R / W trasmesso sarà automaticamente 1 che indica l'operazione di scrittura . Hai mescolato i valori R / W ma penso che non sia un problema per la funzione, quindi non è un errore reale nel tuo codice.
Il 3o parametro ( uint8_t *pData
) è un puntatore a un buffer che contiene i dati da inviare . Ora, nella tua chiamata, il terzo parametro è 0x0C
quali sono i tuoi dati effettivi, l'indirizzo del registro. Il problema è che verrà interpretato come un puntatore (da HAL_I2C_Master_Transmit()
) a una posizione di memoria, in cui è possibile trovare alcuni dati non definiti.
Il 4o parametro è la dimensione del buffer , il numero di byte da inviare. Se si desidera inviare un singolo byte, questo parametro dovrebbe essere 1 e non 10.
io2C la cosa migliore da fare è ottenere il foglio dati del dispositivo slave e cercare la documentazione delle operazioni di scrittura e lettura.
Scrivi registri
Ecco il diagramma corrispondente dal foglio dati.
Quindi, dopo aver inviato l'indirizzo slave al bus, dovrebbero essere trasmessi altri tre byte: puntatore di registro , byte MSB , byte LSB . Un'implementazione generale con HAL che scrive registri a 16 bit:
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
}
Esempio con i tuoi valori: write_register(0x0C, 0x0054);
In alternativa è possibile utilizzare anche la funzione di scrittura del registro definita HAL, che ha parametri aggiuntivi per il passaggio dell'indirizzo del registro e la dimensione dell'indirizzo.
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
}
}
Ora, la HAL_I2C_Master_Receive()
funzione è quasi uguale all'altra.
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
L'unica differenza è che il terzo parametro è un puntatore al buffer in cui verranno archiviati i dati ricevuti . È0x02
nel tuo codice e non so quale fosse il tuo scopo, ma verrà interpretato come un puntatore (purtroppo a una posizione di memoria casuale).
Leggi i registri
Per leggere un registro, è necessario selezionarlo con un io2Coperazione di scrittura inviando il puntatore del registro appropriato (si noti che se si è scritto questo registro prima della lettura, non è necessario inviare nuovamente il relativo indirizzo al registro del puntatore, poiché è già stato impostato durante la scrittura). Quindi con unio2C operazione di lettura, rilettura dei dati a 16 bit.
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);
}
Esempio:
uint8_t reg_ptr = 0x0C;
uint8_t buffer[2];
read_register(reg_ptr, buffer);
// the register content available in the buffer
C'è anche una funzione di lettura del registro definita HAL, che ha.
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;
}
Leggi la sezione 8.5 Programmazione della scheda tecnica per maggiori dettagli.