Indirizzamento dei registri con le librerie HAL I2C STM32F0


12

Sono molto nuovo nell'uso di STM CUBE e HAL_libraries. Sto usando un microcontrollore STM32F0 a 32 pin. Lo schema per I2C è corretto. Quindi ho bisogno di un piccolo aiuto qui.

Ho un sensore capacitivo ( FDC1004 ) che utilizza la comunicazione I2C. Devo scrivere questi registri per leggere i dati.

Come posso inviare correttamente il modulo di richiesta START al master (l'indirizzo slave è A0)?

Come impostare il puntatore sul registro 0x0C?

  • Il foglio dati vede (Registro 0x0C: bit [7: 4]) a 1.) Non lo so, come si fa? E infine come LEGGERE dallo stesso registro?
  • Inoltre devo attendere il campo DONE_x (registro 0x0C: bit [3: 0]) prima di leggerlo?

Ma non so se mi rivolgo ai registri giusti! Perché non ricevo alcun dato dal sensore!

Ecco il mio codice:

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];
}

Si prega di porre una o più domande specifiche. Mi piace Come posso indirizzare correttamente il registro X? Questa è una domanda formulata male. Per ulteriori linee guida consultare electronics.stackexchange.com/help/how-to-ask
Voltage Spike

Quindi è meglio scrivere una nuova domanda o semplicemente modificarla?
yest111

Meglio modificare, meno domande e non dovremo chiudere questa.
Voltage Spike,

Risposte:


16

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);
  1. Problema minore con il 2o parametro, l'indirizzo del dispositivo slave. L'indirizzo del dispositivo slave è b1010000se 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.

  2. Il 3o parametro ( uint8_t *pData) è un puntatore a un buffer che contiene i dati da inviare . Ora, nella tua chiamata, il terzo parametro è 0x0Cquali 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.

  3. 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.

inserisci qui la descrizione dell'immagine

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*)(&register_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

inserisci qui la descrizione dell'immagine

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, &register_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.


Grazie per la tua risposta, ora finalmente funziona. Ma un'altra domanda? Devo aspettare qualche secondo per leggere o posso leggere senza indugio?
yest111

Non penso che sia necessario alcun ritardo, potresti provare senza prima.
Bence Kaulics,

1
Non è necessario attendere, I2C comporta il looping del segnale di clock fino al completamento dello slave.
Mahmoud Al-Qudsi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.