使用I2C STM32F0 HAL库寻址寄存器


12

我对使用STM的CUBE和HAL_libraries非常陌生。我正在使用具有32个引脚的STM32F0微控制器。I2C的原理图是正确的。所以在这里我需要一点帮助。

我有一个使用I2C通信的电容传感器(FDC1004)。我必须写这些寄存器才能读取数据。

我该如何正确地将START请求表的主机发送给从机(从机地址为A0)?

如何设置指向0x0C寄存器的指针?

  • 数据表中看到(寄存器0x0C:bit [7:4])为1。)我不知道,该怎么做?最后如何从同一寄存器读取?
  • 另外,在阅读之前,我必须等待DONE_x字段(寄存器0x0C:bits [3:0])吗?

但是我不知道我是否在寻找正确的寄存器!因为我没有从传感器获得任何数据!

这是我的代码:

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

请提出更具体的问题。像我如何正确地注册X?这是一个措辞不好的问题。有关更多准则,请参阅electronics.stackexchange.com/help/how-to-ask
电压峰值

那么,写一个新问题还是只编辑一个更好呢?
yest111 '16

最好进行编辑,减少问题,而我们不必关闭此问题。
电压峰值

Answers:


16

让我们从HAL_I2C_Master_Transmit()函数开始。如果检查其声明:

 HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  1. 第2个参数(从站地址)存在小问题。如您所说,从设备地址是b1010000如果我们将其完成为8位格式,则为0xA0。现在,将其传递给HAL_I2C_Master_Transmit()您时,不必手动设置R / W位,HAL会为您完成。因此,当您调用HAL_I2C_Master_Transmit()发送的R / W位将自动为0表示写操作,而当您调用HAL_I2C_Master_Receive()发送的R / W位将自动为1表示写操作。您已经混合了R / W值,但是我认为这对于函数来说并不重要,因此它不是代码中的实际错误。

  2. 第三参数(uint8_t *pData)是一个指向缓冲区的指针,其包含要被发送的数据。现在,在您的调用中,第三个参数0x0C是您的实际数据,即寄存器地址。问题是,它将被解释为指向HAL_I2C_Master_Transmit()存储位置的指针(由),在该位置可以找到一些未定义的数据。

  3. 所述第四参数是所述缓冲器的大小,要发送的字节数。如果要发送单个字节,则此参数应为1而不是10。

当使用,最好的办法是获取从设备的数据表并查找写入和读取操作的文档。一世2C

写寄存器

这是数据表中的对应图。

在此处输入图片说明

因此,在将从机地址发送到总线之后,应再发送三个字节:寄存器指针MSB字节LSB字节。HAL写入16位寄存器的一般实现:

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
}

您的值的示例: write_register(0x0C, 0x0054);

另外,也可以使用HAL定义的寄存器写功能,它具有用于传递寄存器地址和地址大小的附加参数。

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

现在,该HAL_I2C_Master_Receive()功能与其他功能几乎相同。

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

唯一的区别是第三个参数是指向将存储接收到的数据的缓冲区的指针。它0x02在您的代码中,我不知道您的用途是什么,但是它将被解释为指针(不幸的是指向随机内存位置)。

读取寄存器

在此处输入图片说明

要读取寄存器,必须使用写操作通过发送适当的寄存器指针来对其进行选择(请注意,如果您在读取之前就已写入该寄存器,则不必再次将其地址发送给指针注册,因为您已经在写入过程中进行了设置)。然后通过读取操作,回读16位数据。一世2C一世2C

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

例:

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

read_register(reg_ptr, buffer);

// the register content available in the buffer

还具有HAL定义的寄存器读取功能。

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

请通读数据手册的8.5编程部分以获取更多详细信息。


谢谢您的回答,现在终于可以使用了。但是还有一个问题?我是否需要等待几毫秒的阅读时间,还是可以立即阅读?
yest111 '16

我认为不需要任何延迟,您可以先尝试一下。
Bence Kaulics '16

1
您无需等待,I2C涉及循环时钟信号,直到从机完成。
Mahmoud Al-Qudsi'7
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.