Модуль I2C в dsPIC

advertisement
7. Модуль I2C в dsPIC
7.1. Описание интерфейса I2C
7.2. Характеристики модуля I2C в dsPIC
7.3. Настройка модуля I2C
7.4. Работа модуля I2C в режиме ведущего
7.5. Работа модуля I2C на примере (пример в PROTEUS)
7.1. Описание интерфейса I2C
Inter-Integrated Circuit (I2C) модуль - последовательный интерфейс, предназначен,
чтобы поддерживать связь с периферийными устройствами микроконтроллера.
Периферийными устройствами могут быть последовательные EEPROM, драйверы
дисплея, A/D преобразователи, и т.д.
Характеристики шины I2C
Шина I2C – это двухпроводный последовательный интерфейс. На рисунке 1
приведено схемная реализация шины I2C между dsPIC33F и 24LC256 EEPROM по I2C,
которая является типичным примером для любого интерфейса I2C.
Рисунок 1. Типичная схема организации шины I2C
Интерфейс использует двунаправленный протокол, чтобы гарантировать надежную
передачу и прием данные. При соединении одно устройство выполняет роль ведущего.
Ведущий начинает передачу данных на шине, а также генерирует тактовые импульсы А
второе устройство является ведомым, отвечающим на передачу. Линия тактирования
SCLx управляется ведущим, и по ней тактовые импульсы поступают ведомому, хотя есть
такие ситуации, когда и ведомый может управлять линией SCLx. Линия данных, SDAx,
может быть как выходом, так и входом, как для ведущего, так и для ведомого.
Поскольку линии SDAx и SCLx двунаправлены, то выводы устройств должны
иметь линии SDAx и SCLx с открытым коллектором, чтобы обеспечить функцию
логического И на шине. Внешние подтягивающие резисторы используются, чтобы
гарантировать высокий уровень на линиях, когда ни одно из устройств не управляет
шиной.
В протоколе интерфейса I2C, каждое устройство имеет свой собственный адрес.
Когда ведущий желает инициализировать передачу данных, то он сначала передаёт адрес
устройства, с которым требуется установить связь. Все устройства "слушают шину" и
проверяют, является ли это их адрес. Нулевой бит адреса определяет, хочет ли ведущий
прочитать или записать данные из/на ведомое устройство. Ведущий и ведомый всегда
находятся в противоположных режимах во время передачи данных, т.е. если один
является ведущим, то второй должен быть ведомым, т.е. по парам:
• Ведущий-передатчик и Ведомый-приёмник
• Ведомый-передатчик и ведущий-приёмник
В любом случае тактовый сигнал SCLx генерирует ведущий.
Шинный протокол
Был определён следующий протокол на шине I2C:
• Передача данных может быть начата, только когда шина не занята.
• В течение передачи данных, состояние на линии данных НЕ должны изменяться в то
время, когда на тактовой линии SCLx находится высокой уровень. Так как данный режим
зарезервирован для служебных нужд. В частности, таким образом формируются условия
START и STOP.
На рисунке 2 показаны различные состояния шины I2C.
Рисунок 2. Состояние протокола шины I2C
Условие START (S)
После простоя шины, когда линии SCLx находится в высоком уровне, необходимо
на линии SDAx сменить уровень с высокого на низкий. Это и будет соответствовать
условию START. Перед тем как передавать данные, нужно сначала выполнить условие
START.
Условие STOP (P)
Переход на линии SDAx от низкого к высокому уровню, в то время как тактовая
линия (SCLx) находится в высоком состоянии – соответствует условию STOP. Все
передачи данных должны заканчиваться условием STOP.
Условие повторного START (R)
После неактивного состояния шины, переход на линии SDAx от высокого к
низкому уровню, в то время как тактовая линия (SCLx) находится в высоком состоянии определяет условие повторного START. Повторный START разрешает ведущему
изменить режим управления шиной или адрес ведомого без освобождения шины (чтобы
другое устройство не смогло захватить шину для своих нужд).
Достоверность данных (D)
Состояние линии SDAx предоставляет достоверные данные, когда, после условия
START, линия SDAx устойчиво в то время, когда на тактовой линии присутствует
высокий уровень. Один такт на SCLx передаёт один бит данных.
Подтверждение (A), или не подтсверждение (N)
Все передачи байта данных должны быть подтверждены (ACK) или не
подтверждено (NACK) приёмником. Для формирования ACK приёмник устанавливает на
линии SDAx низкий уровень, или отпускает линию SDAx (т.е. устанавливается «1») для
условия NACK.
Для подтверждения используется 1 дополнительный такт SCLx.
Задержка или данные недействительны (Q)
Данные на линии должны изменяться, когда на тактовой линии присутствует
низкий уровень. Устройство также может задержать низкий уровень на тактовой линии
SCLx, что вызывает задержку на шине (например, для подготовки данных для ответа без
освобождения шины).
Простой шины (I)
Это состояние, когда на обеих линиях присутствует высокий уровень. В этом
состоянии шина находится до условия START и после условия STOP.
Протокол Сообщения
Типичное I2C сообщение показано на рисунке 3. В этом примере, сообщение будет
читать указанный байт из последовательной EEPROM 24LC256 по шине I2C. dsPIC33F
будет работать как ведущий, а 24LC256 как ведомый.
Рисунок 3 показывает данные на ведущем устройстве и на ведомом устройстве,
принимая во внимание, что объединенная линия SDAx включена по схеме логического И
между ведущим и ведомым. Ведущее устройство обеспечивает работу протоколом.
Ведомое устройство будет управлять шиной только в определённое время.
Рисунок 3. Сообщения чтения данных с EEPROM
Условие START
Каждое сообщение инициализируется условием START и заканчивается условием
STOP. Число байт данных передаваемых между условием START и условием STOP –
определяет ведущее устройство.
Адрес ведомого
На рисунке 3, первый байт - это байт адреса устройства, который должен всегда
следовать первым байтом в сообщении I2C. Оно содержит адрес устройства и состояние
бита R/W. Если R/W = 0, то это указывает, что для адресуемого ведомого будет
установлен режим, когда ведущий будет передатчиком, а ведомый приёмником.
Подтверждение ведомым
Приёмник обязан генерировать подтверждение “ACK”, после приема каждого
байта. Ведущий должен генерировать дополнительные импульсы SCLx, для
подтверждений.
Передача ведущим
Следующие два байта, посланные ведущим ведомому, являются байтами данных,
содержащими местоположение требуемого байта данных EEPROM. Ведомый должен
подтверждать приём каждого байта данных.
Повторный START
В данном месте, ведомое EEPROM имеет адрес байта данных, который
необходимую возвратиться ведущему. Однако, бит R/W ещё от первого байта сообщения
(адресного) определяет, что ведущий является передатчиком, а ведомый приёмником.
Шина должна быть переопределена, чтобы ведущий принимал данные, а ведомый
отправлял данные. Чтобы выполнить эту функцию, не обрывая сообщение, ведущий
посылает “Повторный START”.
Повторный START сопровождается байтом адреса устройства, содержащим тот же
самый адрес устройства, как и прежде, но с битом R/W = 1, чтобы указать, что теперь
ведущий будет принимать, а ведомый передавать.
Ответ ведомым
Теперь ведомый передаёт байт данных, управляя линией SDAx, в то время как
ведущий продолжает формировать такты. При этом ведущий отпускает линию SDAx, для
того чтобы ею мог управлять ведомый.
Подтверждение ведущим
В течение чтения, ведущий должен закончить приём данных от ведомого выполнив
условие “NACK” на последнем байте сообщения, который он желает принять.
Условие STOP
Ведущий посылает STOP, чтобы закончить сообщение и возвратить шину в
неактивное состояние.
7.2. Характеристики модуля I2C в dsPIC
I2C модуль может работать в любом из следующих режимов:
• Как ведомое устройство
• Как ведущее устройство с одним ведущим в системе
• Как ведущее/ведомое устройство в многопроцессорной системе (имеется арбитраж
доступа к шине)
I2C – является независимым модулем, который содержит логику для работы в
режиме ведущего и для работы в режиме ведомого. Имеет свои собственные прерывания,
основанные на событиях, происходящих в данном модуле.
Когда активна логика ведущего I2C, тогда логика ведомого также является
активной, определяя состояние на шине и возможного получения сообщений от себя же в
системе с одним ведущим или от другого ведущего в многопроцессорной системе. В
мультипроцессорном режиме никакие сообщения НЕ теряются из-за шинного арбитража.
В мультипроцессорной системе, если выявляется шинная коллизия с другими ведущими в
системе, то модуль прерывает свою операцию и затем перезапускает сообщения.
I2C модуль содержит Генератор скорости обмена. Так как данный генератор
встроен в модуль I2C, то он не потребляет ресурсы имеющихся таймеров в
микроконтроллере.
Ниже приведены главные особенности модуля I2C:
• Независимая логика для ведущего и ведомого
• Поддержка мультипроцессорной системы, которая предотвращает потери сообщения с
помощью арбитража
• Обнаруживает 10-ти и 7-ми битные адреса устройства с настройкой маски адреса в
режиме ведомого
• Обнаруживает адреса общего вызова как определено в I2C протоколе
• режим Bus Repeater, позволяет модулю принимать все сообщения как ведомому
независимо от его адреса
• Автоматический генератор SCLx, может приостановиться для задержки, чтобы
микроконтроллер мог ответить ведомому на запрос.
• Поддерживает скорости обмена данными 400 кГц и 100 кГц
• Поддерживает стандарт Intelligent Platform Management Interface (IPMI).
На рисунке 4 изображена блок схема модуля I2C.
Рисунок 4. Блок схема модуля I2C
7.3. Настройка модуля I2C
Модуль включается установкой бита I2CEN (I2CxCON <15>). Модуль I2C
полностью осуществляет все функции ведущего и ведомого. Когда модуль включён,
функции ведущего и ведомого активны одновременно и отвечают согласно программному
обеспечению или событиям на шине.
Когда инициализация выполнена, модуль отпустит выводы SDAx и SCLx, переводя
шину в состояние простоя. Функции ведущего остаются в режиме простоя, пока в
программе не будет установлен бит SEN и данные загружаются в регистр I2CxTRN. Эти
два действия инициируют события ведущего.
Когда логика ведущего активна, то логика ведомого также остаётся активной.
Поэтому, функции ведомого ведут мониторинг шины. Если логика ведомого
обнаруживает условие START и свой адрес на шине, то логика ведомого начнёт
транзакцию в режиме ведомого.
Активизация входов выходов I2C
Два вывода используются для операций с шиной. Это вывод SCLx, который
является тактовой линией, и вывод SDAx, который является выводом данных. Когда
модуль I2C включён, то выводами SDAx и SCLx будет управлять модуль I2C, при этом
значения битов регистра TRIS для данных выводов будут игнорировать. При
инициализации выводы находятся в отпущенном состоянии (3-ем состоянии, не оказывая
влияние на шину).
I2C прерывания
I2C модуль генерирует два вида прерываний. Одно прерывания, MI2CxIF,
предназначен для событий ведущего; другое прерывание, SI2CxIF, предназначено для
событий ведомого. Эти прерывания устанавливают соответствующие флаги прерываний и
формируют сами прерывания, которые обрабатываются программным обеспечением, если
соответствующее прерывания разрешено и установлен достаточно высокий приоритет
прерывания.
Прерывание MI2CxIF происходит при завершении следующих событий ведущего:
• условие START
• условие STOP
• Передача данных, байт передаётся/принимается
• Подтверждение передачи
• Повторный START
• Обнаружение коллизии на шине
Прерывание SI2CxIF происходит при обнаружении сообщения направленного
ведомому, включая следующие события:
• Обнаружение собственного адреса (включая общий запрос)
• Подтверждение данных (ACK) или (NACK)
• Прием данных
Настройка скорости обмена при работе в режиме ведущего
При работе в режиме ведущего, модуль I2C должен генерировать тактовые
импульсы на выводе SCLx. Вообще, тактовая частота на шине I2C должна
соответствовать стандартной 100 кГц, 400 кГц или 1 МГЦ.
Перегружаемое значение для генератора baud rate (BRG) – это регистр I2CxBRG,
как показано на рисунке 5. Когда генератор скорости обмена загружен этим значением, то
генератор считает в обратном порядке к 0, а после перегружается. Значение генератора
уменьшается дважды в цикле инструкции (TCY).
Рисунок 5. Блок схема генератора Baud rate
Обратите внимание: регистр I2CxBRG не поддерживает значение меньше чем 2.
Вычислять значение генератора скорости обмена можно используя следующее уравнение:
Ниже приведена таблица, показывающая примеры значений для некоторых частот
Требуемая системная
частота FSCL
100 кГц
100 кГц
100 кГц
400 кГц
400 кГц
400 кГц
1 МГц
FCY
I2CBRG в DEC
I2CBRG в HEX
Частота FSCL
40 МГц
20 МГц
10 МГц
20 МГц
10 МГц
5 МГц
10 МГц
395
197
98
47
23
11
8
0x18B
0x0C5
0x0B2
0x02F
0x017
0x00B
0x008
100 кГц
100 кГц
100 кГц
400 кГц
400 кГц
400 кГц
1 МГц
Обратите внимание: Уравнение и Таблица - только принципы к руководству. Из-за
некоторого отклонения системной частоты, фактическая скорость обмена может
немного отличаться. Только испытания могут подтвердить, что фактическая скорость
обмена отвечает требованиям системы. Иначе, значение из регистра I2CxBRG,
возможно должно быть отрегулировано
7.4. Работа модуля I2C в режиме ведущего
Обычно модуль I2C используется, чтобы связаться с I2C периферией, например I2C
памятью. В I2C системе, ведущий управляет последовательностью всех операций на
шине. Ведущий модуль должен генерировать тактовые импульсы на линии SCLx и
управлять протоколом сообщения.
В I2C модуле, модуль управляет индивидуальными частями I2C протокола
сообщения; при этом собрать всю последовательность воедино – это задача программиста.
Например, типичное действие в системе с одним ведущим – ведущий должен
прочитать байт данных из I2C EEPROM. Пример этого сообщения изображён на рисунке
6.
Рисунок 6. Типичное I2C сообщение: читаем байт из I2C EEPROM (Случайный
Способ Адресации)
Чтобы реализовать это сообщение, программное обеспечение должно реализовать
следующие шаги.
1. Сформировать условие START на выводах SDAx и SCLx.
2. Послать байт адреса ведомому устройству I2C с признаком запись.
3. Дождаться и проверить подтверждение ACК от ведомого.
4. Послать памяти старший байт адреса байта.
5. Дождаться и проверить подтверждение ACК от ведомого.
6. Послать памяти младший байт адреса байта.
7. Дождаться и проверить подтверждение ACК от ведомого.
8. Сформировать условие повторного START на выводах SDAx и SCLx.
9. Послать байт адреса ведомого устройства с признаком чтение.
10. Дождаться и проверить подтверждение ACК от ведомого.
11. Разрешить ведущему получить данные из памяти.
12. Сформировать условие ACK или NACK в конце полученного байта данных.
13. Сформировать условие STOP на выводах SDAx и SCLx.
I2C модуль активизирует какое-то действие, затем ждёт прерывания, или
опрашивает соответствующие флаги, чтобы активизировать следующее действие.
Последующие подглавы детализируют каждое из этих действий.
Обратите внимание: I2C модуль не позволяет организовать очередь событий.
Например, программное обеспечение – не разрешает сформировать условия START и
немедленно записать регистр I2CxTRN для инициализации передачи перед завершением
условия START. В этом случае, регистр I2CxTRN не будет записан и будет установлен
бит IWCOL, указывая что данные в регистр I2CxTRN не были записаны, так как данный
регистр не готов принять данные.
Генерация условия START
Чтобы инициировать условие START, программно нужно установить бит SEN
(I2CxCON <0>). До формирования условия START, программа может проверить бит P
(I2CxSTAT <4>), чтобы убедиться, что шина в настоящее время бездействует.
• Логика ведомого обнаруживает условие START, устанавливает бит S (I2CxSTAT
<3>) и сбрасывает бит P (I2CxSTAT <4>).
• После завершения условия START бит SEN автоматически сбрасывается.
• Происходит прерывание MI2CxIF после завершения условия START.
• После выполнения условия START линии SDAx и линии SCLx находятся в
низком состоянии.
Рисунок 7. Показывает диаграмму формирования условия START.
1 – устанавливается бит SEN = 1, инициализирующий условие START. Запускается
генератор скорости обмена.
2 – Время тактового импульса вышло. Ведущий устанавливает на линии SDAx низкий
уровень. Перезапускается генератор скорости.
3 – Ведомый модуль обнаруживает START и устанавливает S=1 и P = 0.
4 – Время тактового импульса вышло. Ведущий модуль устанавливает на шине SCLx
низкий уровень, генерирует прерывание и сбрасывает SEN.
Флаг IWCOL
Если программное обеспечение запишет регистр I2CxTRN, когда происходит
последовательность START, то установится флаг IWCOL и содержимое буфера
передатчика не изменится (запись не происходит).
Обратите внимание: поскольку организация очереди событий не разрешена, то
запись пяти младших битов в регистре I2CxCON, запрещена, пока условие START не было
завершено.
Передача данных на ведомое устройство
Передача байта данных, 7-ми байтный адрес устройства или двойной байт при 10
битной адресации достигается простой записью соответствующего значения в регистр
I2CxTRN. Загрузка этого регистра начнёт следующий процесс:
• программное обеспечение загружает регистр I2CxTRN байтом данных, чтобы
передать его.
• Запись регистра I2CxTRN устанавливает флаг заполнения буфера TBF
(I2CxSTAT <0>).
• байт данных передаётся по выводу SDAx до тех пор пока все 8 битов не
переданы. Каждый бит адреса/данных будет изменяться на выводе SDAx после заднего
фронта импульса на линии SCLx.
• На девятом импульсе SCLx, модуль принимает бит подтверждения ACK
ведомого устройства и перемещает его значение в бит ACKSTAT (I2CxSTAT <15>).
• модуль генерирует прерывание MI2CxIF в конце девятого тактового импульса
SCLx.
Передача 7-ми битного адреса ведомому
Передача 7-ми битного адреса устройства вовлекает посылку одного байта
ведомому. 7-ми битный байт адреса должен содержать 7 битов адреса I2C устройства и
R/W бит статуса, который определяет будет ли данные записываться (ведущий передаёт,
ведомый принимает) или читаться (ведомый передаёт, а ведущий читает)
Обратите внимание: В 7-ми битном способе адресации, каждый узел, используя I2C
протокол должен обладать уникальным адресом, который для микроконтроллена
записан в регистре I2CxADD.
Получение подтверждения от ведомого
На заднем фронте восьмого такта линии SCLx, бит TBF сбрасывается и ведущий
отпускает вывод SDAx, разрешая ведомому передать ответ ACK. Ведущий тогда
производит девятый тактовый импульс на линии SCLx.
Это позволяет адресуемому ведомому устройству отвечать битом ACK в течение
девятого тактового импульса, если состояние адреса совпадает, или данные были
получены должным образом. Ведомый посылает ACK, когда признала свой адрес
(включая общий запрос) или когда ведомый должным образом получил данные.
Статус ACK записывается в бит статуса подтверждения ACKSTAT (I2CxSTAT
<15>), во время заднего фронта девятого импульса на выводе SCLx. После девятого
импульса на выводе SCLx, модуль генерирует прерывание MI2CxIF, и шина входит в
режим бездействия, пока следующий байт данных не будет загружен в регистр I2CxTRN.
Флаг статуса ACKSTAT
Флаг статуса ACKSTAT (I2CxSTAT <15>) сброшен, когда ведомый послал
подтверждение (ACK = 0) и устанавливается, когда ведомый НЕ подтвердил (ACK = 1).
Флаг статуса TBF
При передаче, флаг статуса TBF (I2CxSTAT <0>) установлен, когда процессор
записывает регистр I2CXTRN, и сбрасывается, когда все 8 битов переданы.
Флаг статуса IWCOL
Если программное обеспечение пытается записать данные в регистр I2CXTRN,
когда происходит передача (то есть, модуль все еще передаёт байт данных), тогда бит
статуса IWCOL будет установлен и содержимое буфера не изменится (запись не
произойдёт). Бит статуса IWCOL должен быть очищен в программе.
Обратите внимание: поскольку организация очереди событий не позволяется,
запись в регистр I2CxCON младших 5-ти бит может повредить регистр, пока не
завершено состояние передачи
Рисунок 8. Временная диаграмма передачи ведущим.
1 – запись регистра I2CxTRN начинает передачу ведущим. Устанавливается бит TBF.
2 – запускается тактовый генератор скорости обмена. MSB (младший бит) регистра
I2CxTRN устанавливается на линии SDAx. SCLx остается низким. Устанавливается бит
статуса TRSTAT.
3 – Тактовый импульс завершён. SCLx отпускается. Генератор перезагружается.
4 - Тактовый импульс завершён. SCLx переводится в низкое состояние. После
обнаружения на SCLx низкого уровня, следующий бит регистра I2CxTRN передаётся на
линию SDAx.
5 - в то время как на линии SCLx низкий уровень, ведомый может также установить на
линии SCLx низкий уровень, тем самым на шине I2C формируется задержка.
6 – Если ведомому не нужна была задержка, или ведомый больше не нуждается в
задержке, то он также как и ведомый отпускает линию SCLx. После чего перегружается
генератор.
7 – По заднему фронту восьмого тактового импульса на линии SCLx, ведущий отпускает
линию SDAx. Бит TBF очищается. Ведомый даёт ответ или ACK или NACK.
8 – По заднему фронту девятого тактового импульса на линии SCLx, ведущий генерирует
прерывание. SCLx остается в низком уровне до следующей передачи. Ведомый отпускает
SDAx. Сбрасывается бит TRSTAT.
Получение Данных от ведомого устройства
Ведущий может получить данные от ведомого устройства после того, как ведущий
передал адрес ведомого с битом R/W = 1. Разрешается приём RCEN (I2CxCON <3>).
Логика ведущего начинает генерировать тактовые импульсы перед каждым падающем
фронтом SCLx, SDAx линия выбрана, и данные перемещаются в регистр I2CxRSR.
Обратите внимание: 5 младших битов регистра I2CxCON должны быть ‘0’
перед тем как установить бит RCEN. Это гарантирует, что логика ведущего
бездействует.
После заднего фронта восьмого тактового импульса на линии SCLx, происходят
следующие события:
• Бит RCEN автоматически очищается
• содержимое регистра I2CxRSR перемещается в регистр I2CxRCV.
• устанавливается бит статуса RBF.
• модуль генерирует прерывание MI2CxIF.
Когда из программы читается буфер, то автоматически бит RBF сбрасывается.
Программное обеспечение может обработать данные и затем выполнить
последовательность подтверждения.
Флаг статуса RBF
При получении данных устанавливается бит статуса RBF, когда адрес устройства
или байт данных загружены в регистр I2CxRCV из I2CxRSR регистра. Данный бит RBF
сбрасывается, когда программное обеспечение читает регистр I2CxRCV.
Флаг статуса I2COV
Если получен другой байт в регистр I2CxRSR, в то время как бит RBF был
установлен, и предыдущий байт ещё находится в регистре I2CxRCV, то устанавливается
флаг I2COV, и данные в регистре I2CxRSR теряются.
При установленном бите I2COV дальнейший приём не запрещается. Если бит RBF
будет сброшен, путём прочтения регистра I2CxRCV, то регистр I2CxRSR получает тот
байт, который в данное время находится в I2CxRCV.
Флаг статуса IWCOL
Если программное обеспечение записывает регистр I2CxTRN, когда
осуществляется приём (то есть, регистр I2CxRSR всё ещё перемещает байт данных), бит
IWCOL устанавливается и содержание буфера не изменяется (запись не происходит).
Обратите внимание: Так как организация очереди событий не поддерживается,
запись младших пяти битов регистра I2CxCON могут повредить данный регистр, пока
условие приема данных не выполнено.
Рисунок 9. Временная диаграмма приёма ведущим
1 - Как правило, ведомый может притянуть линию SCLx к низкому уровню, чтобы
сформировать задержку для подготовки ответа. Ведомый будет выводить MSB (мл. бит)
ответа данных на линию SDAx когда ответ готов.
2 – Запись бита RCEN запустят событие приёма ведущим. Запускается генератор
скорости. SCLx остается в низком уровне.
3 – Время тактового импульса вышло. Ведущий пытается отпустить SCLx.
4 – Когда ведомый отпускает SCLx, перезапускается генератор скорости.
5 - Время тактового импульса вышло. MSB ответа перемещается в регистр I2CxRSR.
SCLx управляется низким уровнем для следующего импульса.
6 – По задним фронтам восьмых тактов на линии SCLx, регистр I2CxRSR перемещает
данные в регистр I2CxRCV. Модуль очищает бит RCEN. Бит статуса RBF
устанавливается. Ведущий генерирует прерывание.
Генерирование подтверждения
Установление подтверждения активизируется битом ACKEN (I2CxCON <4>),
разрешая генерирования ведущим последовательность подтверждения.
Обратите внимание: необходимо убедиться, что младшие 5 битов регистра I2CxCON
равны 0 (логика ведущего неактивно) перед попыткой установить бит ACKEN.
Рисунок 10 показывает последовательность ACK, а рисунок 11 показывает
последовательность NACK. Бит подтверждения данных, ACKDT (I2CxCON <5>),
определяют ACK или NACK.
После двух периодов генератора скорости, бит ACKEN автоматически очищается, и
модуль генерирует прерывание MI2CxIF.
Флаг статуса IWCOL
Если программное обеспечение записывает регистр I2CxTRN, когда происходит
подтверждающая последовательность, бит статуса IWCOL устанавливается и содержание
буфера не изменяется (запись не происходит).
Обратите внимание: поскольку организация очереди событий не разрешена, запись
младших пяти бит в регистре I2CxCON могут привести к повреждению, если
подтверждение не было завершено.
Рисунок 10. Временная диаграмма подтверждения ведущим (ACK)
1 –Запись ACKDT = 0 определяет передачу ACK. При записи ACKEN = 1 инициируется
подтверждения ведущим. Запускается генератор скорости. SCLx остается низким.
2 - когда обнаруживается низкий уровень на SCLx, модуль подтягивает линию SDAx к
низкому уровню.
3 – Тактовый импульс завершён. Модуль отпускает SCLx. Перезапускает генератор
скорости.
4 – Тактовый импульс завершён. Модуль подтягивает линию SCLx к низкому уровню,
затем отпускает линию SDAx. Модуль очищает бит ACKEN. Ведущий генерирует
прерывание.
Рисунок 11. Временная диаграмма NACK ведущим
1-Запись ACKDT = 1 определяют посылку NACK. При записи ACKEN = 1 инициируется
подтверждения ведущим. Запускается генератор скорости.
2 –когда обнаруживается низкий уровень на линии SCLx, модуль отпускает SDAx.
3 – Тактовый импульс генератора вышел. Модуль отпускает SCLx. Перезапускает
генератор скорости.
4 – Тактовый импульс генератора вышел. Модуль подтягивает линию SCLx к низкому
уровню, затем отпускает линию SDAx . Модуль очищает бит ACKEN. Ведущий
генерирует прерывание.
Генерирование условия Stop на шине
Условие STOP генерируется установлением бита PEN (I2CxCON <2>).
Обратите внимание: младшие 5 битов I2CxCON должны быть ‘0’ (логика ведущего не
активна) перед попыткой установить бит PEN.
Когда бит PEN установлен, ведущий генерирует последовательность STOP как показано
на рисунке 12.
• ведомый обнаруживает условие STOP, устанавливает бит P (I2CxSTAT <4>) и
очищает бит S (I2CxSTAT <3>).
• Бит PEN автоматически очищается
• модуль генерирует прерывание MI2CxIF.
Флаг статуса IWCOL
Если программное обеспечение записывает регистр I2CxTRN, когда происходит
последовательность STOP, то бит статуса IWCOL устанавливается и содержимое буфера
не изменяется (запись не происходит).
Рисунок 12. Временная диаграмма формирования ведущим условия STOP
1 – Запись PEN = 1 инициирует событие STOP ведущим. Запускается генератор скорости.
Модуль подтягивает линию SDAx к низкому уровню.
2 – Тактовый импульс генератора вышел. Модуль отпускает SCLx. Перезапускает
генератор скорости.
3 - Время генератора скорости вышло. Модуль отпускает SDAx.
4 – Логика ведомого обнаруживает условие STOP. Модуль устанавливает биты P = 1 и S =
0.
5 – Тактовый импульс генератора вышел. Модуль очищает бит PEN. Ведущий генерирует
прерывание.
Генерирование условия повторного START
Условие повторного START активизируется битом, RSEN (I2CxCON <1>)
(Рисунок 13)
Обратите внимание: младшие 5 битов I2CxCON должны быть ‘0’ (логика ведущего не
активна) перед попыткой установить бит RSEN.
Чтобы произвести условие повторного START, программное обеспечение должно
установить бит RSEN (I2CxCON <1>). Модуль подтягивает линию SCLx к низкому
уровню. Когда на линии SCLx низкий уровень, модуль отпускает линию SDAx для одного
счёта генератора скорости (TBRG). Когда время генератора скорости выйдет и на линии
SDAx установится высокий уровень, модуль переопределяет линию SCLx. Когда линия
SCLx находится в высоком уровне, происходит перезагрузка генератора скорости и
начинает счёт. Линии SDAx и SCLx должны находиться в высоком уровне в течении
одного TBRG. Это действие тогда сопровождается установлением линии SDAx в низкий
уровень для одного TBRG, в то время как на линии SCLx находится высокий уровень.
Флаг статуса IWCOL
Если программное обеспечение записывает данные в регистр I2CxTRN в то время
когда происходит условие Повторный START, то устанавливается бит IWCOL, а
содержимое буфера не изменяется (запись не происходит).
Обратите внимание: поскольку организация очереди событий не разрешена, запись
младших пяти бит в регистре I2CxCON могут привести к повреждению, если условие
повторного START не завершено.
Рисунок 13. Временная диаграмма повторного START ведущим
1 - Запись RSEN = 1 запускает условие повторного START ведущим. Запускается
генератор скорости. Модуль подтягивает линию SCLx к низкому уровню и отпускает
SDAx.
2 – Тактовый импульс генератор вышел. Модуль отпускает SCLx. Перезапускает
генератор скорости.
3 - Тактовый импульс генератор вышел. Модуль подтягивает линию SDAx к низкому
уровню. Перезапускает генератор скорости.
4 - Логика ведомого обнаруживает START. Модуль устанавливает S = 1 и P = 0.
5 - Тактовый импульс генератор вышел. Модуль подтягивает линию SCLx к низкому
уровню. Модуль очищает бит RSEN. Ведущий генерирует прерывание.
Создание полного сообщения ведущим
Как уже было отмечено ранее, программа должна осуществлять создание всего
сообщения, используя элементарные функции предоставляемые аппаратными средствами.
Программное обеспечение может использовать опрос или методы прерывания при
использовании модуля. Примеры показывают использование прерывания.
Программное обеспечение может использовать биты SEN, RSEN, PEN, RCEN, и
ACKEN (младшие 5 битов регистра I2CxCON) и бита статуса TRSTAT. Например,
таблица 2 показывает различные режимы шины и их соответствующие значения для
регистра управления.
Таблица 2. Состояния протокола сообщения ведущего
Пример
значения
состояния
0
1
2
3
4
5
6
I2CxCON<4:0>
TRSTAT
Состояние
(I2CxSTAT<14>)
00000
00001
00000
00010
00100
01000
10000
0
N/A
1
N/A
N/A
N/A
N/A
Шина бездействует либо в режиме задержки
Отправка условия START
Ведущий передаёт
Отправка повторного START
Отправка условия STOP
Ведущий принимает
Ведущий подтверждает
Программное обеспечение начинает сообщение, выдавая команду START.
Поскольку каждое условие завершается генерированием прерывания, то в прерывании
можно проверить значение состояния. Так, для значения состояния START, управление
прерыванием подтвердит выполнения последовательности START, после чего ведущий
начнёт передачу, чтобы послать адрес I2C устройства, далее изменяем значение
состояния, чтобы выполнить передачу ведущим.
На следующем прерывании, при обработке прерывания снова проверить значение
состояния, определяя, что ведущий закончил передачу. После подтверждения успешной
передачи данных, нужно будет выполнять следующее условия в зависимости от
содержания сообщения. В такой же манере, на каждом прерывании в обработчике
прерывания будет отрабатываться весь протокол сообщения, пока не будет послано всё
сообщение.
Рисунок 14 показывает более детальную схему той же самой последовательности
сообщения что и на рисунке 6. Рисунок 15 показывает некоторые простые примеры
сообщений, используя 7-ми битовый формат адресации. Рисунок 16 показывает пример
сообщений отправки данных ведущим с 10-ти битовым форматом адресации. Рисунок 17
показывает пример 10-ти битной адресации при приёме ведущим данных от ведомого.
Рисунок 14.
EEPROM)
Сообщение ведущего (Типичное I2C сообщение: Чтение памяти
1 – Установка бита SEN начинает формирования условия START.
2 - Запись данных в регистр I2CxTRN начинают передачу ведущим. Данными является
байт адреса EEPROM устройства, с битом R/W=0, что значит, что ведущий будет
передавать данные.
3 – Запись данных в регистр I2CxTRN начинают передачу данных ведущим. Данными
является первый байт адреса ячейки EEPROM.
4 – Запись данных в регистр I2CxTRN начинают передачу данных ведущим. Данными
является второй байт адреса ячейки EEPROM.
5. Установка бита RSEN запускает условие повторного START.
6 - Запись в регистр I2CxTRN начинают передачу данных ведущим. Данными является
байт адреса EEPROM устройства, но уже с R/W=1, указывая на то, что ведущий будет
принимать данные от ведомого.
7 – Установим бит RCEN начинает приём данных ведущим. Во время прерывания,
программой необходимо прочитать регистр I2CxRCV, что в свою очередь приведёт с
сбросу флага RBF.
8 – Установка бита ACKEN выполняет подтверждение или установить ACKDT = 1, чтобы
послать NACK.
9 – Установка бита PEN запускает формирование условия STOP.
Рисунок 15. Сообщение ведущего (7-ми битная адресация: Передача и приём)
1 - Установка бита SEN начинает формирования условия START.
2 – Запись данных в регистр I2CxTRN начинает передачу ведущим. Данными является
байт адреса с битом R/W=0.
3 – Запись данных в регистр I2CxTRN начинает передачу ведущим. Данными является
байт сообщения.
4 – Установка бита PEN начинает формировать условие STOP.
5 – Установка бита SEN начинает условия START.
6 - запись данных в регистр I2CxTRN начинает передачу ведущим. Данными является
байт адреса с битом R/W=1.
7 – Установка бита RCEN начинает приём ведущим.
8 – Установка бита ACKEN формирует условие подтверждения. Если нужно послать
NACK, то устанавливаем бит ACKDT = 1.
9 – Установка бита PEN начинает формирование условия STOP.
7.5. Работа модуля I2C на примере
Ну наконец-то после сложного теоретического введения мы добрались до примера.
Поставим следующую задачу для данного примера: необходимо, чтобы двигатель
вращался в одном направлении 5 секунд, затем в противоположном направлении также 5
секунд. Для таких целей в микроконтроллере есть таймер, однако данную задачу мы
решим другим способом, с помощью часов реального времени. Благо в PROTEUS есть
такие элементы. Так как в данной статье рассматривается протокол I2C, то и часы
реального времени мы выберем для работы по протоколу I2C. Нам необходимо
подключить часы реального времени к микроконтроллеру по правилам шины I2C, т.е.
использовать подтягивающие резисторы на линиях. Следует обратить внимание, что в
микроконтроллере, имеющемся в PROTEUS, линии интерфейса I2C жёстко определены.
Это выводы SDA и SCL. Другими словами мы уже не сможем, как делали это ранее,
настраивать данные входы на любой вывод, поддерживающий периферию.
Дополнительно подключаем к шине и специальный монитор за шиной I2C, чтобы можно
было видеть, какие действия происходят на шине. Также нам потребуется
электродвигатель. Мы его подключим непосредственно к выводам микроконтроллера (к
счастью в PROTEUS это можно делать ).
Теперь пару слов о самих часах реального времени, точнее как с ними связаться по
шине I2C. Протокол требует, чтобы у каждого ведомого устройства на шине был свой
уникальный 7-ми битный адрес. Так вот у часов, которые у нас будут использоваться,
адрес соответствует в двоичной системе 1101000. В программе мы будем к часам
обращаться, используя адрес 0xD0 и 0xD1, т.е. 7-ми битный адрес, а нулевой бит, является
признаком записи или чтения (как указано в протоколе). Вся остальная работа с часами
соответствует протоколу шины I2C. А для большей информации, необходимо на данное
устройства прочитать даташит. В даташите описано как работать с конкретным
устройством.
Теперь для примера опишем как происходит получение данных из часов. Сначала
микроконтроллер формирует условие START, после отправляет адрес часов (0xD0). Когда
придёт подтверждение, то микроконтроллер должен отправить адрес первого байта
данных, который нужно будет прочитать. К примеру, если нам необходимо получить
значение секунд, то необходимо отправить адрес данных равный 0x00. По этому адресу в
часиках находятся секунды. После подтверждения можно начинать принимать данные,
для этого контроллер формирует условие повторного старта и начинает принимать
данные. Уже контроллер должен подтверждать приём данных. Когда микроконтроллеру
больше не нужны будут данные он вместо подтверждения ACK должен отправить NACK.
А затем сформировать условие STOP.
Ниже приведена схема в PROTEUS (в рабочем состоянии)
#include "p33Fxxxx.h"
#include <i2c.h> // функции для работы с I2C
// Устанавливаем биты настройки генератора (HS)
_FOSCSEL(0x02);
_FOSC(0xE2);
//объявляем структуру, для хранения времени и даты
union Time_
{ struct
{
unsigned char
Sec;
// секунды
unsigned char
Min;
// минуты
unsigned char
Hour;
// часы
unsigned char
Day;
unsigned char
Month;
unsigned char
Year;
};
unsigned char array[6];
};
typedef union Time_ Times;
// создаём новый тип данных (тип время)
Times TimeNow={0x55,0x20,0x13,0x17,0x11,0x09};
void init (void);
// Задаём начальное время
//объявляем подпрограмму инициализации
// ********** подпрограмма инициализация **********
void init (void)
{ AD1PCFGL=0xffff; // все выводы как цифровые I/O
PORTB=0;
LATB=0;
TRISB=0x0000;
//устанавливаем все выводы на выход
PORTB=0x0;
}
// ************ Точка входа в программу *************************
void main (void)
{
Times tempTime;
// объявляем переменную, типа Times
unsigned long int i;
// переменная для цикла (задержки)
unsigned char ctemp;
// вспомогательная переменная для расчёта
init();
I2C_RTC_Init(400000);
SetTime (&TimeNow);
SetDate (&TimeNow);
// вызываем подпрограмму общей инициализации
// инициализируем модуль I2C для работы с RTC
// процедуры для работы с временем находится в
// присоединённом к проекту файлу RTC.c
// устанавливаем время
// устанавливаем дату
while(1)
// запускаем бесконечный цикл
{
for (i=0;i<100000;i++)
// включаем задержку, чтобы не часто
{
// нужно было делать запросы к часам
ClrWdt();
// сбрасываем сторожевой таймер
Nop();
// пропускаем такт контроллера
}
GetTime (&tempTime);
// получаем текущее время
// следующие две команды определяют в каком диапазоне находятся
сtemp = (tempTime.Sec & 0x0F) / 5;
// единицы секунд
ctemp = ctemp % 2;
// 1 - 1..5, 0 - 6..10(0)
if (ctemp)
// в зависимости от диапазона времени
{ _RB15=0; _RB14=1;
// выбираем направления движения двигателя
}
else
{ _RB14=0; _RB15=1;
}
//GetDate(&tempTime);// получить дату. В данной программе не используется
} // while(1)
}
Ниже приведён код обработки некоторых процедур, расположенных в файле RTC.c,
вызываемых из главной программы.
void I2C_RTC_Init (unsigned long baudrate)
{ unsigned int brg = ((FCY)/baudrate - ((FCY)/10000000UL))-1; // данная формула из даташита
/* процедура OpenI2C1 описана в библиотеке microchip, который приведён в файле I2C.h, I2C.c, а
все названия передающиеся в эту функцию описаны в файле p33FJ32GP204.h */
OpenI2C1 (I2C1_ON &
// включить модуль I2C
I2C1_IDLE_STOP &
// останавливаться в Idle режиме
I2C1_CLK_REL &
I2C1_IPMI_DIS &
I2C1_7BIT_ADD &
// адресация 7-ми битная
I2C1_SLW_DIS &
I2C1_SM_DIS &
I2C1_GCALL_DIS & I2C1_STR_DIS &
I2C1_NACK & I2C1_ACK_DIS &
I2C1_RCV_DIS & I2C1_STOP_DIS &
I2C1_RESTART_DIS &
I2C1_START_DIS , brg);
}
// ********* получить значение времени с RTC часов **************
void GetTime (unsigned char *SecMinHour)
{ IdleI2C1();
// проверяем, свободна ли шина
Start();
// выполняем условие START
SendByteI2C(SLAVE_ADDR);
// выдаём в шину адрес часов RTC
SendByteI2C(0);
// устанавливаем указатель в часах на секунды
Restart();
// выполняем условие повторного START
SendByteI2C(SLAVE_ADDR | 1); // выдаем в шину адрес часов, установив при этом бит R|W=1
(*SecMinHour++)=ReadByteI2C();
// читаем значение секунд из часов
ACK_I2C();
// подтверждаем приём
(*SecMinHour++)=ReadByteI2C();
// читаем значение минут из часов
ACK_I2C();
// подтверждаем приём
(*SecMinHour++)=ReadByteI2C();
// читаем значение часов из часов RTC
NACK_I2C();
// просим передать контроль управления шиной ведущему
Stop();
// выдаём последовательность STOP
}
Данная программа состоит аж из трёх файлов. Один файл главный, который
содержит точку входа в программу. Второй файл содержит функции для
работы с часами реального времени. А третий файл мы позаимствовали у
Microchip, т.е. файл для работы с модулем I2C. Так что приведенная выше
программа не полная. Для дополнительной информации смотрите
прилагаемые к данной теме файлы. Кстати, там также можно будет найти
черновой перевод даташита на часы реального времени, которые мы
использовали в примере.
Мотькин Игорь Сергеевич,
Республика Беларусь, г. Гомель,
+375 (29) 736-67-41
motskin@tut.by
Download