STM32L-Интерфейс I2C
Краткий обзор и простой пример работы с интерфейсом I2C, на примере – CAT24C02 (EEPROM память, объем 256 Байт).
Введение
Описание протокола на русском языке с красивыми диаграммами работы можно посмотреть на сайте Easyelectronics.
Возможности и описание модуля представлено в руководстве пользователя:
RM0038: STM32L151xx and STM32L152xx advanced ARM-based 32-bit MCUs (Руководство пользователя).
Пример Сам протокол не сложный, однако множество вариантов состояний (ошибок) требуют “запутанной” схемы их обработки, реализовать которые сходу у меня не получится, а уж об использовании ПДП (DMA) вообще можно не думать.
Микросхема EEPROM памяти CAT24C02 в контексте интерфейса I2C является ведомым (Slave) устройством, следовательно модуль I2C необходимо настроить в режим ведущего (Master).
В данном режиме микроконтроллер (для простоты описания) сам генерирует тактовые сигналы и инициирует передачу данных.
В установленном на плате STM32L-Discovery микроконтроллере имеется два модуля I2C1 и I2C2, я выбрал первый, так как сигнальные линии второго “попадают” под ЖКИ индикатор, а мне хотелось бы его оставить для вывода отладочной информации. Правда, при этом пришлось отказаться от светодиодов, так как они оба подключены к линиям первого модуля, но паять (выпаивать) на плате ни чего не нужно.
Определение линий:
Должны работать в режиме “открытый сток”, схема включения:
Для начала работы необходимо настроить линии ввода-вывода и разрешить тактирование модуля:
Далее необходимо выбрать частоту тактирования модуля.
Сам модуль подключен к выходу шины APB1 (PCLK1), через два предварительных делителя (обвел синим):
Контроллер поддерживает два режима обмена: стандартный (Standard Speed - up to 100 kHz) и быстрый (Fast Speed (up to 400 kHz).
В зависимости от режима обмена частота тактирования модуля должна быть не ниже:
- 2 MHz в стандартном режиме
- 4 MHz в быстром режиме
После сброса микроконтроллера значение обоих делителей равно одному, а в качестве системной тактовой частоты используется внутренний MSI генератор, с частотой по умолчанию 2,097 МГц. Поэтому я выбрал режим “стандартной” скорости обмена (Standard Speed (up to 100 kHz)).
Текущее значение частоты PCLK1 необходимо прописать в регистр (I2C_CR2):
Не совсем понял для чего это нужно. Возможно, что бы было меньше “телодвижений” при смене тактовой частоты.
В зависимости от указанной частоты необходимо установить предварительный делитель в соответствии с выбранной скоростью обмена. Выберем по максимуму, для стандартного режима – 100 кГц:
2,097 МГц / 100 кГц = 10;
Так как линия данных и тактирования работают в режиме “открытый сток”, то время нарастания сигнала (переход от низкого уровня к высокому) будет довольно большое (зависит частоты обмена и от емкости линий связи).
Для правильной работы необходимо задать в “тактах” частоты тактирования модуля максимально возможное время установления, по спецификации для стандартного режима максимальное время равно 1000 нс.
Период тактовой частоты равен (1 / 2,097 МГц = 476 нс), следовательно время максимальное нарастания:
1000 нс / 476 нс = 2 + 1 (плюс единица – небольшой запас) = 3
Как я понял данный параметр задает момент времени по которому производятся выборка состояния линий. Всё, базовая настройка произведена.
Углубляемся в протокол обмена
Диаграмма работы в режиме произвольного чтения данных из EEPROM памяти:
Как видим необходимо:
- сформировать сигнал “Старт”
- передать адрес ведомого устройства
- передать адрес ячейки памяти
- сформировать сигнал “Повторный Старт”
- передать адрес ведомого устройства
- считать данные
- послать сигнал “Стоп”
Можно выделить два режима работы.
Первый режим - запись данных (от “Старт” до “Повторный Старт”).
Второй режим - чтение данных (от “Повторный Старт” до “Стоп”).
Диаграмма работы в ведущего в режиме - запись данных:
У микросхемы EEPROM памяти ширина адреса 7 бит (верхняя диаграмма).
“Пройдемся” по данному режиму параллельно с программным кодом.
Формирование сигнала “Старт”:
После формирования дожидаемся возникновения события EV5 (см. выше), т.е. установки бита:
Пока я не рассматриваю (не обрабатываю) исключительные ситуации (ошибки, коллизии) возникающие на линии.
Адрес ведомого состоит из:
- бит 0 – говорит о направлении передачи последующих данных (0- от ведущего к ведомогу / 1 – от ведомого к ведущему)
- биты 1-7 – задают адрес ведомого (для EEPROM 0x50)
Передаем адрес ведомого:
Перед передачей необходимо прочитать регистр SR1, для сброса бита SB.
Ожидаем окончания передачи адреса (событие EV6) и сбрасываем бит ADDR (чтением SR1 и SR2):
Для примера считаем значение десятой ячейки EEPROM памяти:
Ожидаем окончания передачи:
Диаграмма работы в ведущего в режиме – чтение данных:
Действия аналогичны предыдущему режиму, поэтому сразу код:
После формируем сигнал “Стоп”
Хух, Прочитали один байтик
Запись одного байта проще:
В связи с тем, что при записи нужного адреса ячейки памяти мы уже находимся в режиме запись.
На этом пока все.
Исходный код
comments powered by Disqus