Микроконтроллеры Megawin серии MG32F02: модуль интерфейса I2C
Продолжая цикл публикаций по микроконтроллерам на ядре Cortex-M0 компании Megawin (см. предыдущие статьи 1, 2, 3, 4, 5 и 6), сегодня рассмотрим модуль интерфейса I2C.
Функциональные возможности модуля I2C
Микроконтроллеры серии MG32F02 включают один (MG32F02A032) или два (остальные МК) модуля интерфейса I2C. Модули имеют следующие функциональные особенности:
работа в режиме ведущего (master) или ведомого (slave);
частота шины до 1 МГц;
детальная настройка параметров сигнала SCL в режиме ведущего устройства;
удержание сигнала SCL в состоянии низкого уровня в режиме ведомого устройства;
схема активной подтяжки для линий SCL и SDA;
поддержка до двух адресов в режиме ведомого, а также детектирования адреса по маске;
поддержка адреса общего вызова;
поддержка режима нескольких ведущих (multi-master);
детектирование «нештатных» ситуаций на шине (некорректный NACK, переполнение буфера, потеря приоритета);
низкоуровневый (Byte mode) и высокоуровневый (Buffer mode) режимы работы;
буфер приема и передачи размером 4 байта;
поддержка DMA;
встроенный таймер таймаута, определения таймаута шины SMBus;
пробуждение модуля из состояния STOP.
Функциональная схема модулей I2C0 и I2C1 приведена на рисунке.
Функциональная схема модуля I2C
Каждый модуль I2Cx включает следующие основные узлы:
схему тактирования,
схему детектирования состояния пробуждения,
блок контроля линии SCL,
блок контроля линии SDA,
блок управления буфером Buffer Control,
блок управления режимами Master/Slave,
блок детектирования ошибок Error Detector,
таймер таймаута,
схему управления флагами событий и формирования сигнала прерывания INT_I2Cx.
Тактирование
Модуль I2Cx тактируется сигналом CK_I2Cx, источник которого выбирается в поле I2Cx_CLK.I2Cx_CK_SEL
из числа следующих:
сигнал CK_I2Cx_PR с выхода подсистемы тактирования МК, который, в свою очередь, определяется битом
CSC_CKS1.CSC_I2Cx_CKS
из сигналов CK_APB (0) или CK_AHB (1);выходной сигнал таймера TM00_TRGO.
Сигнал CK_I2Cx поступает на предделитель частоты Prescaler, на выходе которого формируется сигнал CK_I2Cx_PSC. Коэффициент предделителя из непрерывного диапазона 2–16 определяется в 4-битном поле I2Cx_CLK.I2Cx_CK_PSC
значениями от 1 до 15 соответственно. Далее сигнал поступает на делитель частоты DIV, коэффициент которого задается в поле I2Cx_CLK.I2Cx_CK_DIV
из ряда 2, 4, 8, …, 128. На выходе делителя формируется основной тактовый сигнал модуля CK_I2Cx_INT. С другого выхода делителя с фиксированным коэффициентом 64 формируется сигнал CK_I2Cx_DIV64. Тактовый сигнал таймера таймаута CK_I2Cx_TMO в зависимости от значения поля I2Cx_CLK.I2Cx_TMO_CKS
может формироваться из сигнала CK_I2Cx_DIV64 или общесистемного сигнала CK_UT.
Частота внутреннего сигнала тактирования модуля CK_I2Cx_INT определяется выражением
FINT = F (CK_I2Cx_INT) = F (CK_I2Cx) / [ (PSC + 1)·DIV ],
где F (CK_I2Cx) частота сигнала CK_I2Cx, PSC — значение поля I2Cx_CLK.I2Cx_CK_PSC
, DIV — значение поля I2Cx_CLK.I2Cx_CK_DIV
.
На следующем рисунке показана временная диаграмма сигналов SCL и SDA.
Временная диаграмма сигналов SCL и SDA
В модуле имеется возможность настраивать интервалы tHIGH и tLOW через поля I2Cx_HT
и I2Cx_LT
регистра I2Cx_CR1
соответственно. Длительности состояния высокого уровня tHIGH и состояния низкого уровня tLOW сигнала SCL определяются выражениями
tHIGH = (1 + HT)·TINT,
tLOW = (1 + LT)·TINT,
где HT и LT — значения полей I2Cx_HT
и I2Cx_LT
соответственно, а TINT = 1 / FINT — период сигнала CK_I2Cx_INT.
В режиме мастера интервал tVD: DAT между задним фронтом сигнала SCL и моментом изменения состояния сигнала SDA составляет 2·TINT. Далее интервал до переднего фронта сигнала SCL составляет (LT-1)·TINT. Период сигнала SCL, формируемого мастером, будет определяться выражением
TSCL = tHIGH + tLOW = (2 + HT + LT)·TINT.
Итоговая номинальная частота шины I2C будет определяться выражением
FSCL = 1 / TSCL = FINT / (2 + HT + LT) = F (CK_I2Cx) / [ (PSC + 1)·DIV·(2 + HT + LT) ].
Параметры HT и LT имеют значения по-умолчанию 5 и 4 соответственно. Минимальными «рабочими» значениями параметров являются 2 и 2.
Режимы работы
Общие сведения
Модуль I2Cx включается установкой бита I2Cx_CR0.I2Cx_EN
. С точки зрения логики взаимодействия аппаратуры и программы в модулях I2Cx реализованы три основных режима работы:
I2C Byte mode — низкоуровневый (программно-аппаратный) режим с необходимостью реализации программного контроля приема и передачи на основе конечного автомата,
I2C Buffer mode — высокоуровневый (аппаратный режим),
Monitor (Buffer mode) — режим мониторинга (сниффер шины).
В первых двух режимах (I2C) модуль может играть роль ведущего (Master) или ведомого (Slave) устройства на шине I2C. Режим работы определяется битами I2Cx_MDS
и I2Cx_BUF_EN
регистра I2Cx_CR0
согласно следующей таблице:
|
| Режим работы |
---|---|---|
0 (I2C) | 0 (Disable) | I2C Byte mode (по-умолчанию) |
0 (I2C) | 1 (Enable) | I2C Buffer mode |
1 (Monitor) | 0 (Disable) | --- |
1 (Monitor) | 1 (Enable) | Monitor |
При дальнейшем рассмотрении работы модуля будем исходить из того, что читатель знаком с общим принципом функционирования шины I2C. Для изучения этого вопроса можно обратиться к официальной спецификации и ее переводу на русский язык:
Далее будем использовать следующие обозначения:
Обозначение | Описание |
---|---|
START | Состояние шины «Старт» (Start) |
STOP | Состояние шины «Стоп» (Stop) |
RSTART | Состояние шины «Повторный старт» (Repeated Start) |
SLA | Адресный кадр, с которого начинается обмен данными (Slave Address) |
SLA+W | Адресный кадр, в котором указывается, что ведущий далее будет передавать данные (SLA + Write) |
SLA+R | Адресный кадр, в котором указывается, что ведущий далее будет принимать данные (SLA + Read) |
ACK | Состояние шины «Подтверждено» (Acknowledgment) |
NACK | Состояние шины «Не подтверждено» (No Acknowledgment) |
Адресация
С точки зрения роли устройства на шине I2C в модулях I2Cx реализованы режимы «ведущее устройство» (Master) и «ведомое устройство» (Slave). По-умолчанию включен режим ведущего устройства. Режим ведомого включается при разрешении детектирования адреса.
В режиме ведомого устройства могут быть заданы один или два собственных адреса, на которые будет отвечать модуль. Основной адрес ведомого задается в регистре I2Cx_SADR
в битах 1–7, т.е. если записывать байт, то бит 0 можно оставить равным 0. Дополнительный адрес задается в битах 9–15 аналогично. Детектирование основного адреса разрешается установкой бита I2Cx_SADR_EN
, а дополнительного — установкой бита I2Cx_SADR2_EN
в регистре I2Cx_CR0
. Установка хотя бы одного из этих битов переводит модуль в режим ведомого устройства. В режиме пониженного энергопотребления STOP, если один из этих битов установлен, при детектировании на шине кадра обращения к устройству модуль активирует флаг пробуждения WUPF.
Для основного адреса также можно задействовать маску I2Cx_MASK.I2Cx_SA_MSK
(биты 1–7 регистра), расширяющую диапазон адресов, на которые будет отвечать модуль: в адресе будут проверяться только те разряды, которые установлены в 1 в маске. По-умолчанию, в маске установлено значение 0×7F, т.е. строгое соответствие заданному в поле I2Cx_SADR
адресу. Кроме того, модуль будет отвечать на нулевой адрес (общий вызов), если установлен бит I2Cx_CR0.I2Cx_GC_EN
(по-умолчанию сброшен).
Буфер данных
В модуле I2Cx программно доступен 8-разрядный сдвиговый регистр I2Cx_SBUF
, выполняющий функцию буфера данных нижнего уровня. Программа же обычно взаимодействует с 32-разрядным регистром I2Cx_DAT
, выполняющим функцию буфера верхнего уровня с возможностью 8-, 16- и 32-битного доступа. Буфер тесно связан с полем I2Cx_CR2.I2Cx_BUF_CNT
, в котором в режиме Buffer mode задается фактическое число (1–4) принимаемых или передаваемых байт (в режиме Master) или сохраняется число уже принятых байт (в режиме Slave). Последовательность байт при приеме или передаче — от младшего к старшему.
В режиме Buffer mode при передаче данных разрядность операции записи в регистр I2Cx_DAT
должна соответствовать объему передаваемых данных: для записи одного байта нужно использовать байтовую пересылку (STRB
) в младший байт регистра, для двух байт — двухбайтовую (STRH
), для 3–4 байт — пересылку слова (STR
).
Команды управления состоянием
Для управления состоянием шины I2C в регистре I2Cx_CR2
имеются биты, установка которых приводит к генерации нового состояния непосредственно в момент их установки или по завершению текущей операции приема или передачи данных. Биты команд приведены в следующей таблице.
Разряд | Название | Описание |
---|---|---|
0 |
| Генерация состояния START |
1 |
| Генерация состояния STOP |
2 |
| Генерация состояния ACK |
3 |
| Разрешение генерации состояний при установке битов PSTA, PSTO, PAA |
4 |
| Разблокировка записи в разряды |
5 |
| Разблокировка записи в разряды |
6 |
| Разблокировка записи в разряды |
24 |
| Генерация состояния START после завершения текущей операции |
25 |
| Генерация состояния STOP после завершения текущей операции |
26 |
| Генерация состояния ACK после завершения текущей операции |
Команда STA (START) формируется при установке бита I2Cx_STA
вместе с битом разблокировки I2Cx_STA_LCK
и приводит в режиме Master к генерации состояния START, если шина была свободна. Если шина была занята, ожидается состояние STOP на шине, после чего генерируется состояние START. Если модуль уже находится в режиме ведущего после предыдущей команды STA в процессе приема или передачи, генерируется состояние RSTART.
Команда STO (STOP) формируется при установке бита I2Cx_STO
вместе с битом разблокировки I2Cx_STO_LCK
и приводит в режиме Master к генерации состояния STOP. Если одновременно с командой STO дается команда STA, то после генерации состояния STOP генерируется состояние START. В режиме Slave команда STO может использоваться для выхода из состояния какой-либо ошибки на шине.
Команда AA (ACK) формируется при установке бита I2Cx_AA
вместе с битом разблокировки I2Cx_AA_LCK
и приводит к генерации состояния ACK (низкий уровень сигнала SDA в течение передачи 9-го импульса сигнала SCL в текущем кадре) в следующих случаях:
подтверждение адреса при совпадении в кадре SLA в режиме ведомого устройства,
подтверждение принятия байта в режиме приема ведущим устройством,
подтверждение принятия байта в режиме приема ведомым устройством.
Если устанавливается бит I2Cx_AA_LCK
при сброшенном бите I2Cx_AA
, генерируется состояние NACK (остается высокий уровень сигнала SDA в течение передачи 9-го импульса сигнала SCL в текущем кадре) в следующих случаях:
принят байт в режиме приема ведущим устройством,
принят байт в режиме приема ведомым устройством.
Команды STO и AA предназначены для применения, в первую очередь, в программно-аппаратном режиме (Byte mode). В аппаратном режиме (Buffer mode) большинство действий выполняется автоматически и в программе лишь требуется заранее установить поведение модуля с помощью команд PSTA, PSTO и PAA. Для их выполнения также должен быть установлен бит I2Cx_CMD_TC
.
Команда PSTA формируется при установке бита I2Cx_PSTA
вместе с битом I2Cx_STA_LCK
и приводит в режиме Master к генерации состояния RSTART после завершения запланированной операции приема или передачи данных.
Команда PSTO формируется при установке бита I2Cx_PSTO
вместе с битом I2Cx_STO_LCK
и приводит в режиме Master к генерации состояния STOP после завершения запланированной операции приема или передачи данных.
Команда PAA формируется при установке бита I2Cx_PAA
вместе с битом I2Cx_STO_LCK
и приводит к формирования состояния подтверждения после завершения запланированной операции приема или передачи данных. Если бит I2Cx_PAA
сброшен, а бит I2Cx_STO_LCK
установлен, после завершения операции подтверждение генерироваться не будет.
Программно-аппаратный режим (Byte mode)
В программно-аппаратном режиме Byte mode передача и прием каждого кадра шины I2C разбивается на несколько этапов, характеризующихся тем или иным состоянием шины и модуля. Завершение каждого этапа и переход в новое состояние представляет собой событие. Программа должна реагировать на каждое новое событие: формировать команды, считывать или записывать данные. Все возможные состояния пронумерованы и представлены в таблице. Отметим, что разработчики МК серии MG32F02 взяли схему кодирования состояний модуля I2C, применяемую в 8-разрядных МК на ядре C8051 (например, NXP, Silicon Labs) и МК серии ATmega.
Код | Описание | MT | MR | SR | ST |
---|---|---|---|---|---|
0×00 | Ошибка шины | v | v | v | v |
0×08 | Сформировано состояние START | v | v | ||
0×10 | Сформировано состояние RSTART | v | v | ||
0×18 | Передан кадр SLA+W и получено подтверждение (ACK) | v | |||
0×20 | Передан кадр SLA+W, подтверждение не получено (NACK) | v | |||
0×28 | Передан байт с данными и получено подтверждение (ACK) | v | |||
0×30 | Передан байт с данными, подтверждение не получено (NACK) | v | |||
0×38 | Потеря приоритета при передаче кадра SLA+R/W или данных | v | v | ||
0×40 | Передан кадр SLA+R и получено подтверждение (ACK) | v | |||
0×48 | Передан кадр SLA+R, подтверждение не получено (NACK) | v | |||
0×50 | Принят байт с данными и сформировано состояние ACK | v | |||
0×58 | Принят байт с данными и сформировано состояние NACK | v | |||
0×60 | Принят кадр SLA+W с собственным адресом и сформировано состояние ACK | v | |||
0×68 | Принят кадр SLA+W с собственным адресом, потерян приоритет, сформировано состояние ACK | v | |||
0×70 | Принят общий вызов и сформировано состояние ACK | v | |||
0×78 | Принят общий вызов, потерян приоритет, сформировано состояние ACK | v | |||
0×80 | Устройство уже адресовано, принят байт с данными и сформировано состояние ACK | v | |||
0×88 | Устройство уже адресовано, принят байт с данными и сформировано состояние NACK | v | |||
0×90 | Общий вызов, принят байт с данными и сформировано состояние ACK | v | |||
0×98 | Общий вызов, принят байт с данными и сформировано состояние NACK | v | |||
0xA0 | Устройство адресовано, обнаружено состояние START или RSTART | v | |||
0xA8 | Принят кадр SLA+R с собственным адресом и сформировано состояние ACK | v | |||
0xB0 | Принят кадр SLA+R с собственным адресом, потерян приоритет, сформировано состояние ACK | v | |||
0xB8 | Передан байт с данными и получено подтверждение (ACK) | v | |||
0xC0 | Передан байт с данными, подтверждение не получено (NACK) | v | |||
0xC8 | Передан последний байт с данными и получено подтверждение (ACK) | v | |||
0xF8 | Состояние шины STOP или шина свободна | v | v | v | v |
В колонках MT, MR, SR и ST указана применимость состояния в режимах «ведущий передает», «ведущий принимает», «ведомый принимает» и «ведомый передает» соответственно. Код последнего события (состояния) всегда отображается в поле I2Cx_STA2.I2Cx_EVENT
, а появление нового события приводит к установке флага EVENTF и возможному прерыванию. В приеме и передаче данных в этом режиме используется только однобайтный буфер I2Cx_SBUF
. Для формирования состояний на шине применяются вышеописанные команды STA, STO и AA.
В документации User Guide приводятся подробные блок-схемы алгоритмов работы модуля и таблицы переходов между состояниями для режимов: «ведущий передает», «ведущий принимает», «ведомый передает», «ведомый принимает» и «ведомый принимает общий вызов». Оптимальной является реализация рассматриваемых алгоритмов на основе прерываний и конечного автомата.
Аппаратный режим (Buffer mode)
Общие сведения
Аппаратный режим (Buffer mode) позволяет максимально автоматизировать работу с модулем I2C и свести к минимуму программный код. Регистр I2Cx_DAT
выполняет в этом режиме функцию 4-байтного буфера, а синхронизация действий с программой достигается с помощью основных флагов RXF и TXF. В данном режиме при приеме и передаче данных используется также 32-разрядный промежуточный буфер (Shadow Buffer). С буфером связан счетчик I2Cx_ACNT
, который увеличивается на 1 в следующих случаях:
в режиме приема данных — при передаче каждого байта из сдвигового регистра Shift Buffer в промежуточный буфер,
в режиме передачи данных — при передаче каждого байта из промежуточного буфера в сдвиговый регистр.
Ведущее устройство (Master)
На следующем рисунке показан алгоритм работы модуля в данном режиме.
Алгоритм работы модуля I2C в режиме Buffer mode — Master
Ведущее устройство начинает работу с формирования на шине адресного кадра SLA. Для этого дается команда STA с одновременным указанием в поле I2Cx_CR2.I2Cx_BUF_CNT
числа передаваемых байт N от 1 до 4. Далее в регистр I2Cx_DAT
записываются передаваемые данные. Первым по порядку байтом должен быть адрес ведомого устройства, к которому происходит обращение, сдвинутый на 1 разряд влево. Если младший бит байта сброшен, формируется кадр SLA+W, если установлен — кадр SLA+R. Если было указано N>1, то в случае ответа ведомого состоянием ACK в кадре SLA+W ведущий продолжает передачу данных в этом же кадре. В любом случае данные передаются только если было получено подтверждение на предыдущий байт. По завершению передачи устанавливается флаг TXF.
При указании в поле I2Cx_BUF_CNT
числа передаваемых байт нужно одновременно сформировать команду PSTO или PSTA, чтобы по завершению передачи модуль сгенерировал состояние STOP или RSTART соответственно.
Если был сформирован кадр SLA+R, после подтверждения адреса со стороны ведомого устройства модуль переходит в режим приема данных. В поле I2Cx_BUF_CNT
нужно указать число принимаемых байт N от 1 до 4. После передачи N байт из промежуточного буфера в регистр I2Cx_DAT
активируется флаг RXF.
В завершающей операции приема данных следует также сформировать команду PSTO или PSTA. В этом случае после получения последнего байта модуль генерирует состояние NACK, сигнализируя тем самым ведомому устройству о завершении операции. Прием всех предыдущих байтов модулем подтверждается автоматически. Если требуется подтвердить и последний байт, вместе с командой PSTO (или PSTA) необходимо также дать команду PAA.
Если в программе перед приемом данных требуется сбросить флаг RXF, то необходимо выполнить «фиктивное» чтение регистра I2Cx_DAT
, а не сбрасывать флаг явно записью 1 в регистр I2Cx_STA
, что может привести к приему лишних данных.
Для ведущего устройства можно рекомендовать следующий алгоритм отправки данных:
Дать команду
STA
с одновременной записью 1 в полеI2Cx_CR2.I2Cx_BUF_CNT
.В регистр
I2Cx_DAT
записать адрес ведомого устройства, сдвинутый на 1 разряд влево. Младший бит адреса должен быть нулевым. Таким образом будет сформировано состояние SLA+W.Ожидать установку флага TXF, т.е. готовность буфера принять новые данные.
В поле
I2Cx_CR2.I2Cx_BUF_CNT
указать число отправляемых байт (1–4), а также опционально установить битI2Cx_PSTO
илиI2Cx_PSTA
(вместе с битомI2Cx_CMD_TC
), если после отправки требуется автоматически сгенерировать состояние STOP или RSTART соответственно.Записать новые данные в регистр
I2Cx_DAT
(после чего начинается фактическая отправка).Если требуется дальнейшая передача данных (более 4-х байт), повторить пункты 3–5.
При «ручном» методе генерации состояния STOP ожидать активацию флага TSCF (фактическое завершение передачи) и только после этого дать команду
STO
.При автоматической генерации состояния STOP перед отправкой следующего кадра (очередной команды
STA
) необходимо ожидать активацию флага STOPF.
Кроме того, возможно потребуется программный сброс флага TXF перед пунктом 4 в случае отправки нескольких кадров с данными.
Для ведущего устройства можно рекомендовать следующий алгоритм приема данных:
Дать команду
STA
с одновременной записью 1 в полеI2Cx_CR2.I2Cx_BUF_CNT
.В регистр
I2Cx_DAT
записать адрес ведомого устройства, сдвинутый на 1 разряд влево. Младший бит адреса должен быть установлен. Таким образом будет сформировано состояние SLA+R.Ожидать установку флага SADRF, т.е. завершение формирования состояния SLA+R.
В поле
I2Cx_CR2.I2Cx_BUF_CNT
указать число ожидаемых байт (1–4), а также опционально установить битI2Cx_PAA
и (или)I2Cx_PSTO
(вместе с битомI2Cx_CMD_TC
), если после приема последнего байта требуется автоматически сгенерировать подтверждение и (или) состояние STOP соответственно.Ожидать установку флага RXF, т.е. готовность данных в буфере.
Прочитать данные из регистра
I2Cx_DAT
.Если требуется дальнейший прием данных (более 4-х байт), повторить пункты 4–6.
При «ручном» методе генерации состояния STOP дать команду
STO
.При автоматической генерации состояния STOP перед отправкой следующего кадра (очередной команды
STA
) необходимо ожидать активацию флага STOPF.
Ведомое устройство (Slave)
Модуль переходит в режим ведомого устройства (slave) после установки одного из битов включения механизма детектирования адреса I2Cx_SADR_EN
или I2Cx_SADR2_EN
. Алгоритм работы модуля показан на следующем рисунке.
Алгоритм работы модуля I2C в режиме Buffer mode — Slave
При получении кадра SLA+R с подходящим адресом модуль подтверждает кадр и активирует флаг SADRF. Далее происходит передача данных из буфера I2Cx_DAT
(режим Slave Transmitter) в промежуточный буфер. Счетчик в поле I2Cx_CR2.I2Cx_ACNT
отображает число фактически отправленных байт из промежуточного буфера в сдвиговый регистр.
Если число N, указанное в поле I2Cx_CR2.I2Cx_BUF_CNT
, было в интервале от 1 до 4, после передачи N байт в промежуточный буфер на отправку активируется флаг TXF. В этот момент в программе в регистр I2Cx_DAT
нужно записать новые данные. После записи в регистр I2Cx_DAT
счетчик I2Cx_ACNT
обнуляется. Если новые данные не были записаны, будут отправляться существующие данные последовательно с нулевого по (N-1)-й байт. Данные в принципе будут передаваться на шину пока ведущее устройство генерирует тактовые импульсы сигнала SCL не зависимо от значения I2Cx_BUF_CNT
до тех пор, пока на шине не будет cгенерировано состояние STOP или RSTART. Если значения I2Cx_BUF_CNT
равно 0, флаг TXF сработает после отправки 8-го байта, при этом соответствия отправляемых данных каким-либо байтам буфера не гарантируется.
После получения и подтверждения кадра SLA+W также активируется флаг SADRF и затем начинается процесс приема данных. Каждый принятый байт из сдвигового регистра помещается в промежуточный буфер. Четырехбайтный промежуточный буфер заполняется начиная с младшего байта. Количество байт, записанных в этот буфер, доступно в поле I2Cx_CR2.I2Cx_ACNT
. После записи 4-го байта или при определении на шине состояния STOP или RSTART выполняются следующие действия:
принятые данные копируются в регистр
I2Cx_DAT
,число принятых байт записывается в поле
I2Cx_CR2.I2Cx_BUF_CNT
,значение поля
I2Cx_CR2.I2Cx_ACNT
обнуляется,активируется флаг RXF, после чего в программе можно прочитать и проанализировать данные.
Для ведомого устройства можно рекомендовать следующий алгоритм работы:
Установить адрес или адреса (при необходимости, и маску) ведомого устройства и переключиться в режим slave.
Опционально: ожидать срабатывание флага SADRF (очевидно, после получения кадра SLA+W с командой) для детектирования факта обращения к устройству и подготовки к выполнению запроса.
Ожидать срабатывание флага RXF, после чего прочитать данные из регистра
I2Cx_DAT
, количество принятых байт взять из поляI2Cx_CR2.I2Cx_BUF_CNT
.Проанализировать данные. Если требуется дальнейший прием данных, перейти на предыдущий пункт.
Если согласно полученному запросу требуется отправить данные в ответ, количество байт указать в поле
I2Cx_CR2.I2Cx_BUF_CNT
, затем поместить их в регистрI2Cx_DAT
. Это нужно сделать не дожидаясь активации флага SADRF в следующем кадре SLA+R.Если требуется дальнейшая отправка данных, ожидать срабатывание флага TXF и перейти на предыдущий пункт.
Опционально: ожидать срабатывание флагов STOPF или RSTRF.
Дополнительные функции
Управление линией SCL для Slave
В режиме Buffer mode в процессе обработки запросов ведомому может потребоваться дополнительное время на формирование ответа, например, на получение данных, которые затребовал ведущий. В этом случае согласно спецификации интерфейса I2C ведомое устройство может задержать тактирование от ведущего путем удержания линии SCL в состоянии низкого уровня. Функция удержания линии SCL по-умолчанию включена и работает в следующих случая:
в режиме приема буфер уже заполнен, но программа еще не прочитала из него данные;
в режиме передачи буфер уже опустошен, но программа еще не записала в него новые данные.
Для выключения данной функции нужно установить бит I2Cx_CR0.I2Cx_SCLS_DIS
.
Таймер таймаута
В состав модулей I2Cx входит 8-разрядный таймер таймаута TMO. Таймер тактируется сигналом CK_I2Cx_TMO (см. п. Тактирование). На рисунке показана функциональная схема таймера.
Таймер таймаута модуля I2C
В зависимости от значения поля I2Cx_TMOUT.I2Cx_TMO_MDS
таймер работает в следующих режимах:
0 — ожидание низкого уровня на линии SCL (по-умолчанию),
1 — ожидание высокого уровня на линиях SCL и SDA,
2 — таймер общего назначения.
Для включения таймера необходимо установить бит I2Cx_TMOUT.I2Cx_TMO_EN
. Для применения таймера в режиме общего назначения необязательно включать модуль I2Cx. Период счета таймера задается в поле I2Cx_TMOUT.I2Cx_TMO_CNT
. После завершения полного периода (переполнения) активируется флаг TMOUTF. Если установлен бит I2Cx_TMOUT.I2Cx_TMO_CTL
, то при этом происходит сброс всего модуля I2Cx. После срабатывания таймера TMO с настройкой на сброс перед началом каких-либо следующих действий необходимо сбросить флаг TMOUTF, иначе модуль не сможет корректно работать. Автоматический сброс модуля I2Cx при установленном бите I2Cx_TMOUT.I2Cx_TMO_CTL
не приводит к сбросу этого флага.
События и прерывания
Схема формирования общих (вторичных) флагов событий BUFF, STPSTRF и ERRF, генерирующих прерывание модуля INT_I2Cx, приведена на следующем рисунке.
Схема формирования флагов событий модуля I2C
Флаги событий собраны в регистре I2Cx_STA
, а биты разрешения прерываний — в регистре I2Cx_INT
. Перечень событий и соответствующих флагов прерываний приведен в следующей таблице.
Разряд | Флаг события | Бит прерывания | Название события | Описание |
---|---|---|---|---|
0 | BUSYF | - | I2C control busy | Модуль занят выполнением операции |
1 | EVENTF | EVENT_IE | Event code change | Изменилось состояние модуля |
2 | BUFF | BUF_IE | Buffer mode event | Общий флаг событий в буфере |
3 | ERRF | ERR_IE | Error detect | Общий флаг ошибок |
4 | TMOUTF | TMOUT_IE | Timeout detect | Сработал таймер таймаута |
5 | WUPF | WUP_IE | STOP mode wakeup by I2C event | Событие пробуждения в режиме питания STOP при получении адресного кадра в режиме Slave |
6 | RXF | BUF_IE | Receive data register not empty | Принятые данные готовы к чтению (Buffer mode) |
7 | TXF | BUF_IE | Transmit data register empty | Буфер передачи готов к записи новых данных (Buffer mode) |
8 | RSTRF | BUF_IE | Repeat Start asserted | Обнаружено состояние шины RSTART |
9 | STOPF | BUF_IE | Stop detection | Обнаружено состояние шины STOP |
10 | CNTF | - | BUF_CNT register empty | Счетчик BUF_CNT в значении 0 |
11 | ERRCF | - | I2C error | Не принято подтверждение в режиме Master в кадре SLA или при передаче данных |
12 | SADRF | BUF_IE | Slave address asserted or match detect | В режиме Slave — получен кадр SLA с подходящим адресом, в режиме Master — ведомый подтвердил адрес в кадре SLA+R |
13 | SLAF | - | Slave mode detect | Включен режим ведомого |
14 | MSTF | - | Master mode detection | Включен режим ведущего |
15 | RWF | - | Read or write transfer direction | Состояние 8-го бита в кадре SLA: 0 — кадр SLA+W, 1 — кадр SLA+R |
16 | TSCF | - | Shadow Buffer Transfer complete | В режиме передачи байт из промежуточного буфера скопирован в сдвиговый регистр, в режиме приема — из сдвигового регистра в промежуточный буфер |
17 | STPSTRF | STPSTR_IE | STOP or START detect | Обнаружено состояние STOP или START |
18 | TXRF | - | Slave mode transmit data register remained status | Флаг активен, если при отправке из-за ошибки в буфере остались непереданные данные |
19 | ROVRF | ERR_IE | Data buffer RX overrun | Переполнение буфера приема (Buffer mode, задержка SCL отключена) |
20 | TOVRF | ERR_IE | Data buffer TX Overrun | Буфер передачи не содержит данных (Buffer mode, задержка SCL отключена) |
21 | NACKF | ERR_IE | Invalid NoACK received Error | Обнаружено состояние шины NACK |
22 | ALOSF | ERR_IE | Arbitration lost error | Потеря приоритета |
23 | BERRF | ERR_IE | Bus error | Ошибка шины |
В режиме Byte mode для работы ПО необходимо включить прерывание EVENT_IE по флагу EVENTF. В режиме Buffer mode для работы ПО достаточно включить прерывание BUF_IE по флагу BUFF. Если требуется анализ ошибок, необходимо также включить прерывание ERR_IE по общему флагу ERRF. Прерывание TMOUT_IE генерируется только при включении в работу модуля таймера таймаута TMO.
В процессе тестирования обнаружена недокументированная функция: в старшем байте регистра I2Cx_STA
отображается код состояния модуля I2Cx_EVENT
, в том числе, в режиме Buffer mode.
Для включения генерации прерывания необходимо:
Выбрать событие (или события) в регистре
I2Cx_INT
.Разрешить прерывание самого модуля установкой бита
I2Cx_INT.I2Cx_IEA
.Разрешить прерывание IRQ от модуля в контроллере прерываний NVIC в регистре
CPU_ISER
.
Тестирование
Аппаратная часть
Целью тестирования является проверка работы МК в роли ведущего и ведомого устройства шины I2C. В роли ведущего будет применяться МК MG32F02A064AD48, в роли ведомого — (1) «эталонный» Slave — часы реального времени DS3231 и (2) МК MG32F02A032AT20. Схема подключения микроконтроллеров показана на следующем рисунке.
Схема подключения МК для тестирования модулей I2C
Все устройства запитываются от стабилизатора напряжением 3.3 В программатора J-Link/ST-Link. Для удобства переключения линий SWD-интерфейса между МК установлен переключатель S1. Для линий интерфейса I2C SCL и SDA установлены внешние резисторы подтяжки R3 и R4. При подключении модуля DS3231 МК U2 отключается от шины I2C перемычками (на схеме не показаны), а при работе U2 в качестве ведомого — отключается модуль DS3231, поскольку МК эмулирует его работу. Каждый МК также подключается к ПК через интерфейс UART (в обоих случаях используется модуль МК URT0).
Проектные файлы
В тестировании принимают участие одновременно два «подопытных» МК, поэтому в файлах конфигурации проекта есть изменения. Действия по настройке путей к библиотечным файлам от вендора перенесены в отдельную функцию setup_paths()
в файле premake5.lua
, поскольку пути зависят от типа МК. Для МК MG32F02A032 аргументом функции нужно указать строку "MG32F02A032"
, для всех остальных МК семейства — строку "MG32F02A128"
. В файле определены следующие цели сборки:
svr32
— базовая часть (supervisor) для МК MG32F02A032,svr64
— базовая часть для МК MG32F02A064,