Перейти к содержанию
    

I2C, HAL. Как считать данные из slave-устройства?

Всем привет!

Столкнулся с акселерометром FXOS8700. Управляется по I2C. Адрес устройства 0х1E. Контроллер STM32L476.

Проблема с чтением регистра WHOAMI. (ID устройства). Точнее, в целом проблема чтения данных с устройства. Набросал функцию.

В качестве аргумента передаю адрес регистра который намерен считать.

uint8_t FXOS8700_ReadByte (uint8_t ui8reg)
{
    uint8_t ui8byteFromReg;
    HAL_I2C_Master_Transmit (&hi2c3, (0x1E<<1), &ui8reg, 1, 200);
    HAL_I2C_Master_Receive (&hi2c3, ((0x1E<<1)|0x01), &ui8byteFromReg,1, 200);
    return ui8byteFromReg;
}

 

Как я понял (до этого делов с I2C не имел), для чтения должны придерживаться диаграммы single byte read.

вот вырезка из доки.

1cvqiqbusk.PNG

Вот тут непонятки. Адрес имеет длину 7 бит. Я так понял, просто так мы его передать не можем? Надо его сдвинуть влево на бит и тогда подсунуть в функцию HAL_I2C_Master_Transmit . Сначала мы передаем устройству адрес+W, получаем от устройсва AK, затем передаем адрес регистра который будем читать (в нашем случае это 0х0D). После этого опять ожидаем AK. За эту часть отвечает HAL_I2C_Master_Transmit.

Затем, (не понял как сгенерить SR) отсылаем адрес + R И после этого ожидаем AK и содержимое регистра 0х0D устройства. Но вот что-то на этом этапе линия данных ложится в нуль, хотя ID != 0. Вот сфотал (по другому не получается) экран с данным от лог. анализатора. При таком подходе, в конце работы ф-ции transmit передается STOP.

Работа функции transmit

1cvqrnsppd.PNG

Receive

1cvqrnexka.PNG

Правильно ли я понял принцип обмена данными с устройством, которое сидит на I2C шине и в чем ошибка?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

адрес устройства 0x1E нельзя изменять вот тут

 

HAL_I2C_Master_Receive (&hi2c3, ((0x1E<<1)|0x01), &ui8byteFromReg,1, 200);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

адрес устройства 0x1E нельзя изменять вот тут

 

HAL_I2C_Master_Receive (&hi2c3, ((0x1E<<1)|0x01), &ui8byteFromReg,1, 200);

Может да, а может и нет.

Изменение адреса мудро заключено в скобки, поэтому

если вызов - функция, то все правильно.

если макрос - то в нем (макросе) не должно быть операциий ## для этого аргумента.

Если их нет - то тоже должно работать.

-------

 

Вообще, TS надо посмотреть док. и примеры использования вызовов HAL_xxxx()

 

1. Вызов HAL_I2C_Master_Receive - подразумевает прием, и соовт-но нет необходимости

указывать бит чтения в адресе.

2. Возможно в этом HAL адрес надо задавать в "чистом" виде, без сдвига и прилепливания к нему

бита R/~W (читаем док или смотрим исходник HJL_xxxx). Это самое простое, проверьте.

3. Если HAL написан правильно и правильными писателями, то вызов должен возвращать

код результата выполнения операции (тк. I2C не так "прямолинеен" как SPI, где "мастер всегда прав")

4. Для "неразовой" работы с I2C (и другими интерфейсами) необходим лог. анализатор стоимостью 20-25 кваксов.

А для начинающего в этой части - так темболее :)

5. Ваш код, приведенный выше, думаю правильный. Тк вызовы HAL похожи на "все включено", где старты-сторпы-рестарты-ACK-NACK

уже сделаны. Но. Чтоб ОНО работало, еще должен быть настроен правильно аппаратный узел I2C, в том числе прерывания.

Работает ли он - проверяется тыканием осцилографа на SDA-SCL, а заодно проверяется формирование первого байта посылки

(установка адреса слейва) и ответа слейва в случае распознавания им своего ардеса нулевым ACK на 9-ом такте SCL.

 

PS - наткнулся. ЭТО LA (лог.анализатор) - за менее чем 10 кваксов.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для того чтобы сгенерить повторный "старт" можно использовать функции:

 

 

HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...