Hãy bắt đầu với HAL_I2C_Master_Transmit()
chức năng. Nếu bạn kiểm tra khai báo của nó:
HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
Vấn đề nhỏ với tham số thứ 2 , địa chỉ thiết bị nô lệ. Địa chỉ thiết bị nô lệ là b1010000
nếu chúng tôi hoàn thành định dạng 8 bit, nó sẽ 0xA0
giống như bạn đã nói. Bây giờ khi chuyển cái này cho HAL_I2C_Master_Transmit()
bạn không phải thiết lập bit R / W theo cách thủ công, HAL sẽ làm điều đó cho bạn. Vì vậy, khi bạn gọi HAL_I2C_Master_Transmit()
bit R / W được truyền sẽ tự động 0 chỉ báo hoạt động ghi và khi bạn gọi HAL_I2C_Master_Receive()
bit R / W được truyền sẽ tự động 1 chỉ báo hoạt động ghi . Bạn đã trộn các giá trị R / W nhưng tôi nghĩ rằng đó là một chút không quan tâm đến hàm, vì vậy nó không phải là một lỗi thực tế trong mã của bạn.
Các thứ 3 tham số ( uint8_t *pData
) là một con trỏ đến một bộ đệm chứa dữ liệu được gửi . Bây giờ, trong cuộc gọi của bạn, tham số thứ 3 là 0x0C
dữ liệu thực tế của bạn, địa chỉ đăng ký. Vấn đề là, nó sẽ được hiểu là một con trỏ (theo HAL_I2C_Master_Transmit()
) đến một vị trí bộ nhớ, nơi có thể tìm thấy một số dữ liệu không xác định.
Các thứ 4 tham số là kích thước của bộ đệm , số byte được gửi đi. Nếu bạn muốn gửi một byte đơn thì tham số này phải là 1 chứ không phải 10.
I2C
Viết sổ đăng ký
Đây là sơ đồ tương ứng từ biểu dữ liệu.
Vì vậy, sau khi gửi địa chỉ nô lệ đến bus, cần truyền thêm ba byte: con trỏ thanh ghi , byte MSB , byte LSB . Một triển khai chung với HAL viết các thanh ghi 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
}
Ví dụ với các giá trị của bạn: write_register(0x0C, 0x0054);
Ngoài ra, chức năng ghi thanh ghi được xác định HAL cũng có thể được sử dụng, có các tham số bổ sung để truyền địa chỉ thanh ghi và kích thước địa chỉ.
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
}
}
Bây giờ, HAL_I2C_Master_Receive()
chức năng gần giống như khác.
HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
Chỉ khác là tham số thứ 3 là một con trỏ tới bộ đệm nơi dữ liệu nhận được sẽ được lưu trữ. Nó nằm 0x02
trong mã của bạn và tôi không biết mục đích của bạn với nó là gì, nhưng nó sẽ được hiểu là một con trỏ (không may là một vị trí bộ nhớ ngẫu nhiên).
Đọc sổ đăng ký
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, ®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);
}
Thí dụ:
uint8_t reg_ptr = 0x0C;
uint8_t buffer[2];
read_register(reg_ptr, buffer);
// the register content available in the buffer
Ngoài ra còn có một chức năng đọc thanh ghi được xác định HAL là tốt, trong đó có.
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;
}
Đọc qua phần Lập trình 8,5 của biểu dữ liệu để biết thêm chi tiết.