让我们从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);
第二个参数的小问题,从设备地址。从设备地址是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 值,但我认为这对函数来说是一个无关紧要的位,因此它不是您的代码中的实际错误。
第三个参数 ( uint8_t *pData
) 是指向包含要发送的数据的缓冲区的指针。现在,在您的调用中,第三个参数是0x0C
您的实际数据,即寄存器地址。问题是,它将被解释为指向HAL_I2C_Master_Transmit()
内存位置的指针(由 ),可以在其中找到一些未定义的数据。
第4 个参数是缓冲区的大小,要发送的字节数。如果要发送单个字节,则此参数应为1而不是 10。
使用\$ \small I^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*)(®ister_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
在您的代码中,我不知道您使用它的目的是什么,但它将被解释为一个指针(不幸的是指向一个随机内存位置)。
读取寄存器
要读取一个寄存器,必须使用\$ \small I^2C \$写入操作通过发送适当的寄存器指针来选择它(请注意,如果您在读取之前写入了该寄存器,那么您不必再次发送它的指向指针寄存器的地址,因为您已经在写入期间设置了它)。然后用\$ \small I^2C \$读操作,读回 16 位数据。
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);
}
例子:
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 编程部分了解更多详细信息。