Адресація регістрів з бібліотеками I2C STM32F0 HAL


12

Я дуже новачок у використанні STM CUBE та HAL_libraries. Я використовую мікроконтролер STM32F0 з 32 контактами. Схематична схема для I2C правильна. Тому мені тут потрібна невелика допомога.

У мене ємнісний датчик ( FDC1004 ), який використовує зв'язок I2C. Я повинен записати ці регістри, щоб прочитати дані.

Як я можу правильно надіслати запит на запит START для ведомого (адреса підлеглого - A0)?

Як встановити покажчик на реєстрацію 0x0C?

  • Таблиця даних бачить (Зареєструйте 0x0C: біт [7: 4]) до 1.) Я не знаю, як це зробити? І нарешті, як ЧИТАТИ з того самого реєстру?
  • Плюс я повинен зачекати поле DONE_x (зареєструвати 0x0C: біти [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? Це погано сформульоване питання. Детальніші вказівки див. У електроніці.stackexchange.com/
Спайк напруги

Тоді краще написати нове запитання чи просто відредагувати це?
yest111

Краще редагувати, менше питань, і нам не доведеться закривати це.
Спайк напруги

Відповіді:


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. Незначна проблема с другим параметром, адресою підлеглого пристрою. Адреса підлеглого пристрою - 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. The Третій параметр ( uint8_t *pData) являє собою покажчик на буфер , який містить дані , які повинні бути відправлено . Тепер у вашому дзвінку 3-й параметр - 0x0Cце ваші фактичні дані, адреса регістра. Проблема в тому, що вона буде інтерпретуватися як вказівник (від HAL_I2C_Master_Transmit()) на місце пам'яті, де можна знайти деякі невизначені дані.

  3. 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*)(&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);

Різниця лише в тому, що 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, &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

Я не вважаю, що будь-яка затримка не потрібна, ви можете спробувати без першого.
Бенс Каулікс

1
Вам не потрібно чекати, I2C передбачає циклічний сигнал на тактовому сигналі, поки підлеглий не завершиться.
Махмуд Аль-Кудсі
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.