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


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? Это плохо сформулированный вопрос. Для дальнейших рекомендаций см. Electronics.stackexchange.com/help/how-to-ask
Пик напряжения

Тогда лучше написать новый вопрос или просто отредактировать этот?
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. Третий параметр ( uint8_t *pData) представляет собой указатель на буфер , который содержит данные , которые должны быть отправлено . Теперь в вашем вызове третий параметр - 0x0Cэто ваши фактические данные, адрес регистра. Проблема в том, что он будет интерпретироваться как указатель (на HAL_I2C_Master_Transmit()) на область памяти, где можно найти некоторые неопределенные данные.

  3. Четвёртый параметр является размером буфера , количество байт , которые должны быть отправлено. Если вы хотите отправить один байт, тогда этот параметр должен быть 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);

Разница лишь в том, что третий параметр является указателем на буфер, в котором будут храниться полученные данные . это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.