Registrando endereços com as bibliotecas I2C STM32F0 HAL

12

Sou muito novo em usar as bibliotecas CUBE e HAL do STM. Estou usando um microcontrolador STM32F0 com 32 pinos. O esquema do I2C está correto. Então, preciso de uma ajudinha aqui.

Eu tenho um sensor capacitivo ( FDC1004 ) que usa comunicação I2C. Eu tenho que escrever esses registros para ler os dados.

Como enviar corretamente o mestre do formulário de solicitação START para o escravo (o endereço do escravo é A0)?

Como definir o ponteiro para o registro 0x0C?

  • A folha de dados vê (Registre-se 0x0C: bit [7: 4]) para 1.) Não sei, como fazer isso? E, finalmente, como ler a partir do mesmo registro?
  • Além disso, tenho que esperar o campo DONE_x (registre 0x0C: bits [3: 0]) antes de ler?

Mas não sei se estou abordando os registros corretos! Porque não recebo dados do sensor!

Aqui está o meu código:

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];
}
yest111
fonte
Faça perguntas mais específicas. Como faço para endereçar o registro X corretamente? Esta é uma pergunta mal formulada. Para mais diretrizes ver electronics.stackexchange.com/help/how-to-ask
Tensão Pico
Então é melhor escrever uma nova pergunta ou apenas editar esta?
precisa saber é o seguinte
Melhor editar, menos perguntas e não precisaremos fechar esta.
Voltage Spike

Respostas:

16

Vamos começar com a HAL_I2C_Master_Transmit()função Se você verificar sua declaração:

 HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  1. Problema menor com o parâmetro, o endereço do dispositivo escravo. O endereço do dispositivo escravo é b1010000que, se o completarmos no formato 8 bits, será 0xA0, exatamente como você disse. Agora, ao passar isso para HAL_I2C_Master_Transmit()você, você não precisa definir o bit R / W manualmente, o HAL fará isso por você. Portanto, quando você chamar HAL_I2C_Master_Transmit()o bit R / W transmitido, será automaticamente 0 indicando a operação de gravação e quando você chamar HAL_I2C_Master_Receive()o bit R / W transmitido será automaticamente 1, indicando a operação de gravação . Você misturou os valores de R / W, mas acho que não é um problema para a função, portanto, não é um erro real no seu código.

  2. O terceiro parâmetro ( uint8_t *pData) é um ponteiro para um buffer que contém os dados a serem enviados . Agora, na sua chamada, o terceiro parâmetro é 0x0Cquais são seus dados reais, o endereço de registro. O problema é que ele será interpretado como um ponteiro (pelo HAL_I2C_Master_Transmit()) para um local de memória, onde alguns dados indefinidos podem ser encontrados.

  3. O quarto parâmetro é o tamanho do buffer , o número de bytes a serem enviados. Se você deseja enviar um único byte, esse parâmetro deve ser 1 e não 10.

I2C

Gravar registros

Aqui está o diagrama correspondente da folha de dados.

insira a descrição da imagem aqui

Então, depois de enviar o endereço escravo para o barramento, mais três bytes devem ser transmitidos: ponteiro de registro , byte MSB , byte LSB . Uma implementação geral com registros HAL de gravação de 16 bits:

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
}

Exemplo com seus valores: write_register(0x0C, 0x0054);

Como alternativa, também pode ser usada a função de gravação de registro definida pelo HAL, que possui parâmetros adicionais para a passagem do endereço e tamanho do endereço.

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

Agora, a HAL_I2C_Master_Receive()função é quase a mesma que a outra.

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

A única diferença é que o terceiro parâmetro é um ponteiro para o buffer em que os dados recebidos serão armazenados. Ele está 0x02no seu código e não sei qual era o seu objetivo, mas será interpretado como um ponteiro (infelizmente para um local de memória aleatória).

Ler registros

insira a descrição da imagem aqui

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, &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);   
}

Exemplo:

uint8_t reg_ptr = 0x0C;
uint8_t buffer[2];

read_register(reg_ptr, buffer);

// the register content available in the buffer

Também existe uma função de leitura de registro definida pelo HAL, que possui.

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

Leia a seção 8.5 Programação da folha de dados para obter mais detalhes.

Bence Kaulics
fonte
Obrigado por sua resposta, agora está finalmente funcionando. Mas mais uma pergunta? Preciso esperar alguns milissegundos para ler ou posso ler sem demora?
yest111
Eu não acho que qualquer atraso seja necessário, você pode tentar sem antes.
Bence Kaulics
1
Você não precisa esperar, o I2C envolve um loop no sinal do relógio até que o escravo seja concluído.
Mahmoud Al-Qudsi