Direccionamiento de registros con bibliotecas I2C STM32F0 HAL


12

Soy muy nuevo en el uso de CUBE y HAL_libraries de STM. Estoy usando un microcontrolador STM32F0 con 32 pines. El esquema para I2C es correcto. Entonces necesito un poco de ayuda aquí.

Tengo un sensor capacitivo ( FDC1004 ) que utiliza la comunicación I2C. Tengo que escribir estos registros para leer los datos.

¿Cómo podría enviar correctamente el formulario de solicitud de INICIO maestro al esclavo (la dirección del esclavo es A0)?

¿Cómo configurar el puntero al registro 0x0C?

  • La hoja de datos ve (Registro 0x0C: bit [7: 4]) a 1.) No sé, ¿cómo hacer eso? ¿Y finalmente cómo LEER desde el mismo registro?
  • Además, ¿tengo que esperar el campo DONE_x (Registro 0x0C: bits [3: 0]) antes de leerlo?

¡Pero no sé si me dirijo a los registros correctos! ¡Porque no recibo ningún dato del sensor!

Aquí está mi 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];
}

Por favor haga una pregunta más específica. como ¿Cómo me dirijo al registro X correctamente? Esta es una pregunta mal formulada. Para obtener más pautas, visite electronics.stackexchange.com/help/how-to-ask
Voltage Spike el

Entonces, ¿es mejor escribir una nueva pregunta o simplemente editar esta?
yest111

Es mejor editar, menos preguntas y no tendremos que cerrar esta.
Voltaje pico

Respuestas:


16

Comencemos con la HAL_I2C_Master_Transmit()función. Si revisas su declaración:

 HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  1. Problema menor con el segundo parámetro, la dirección del dispositivo esclavo. La dirección del dispositivo esclavo es b1010000si la completamos en formato de 8 bits, será 0xA0, tal como usted dijo. Ahora, al pasarle esto HAL_I2C_Master_Transmit(), no tiene que configurar el bit R / W manualmente, HAL lo hará por usted. Entonces, cuando llame HAL_I2C_Master_Transmit()al bit R / W transmitido, será automáticamente 0 lo que indica la operación de escritura y cuando llame HAL_I2C_Master_Receive()al bit R / W transmitido será automáticamente 1 lo que indica la operación de escritura . Ha mezclado los valores R / W, pero creo que es un poco no importa la función, por lo que no es un error real en su código.

  2. El tercer parámetro ( uint8_t *pData) es un puntero a un búfer que contiene los datos que se enviarán . Ahora, en su llamada, el tercer parámetro es 0x0Ccuál es su información real, la dirección de registro. El problema es que se interpretará como un puntero (por el HAL_I2C_Master_Transmit()) a una ubicación de memoria, donde se pueden encontrar algunos datos indefinidos.

  3. El cuarto parámetro es el tamaño del búfer , el número de bytes que se enviarán. Si desea enviar un solo byte, este parámetro debe ser 1 y no 10.

yo2C

Escribir registros

Aquí está el diagrama correspondiente de la hoja de datos.

ingrese la descripción de la imagen aquí

Entonces, después de enviar la dirección del esclavo al bus, se deben transmitir tres bytes más: puntero de registro , byte MSB , byte LSB . Una implementación general con HAL escribiendo registros 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
}

Ejemplo con tus valores: write_register(0x0C, 0x0054);

Alternativamente, también se puede utilizar la función de escritura de registro definida por HAL, que tiene parámetros adicionales para pasar la dirección de registro y el tamaño de la dirección.

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

Ahora, la HAL_I2C_Master_Receive()función es casi la misma que la otra.

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

La única diferencia es que el tercer parámetro es un puntero al búfer donde se almacenarán los datos recibidos . Está 0x02en su código y no sé cuál fue su propósito con él, pero se interpretará como un puntero (desafortunadamente a una ubicación de memoria aleatoria).

Leer registros

ingrese la descripción de la imagen aquí

yo2Cyo2C

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

Ejemplo:

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

read_register(reg_ptr, buffer);

// the register content available in the buffer

También hay una función de lectura de registro definida por HAL, que tiene.

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

Lea la sección 8.5 Programación de la hoja de datos para obtener más detalles.


Gracias por su respuesta, ahora finalmente está funcionando. ¿Pero una pregunta más? ¿Tengo que esperar algunos milisegundos para leer o podría leer sin demora?
yest111

No creo que sea necesaria ninguna demora, podrías intentarlo sin ninguna.
Bence Kaulics

1
No necesita esperar, I2C implica un bucle en la señal del reloj hasta que el esclavo se haya completado.
Mahmoud Al-Qudsi
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.