STM Урок 150. LL. I2C. Подключаем внешний EEPROM. Часть 3



В предыдущей части нашего урока мы настроили проект, а также изучили подробно, каким образом происходит инициализация модуля I2C.

 

Вернёмся в нашу функцию AT24C_WriteBytes и после считывания регистра SR1 отправим адрес устройства в шину

 

 

Затем дождёмся установки бита ADDR в регистре SR1, что будет означать окончание передачи адреса SLAVE в шину

 

 

Очистим флаг ADDR, что делается посредством считывания регистров SR1 и SR2 при помощи следующей функции

 

 

Давайте посмотрим успешность отправки адреса микросхеме, для чего соберём код, прошьём контроллер и посмотрим результат в программе анализа

 

 

Как мы видим, процесс передачи адреса прошел нормально, условие подтверждения присутствует.

Далее мы передаём в шину 16-битный адрес памяти — сначала старшую, а затем младшую его части. После передачи каждого байта мы дожидаемся установки бита TXE, олицетворяющего очистку регистра DR и, следовательно, успешное перемещение данных из него в сдвиговый регистр, из которого впоследствии байт отправится в шину, что не означает окончание его передачи но даёт нам возможность заносить новое значение в регистр DR. Этим обусловливается возможность бесперебойной передачи данных по шине без перерыва на их подготовку

 

 

Раньше срока у нас все равно байт не передастся, так как при помощи функции LL_I2C_TransmitData8 мы лишь заносим данные в регистр DR, а не пытаемся их непосредственно передать. Если предыдущий байт ещё не передан, то данные в сдвиговый регистр не переместятся. Так устроен модуль.

 

 

Соберём код, прошьём контроллер и посмотрим успешность передачи адреса памяти микросхеме

 

 

Адрес памяти также успешно передан.

Далее передадим наши байты аналогичным образом

 

 

Теперь удалим весь пользовательский код из бесконечного цикла и добавим код в функцию main(), который покажет нам значения байтов, которые мы записали в микросхему

 

 

Соберём код, прошьём контроллер и посмотрим результат в логической программе

 

 

 

Все байты успешно переданы.

Также дисплей у нас всё отображает

 

 

Добавим теперь функцию для чтения значений из микросхемы. Механизм чтения байтов из микросхемы немного сложнее, чем их записи. Последний байт (даже если он единственный) принимается без подтверждения (условие NACK). Начало функции аналогичное

 

 

В функции main() закомментируем вызов функции записи и вызовем функцию чтения

 

 

 

В цикле также закомментируем вывод элементов массива данных для записи и выведем элементы массива со считанными данными из микросхемы

 

 

Вернёмся в функцию AT24C_ReadBytes, сформируем ещё одно условие START, а затем передадим адрес устройства уже со сброшенным флагом записи, такой порядок работы с шиной

 

 

Разрешим генерацию условия NACK

 

 

Соберём код, прошьём контроллер и проверим успешность передачи адреса с битом чтения в программе анализа

 

 

Не беда, что у нас передался какой-то левый бит (0X14). Это потом поправится, самое главное что адрес передался. Скорей всего это даже не левый байт, а принятый уже из микросхемы, так как 0x14 — это самый первый байт в массиве и следовательно в микросхеме, расположенный по адресу 0x004A

После передачи адреса попробуем принять байт из микросхемы. Причём в коде мы это делаем не только после разрешения формирования условия NACK но и после попытки послать условие STOP

 

 

Соберём код, прошьём контроллер. В логической программе у нас ничего не изменится, зато на дисплее на секунду засветится двадцатка

Вот так читается один байт, а нам надо прочитать 20, причём с условием NACK нам надо принять только последний.

Поэтому мы удалим сначала мы удалим всё это

 

LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
LL_I2C_GenerateStopCondition(I2C1);
while (!(I2C1->SR1 & I2C_SR1_RXNE)){};
buf[0] = LL_I2C_ReceiveData8(I2C1);

 

А затем добавим цикл с условием

 

 

Соберём код, прошьём контроллер и посмотрим теперь результат работы нашего кода

 

 

 

Мы видим, что все наши байты успешно принялись и последний пришёл без подтверждения. На дисплее тоже всё отобразились (думаю, показывать это не обязательно, поверьте на слово).

Теперь давайте попробуем включить шину на максимальную скорость, так как производитель микросхемы нам обещает работу на огромных скоростях. Правда больше 400 кбпс наша шина на STM не разгоняется, но и это неплохо.

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

 

 

Весь обмен продолжался около 2,2 милисекунды.

Закроем проект в Keil, и в Cube MX внесём следующие изменения

 

 

Сгенерируем ещё раз проект и откроем его в Keil. В код изменения мы никакие не вносим. Они внесутся сами в инициализацию в поля структуры, также сработают другие условия и т.д.

Соберём код, прошьём контроллер и посмотрим теперь общее время чтения 20 байтов из микросхемы

 

 

Процесс теперь длится окло 550 микросекунд, что вчетверо быстрее, чем в режиме Standard. Оно так и есть скорость вместо 100 кбпс у нас теперь 400.

Закоментируем теперь вызов функции чтения, раскомментируем запись, таким же образом поступим и с массивом в цикле

 

 

 

Соберём код, прошьём контроллер и убедимся в том, что процесс записи у нас также остался в работоспособном состоянии

 

 

Всё нормально работает, времени уходит даже меньше, чем на чтение. Ну у нас и байтов меньше в обмене, мы адрес дважды не передаём.

Таким образом, на данном уроке мы научились работать с шиной I2C с использованием возможности библиотеки LL, что позволило нам записать и считать данные по данной шине в микросхему памяти EEPROM AT24C32. Также мы узнали много нового в плане аппаратной реализации и настройки шины I2C в контроллере STM32.

Всем спасибо за внимание!

 

 

Предыдущая часть Программирование МК STM32 Следующий урок

 

Исходный код

 

 

Отладочную плату STM32F103C8T6 можно приобрести здесь STM32F103C8T6

Программатор недорогой можно купить здесь ST-Link V2

Модуль RTC DS3231 с микросхемой памяти (3 шт)

Модуль RTC DS3231 с микросхемой памяти (1 шт) — так дороже

Семисегментный чертырехразрядный индикатор красный с общим анодом 10 шт

Логический анализатор 16 каналов можно приобрести здесь

 

 

Смотреть ВИДЕОУРОК (нажмите на картинку)

 

STM I2C. Подключаем внешний EEPROM

2 комментария на “STM Урок 150. LL. I2C. Подключаем внешний EEPROM. Часть 3
  1. Игорь:

    while(!LL_I2C_IsActiveFlag_SB(I2C1)){};
    //read state
    (void) I2C1->SR1;

    когда считываете состояние бита SB, то регистр SR1 уже читается, какая необходимость читать его снова?

  2. Олег:

    Подскажите пожалуйста такая проблема, пишу например в ячейку по адресу 1 а читаю то что записал по всем адресам (до 200 точно ), в чем может бить проблема ?

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*