Почнемо з 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, але я думаю, що це не важливий біт для функції, тому це не є фактичною помилкою у вашому коді.
The Третій параметр ( uint8_t *pData
) являє собою покажчик на буфер , який містить дані , які повинні бути відправлено . Тепер у вашому дзвінку 3-й параметр - 0x0C
це ваші фактичні дані, адреса регістра. Проблема в тому, що вона буде інтерпретуватися як вказівник (від HAL_I2C_Master_Transmit()
) на місце пам'яті, де можна знайти деякі невизначені дані.
The Четвертий параметр є розміром буфера , кількість байт , які повинні бути відправлено. Якщо ви хочете надіслати один байт, то цей параметр повинен бути 1, а не 10.
Під час роботи з Я2С
Пишіть регістри
Ось відповідна діаграма з таблиці.
Тож після відправлення ведомої адреси в шину слід передати ще три байти: регістр покажчика , MSB байт , LSB байт . Загальна реалізація 16-бітових регістрів HAL:
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);
Різниця лише в тому, що 3-й параметр - це вказівник на буфер, де будуть зберігатися отримані дані . Він знаходиться 0x02
у вашому коді, і я не знаю, що було з вами метою, але він буде інтерпретуватися як вказівник (на жаль, на місце випадкової пам'яті).
Читати регістри
Я2СЯ2С
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 Програмування частини таблиці для більш докладної інформації.