Микроконтроллеры 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Функциональная схема модуля 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Временная диаграмма сигналов 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 согласно следующей таблице:

I2Cx_MDS

I2Cx_BUF_EN

Режим работы

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

Разряд I2Cx_CR2

Название

Описание

0

I2Cx_STA

Генерация состояния START

1

I2Cx_STO

Генерация состояния STOP

2

I2Cx_AA

Генерация состояния ACK

3

I2Cx_CMD_TC

Разрешение генерации состояний при установке битов PSTA, PSTO, PAA

4

I2Cx_STA_LCK

Разблокировка записи в разряды I2Cx_STA и I2Cx_PSTA

5

I2Cx_STO_LCK

Разблокировка записи в разряды I2Cx_STO и I2Cx_PSTO

6

I2Cx_AA_LCK

Разблокировка записи в разряды I2Cx_AA и I2Cx_PAA

24

I2Cx_PSTA

Генерация состояния START после завершения текущей операции

25

I2Cx_PSTO

Генерация состояния STOP после завершения текущей операции

26

I2Cx_PAA

Генерация состояния 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Алгоритм работы модуля 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, что может привести к приему лишних данных.

Для ведущего устройства можно рекомендовать следующий алгоритм отправки данных:

  1. Дать команду STA с одновременной записью 1 в поле I2Cx_CR2.I2Cx_BUF_CNT.

  2. В регистр I2Cx_DAT записать адрес ведомого устройства, сдвинутый на 1 разряд влево. Младший бит адреса должен быть нулевым. Таким образом будет сформировано состояние SLA+W.

  3. Ожидать установку флага TXF, т.е. готовность буфера принять новые данные.

  4. В поле I2Cx_CR2.I2Cx_BUF_CNT указать число отправляемых байт (1–4), а также опционально установить бит I2Cx_PSTO или I2Cx_PSTA (вместе с битом I2Cx_CMD_TC), если после отправки требуется автоматически сгенерировать состояние STOP или RSTART соответственно.

  5. Записать новые данные в регистр I2Cx_DAT (после чего начинается фактическая отправка).

  6. Если требуется дальнейшая передача данных (более 4-х байт), повторить пункты 3–5.

  7. При «ручном» методе генерации состояния STOP ожидать активацию флага TSCF (фактическое завершение передачи) и только после этого дать команду STO.

  8. При автоматической генерации состояния STOP перед отправкой следующего кадра (очередной команды STA) необходимо ожидать активацию флага STOPF.

Кроме того, возможно потребуется программный сброс флага TXF перед пунктом 4 в случае отправки нескольких кадров с данными.

Для ведущего устройства можно рекомендовать следующий алгоритм приема данных:

  1. Дать команду STA с одновременной записью 1 в поле I2Cx_CR2.I2Cx_BUF_CNT.

  2. В регистр I2Cx_DAT записать адрес ведомого устройства, сдвинутый на 1 разряд влево. Младший бит адреса должен быть установлен. Таким образом будет сформировано состояние SLA+R.

  3. Ожидать установку флага SADRF, т.е. завершение формирования состояния SLA+R.

  4. В поле I2Cx_CR2.I2Cx_BUF_CNT указать число ожидаемых байт (1–4), а также опционально установить бит I2Cx_PAA и (или) I2Cx_PSTO (вместе с битом I2Cx_CMD_TC), если после приема последнего байта требуется автоматически сгенерировать подтверждение и (или) состояние STOP соответственно.

  5. Ожидать установку флага RXF, т.е. готовность данных в буфере.

  6. Прочитать данные из регистра I2Cx_DAT.

  7. Если требуется дальнейший прием данных (более 4-х байт), повторить пункты 4–6.

  8. При «ручном» методе генерации состояния STOP дать команду STO.

  9. При автоматической генерации состояния STOP перед отправкой следующего кадра (очередной команды STA) необходимо ожидать активацию флага STOPF.

Ведомое устройство (Slave)

Модуль переходит в режим ведомого устройства (slave) после установки одного из битов включения механизма детектирования адреса I2Cx_SADR_EN или I2Cx_SADR2_EN. Алгоритм работы модуля показан на следующем рисунке.

Алгоритм работы модуля I2C в режиме Buffer mode - SlaveАлгоритм работы модуля 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, после чего в программе можно прочитать и проанализировать данные.

Для ведомого устройства можно рекомендовать следующий алгоритм работы:

  1. Установить адрес или адреса (при необходимости, и маску) ведомого устройства и переключиться в режим slave.

  2. Опционально: ожидать срабатывание флага SADRF (очевидно, после получения кадра SLA+W с командой) для детектирования факта обращения к устройству и подготовки к выполнению запроса.

  3. Ожидать срабатывание флага RXF, после чего прочитать данные из регистра I2Cx_DAT, количество принятых байт взять из поля I2Cx_CR2.I2Cx_BUF_CNT.

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

  5. Если согласно полученному запросу требуется отправить данные в ответ, количество байт указать в поле I2Cx_CR2.I2Cx_BUF_CNT, затем поместить их в регистр I2Cx_DAT. Это нужно сделать не дожидаясь активации флага SADRF в следующем кадре SLA+R.

  6. Если требуется дальнейшая отправка данных, ожидать срабатывание флага TXF и перейти на предыдущий пункт.

  7. Опционально: ожидать срабатывание флагов STOPF или RSTRF.

Дополнительные функции

Управление линией SCL для Slave

В режиме Buffer mode в процессе обработки запросов ведомому может потребоваться дополнительное время на формирование ответа, например, на получение данных, которые затребовал ведущий. В этом случае согласно спецификации интерфейса I2C ведомое устройство может задержать тактирование от ведущего путем удержания линии SCL в состоянии низкого уровня. Функция удержания линии SCL по-умолчанию включена и работает в следующих случая:

  • в режиме приема буфер уже заполнен, но программа еще не прочитала из него данные;

  • в режиме передачи буфер уже опустошен, но программа еще не записала в него новые данные.

Для выключения данной функции нужно установить бит I2Cx_CR0.I2Cx_SCLS_DIS.

Таймер таймаута

В состав модулей I2Cx входит 8-разрядный таймер таймаута TMO. Таймер тактируется сигналом CK_I2Cx_TMO (см. п. Тактирование). На рисунке показана функциональная схема таймера.

Таймер таймаута модуля I2CТаймер таймаута модуля 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Схема формирования флагов событий модуля I2C

Флаги событий собраны в регистре I2Cx_STA, а биты разрешения прерываний — в регистре I2Cx_INT. Перечень событий и соответствующих флагов прерываний приведен в следующей таблице.

Разряд I2Cx_STA

Флаг события

Бит прерывания

Название события

Описание

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.

Для включения генерации прерывания необходимо:

  1. Выбрать событие (или события) в регистре I2Cx_INT.

  2. Разрешить прерывание самого модуля установкой бита I2Cx_INT.I2Cx_IEA.

  3. Разрешить прерывание IRQ от модуля в контроллере прерываний NVIC в регистре CPU_ISER.

Тестирование

Аппаратная часть

Целью тестирования является проверка работы МК в роли ведущего и ведомого устройства шины I2C. В роли ведущего будет применяться МК MG32F02A064AD48, в роли ведомого — (1) «эталонный» Slave — часы реального времени DS3231 и (2) МК MG32F02A032AT20. Схема подключения микроконтроллеров показана на следующем рисунке.

Схема подключения МК для тестирования модулей I2CСхема подключения МК для тестирования модулей 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,

  • © Habrahabr.ru