Статья №7
В настоящее время бытовая техника сделала резкий скачёк в сторону усложнения схемотехники. Число микросхем в устройствах увеличивается, что приводит к уплотнению и запутанности печатного монтажа. Исходя из вышеизложенной ситуации компания Philips решила вместо широких параллельных шин использовать всего два проводника. Один провод в такой шине отвечает за данные (SDA), а по другому идут тактовые импульсы (SCL).
Данную разработку Philips начала ещё в 80 – х годах прошлого столетия. IIC (I2C) - это сокращение от Inter – IC. C 1992 года I2C стандарт использует семибитные адреса, что позволяет подключать одновременно к одной шине до 128 интегральных микросхем.
Изначально стандарт I2C работал с тактовой частотой до 100 КГц. В 1992 году был добавлен «Быстрый режим» с максимальной частотой 400 КГц. В этом же варианте была реализована 10 – битная адресация. В 1998 году был разработан «Высокоскоростной режим» с максимальной скоростью 3,4 Мбит/с. Следует отметить, что «Быстрый» и «Высокоскоростной режимы» одинаково хорошо работают и с частотой 100 КГц.
Большинство микроконтроллеров AVR обладают двухпроводным интерфейсом. Он называется двухпроводный канал USI. Видимо это терминология применяется из – за нежелания платить фирме Philips за то, чем все и так бесплатно пользуются.
Стандарт I2C предусматривает подтягивающие резисторы на SDA и SCL, величина которых 10 КОм. Иногда можно встретить резисторы 100 – 300 Ом. Это делается для уменьшения взаимного влияния шин. Длина шины I2C не ограничена. Единственное, что общая ёмкость линии с подключёнными устройствами не должна превышать 400 пФ.
Устройство, начинающее передачу передачу, называется Ведущим - Master (мастер). Устройство, к которому обращается Master, называется Ведомым – Slave (раб). Ведомое устройство молчит всегда, пока его не спросит Master. Тактовые импульсы на SCL также обеспечивает Ведущее устройство. Master отвечает за временные интервалы в передаче, если Slave должно вернуть какие – то значения. Ведущее устройство отвечает также за все временные интервалы.
I2C позволяет организовать работу нескольких ведущих устройств на одной шине, однако во всех наших примерах будет рассмотрена работа только одного Master и одного или нескольких Slave.
Команды чтения и записи I2C работают с одним байтом за раз. Приведём пример стандартной процедуры записи в Slave:
I2cstart
I2cwbyte Adressbyte
I2cwbyte Databyte
I2cwbyte . . . . . . . .
I2cstop
Команда I2cstart производит сброс линии SDA и заставляет все устройства Slave внимательно слушать. Затем отправляется адрес интересующей нас микросхемы. Она начинает обмен (все остальные Slave в это время молчат). Далее с помощью команды I2cwbyte отправляются один или несколько байтов. Приём каждого байта подтверждается микросхемой Slave. Команда I2cstop освобождает линию.
Приведём пример стандартной процедуры чтения из Slave:
I2cstart
I2cwbyte Adressbyte
I2crbyte Tempbyte, Ack
I2cbyte Lowbyte, Nack
I2cstop
Как и в первом случае команда I2cstart сбрасывает линию и заставляет все Slave cлушать. Затем передаётся адрес нужной микросхемы Slave. Далее с помощью команды I2crbyte принимаются один или несколько байтов. После переменной ставится ключевое слово. Ack сообщает, что нужно считать ещё один байт, Nack – что этот принятый байт был последним.
Конфигурирование выводов микроконтроллера в Bascom для I2C происходит следующим образом, например для ATtiny2313:
Config SDA = PORTB.5
Config SCL = PORTB.7
Bascom использует стандартную частоту обмена для I2C 200 КГц. Однако применяя конфигурирование параметра I2cdelay можно задать другую частоту, например:
Config I2cdelay = 10
Этот код задаст частоту 100 КГц, 5 – 200 КГц (по умолчанию), 2 – 500 КГц, 1 – 1МГц.
Следует отметить, что после команд PORTx или после изменения направления input/output на выводах SDL и SDA могут оказаться непредсказуемые уровни, поэтому, чтобы перед началом или продолжением обмена установить на них низкий уровень необходимо применить команду I2cinit.
Рассмотрим применение Bascom для программирования работы устройств, работающих по I2C на примере температурного датчика Lm76. Данный датчик измеряет температуру с точностью до 0,065 град.С. Он имеет линейную характеристику в диапазоне от - 30 до +50 град.С.
Температура хранится как 16 – битное слово и считывается, как два байта. Регистр, из которого нужно читать температуру, выбирается по умолчанию при включении питания.
D0 – D2 не определены. D15 – cодержит бит знака. Само значение температуры лежит в D3 – D14. Температура хранится в обычном двоичном представлении. Положительные числа хранятся как есть, с битом знака равным 0.
Отрицательные числа имеют в бите знака 1. Сам модуль числа записан в инвертированном виде и увеличен на 1.
При считывании положительных температур нужно просто считать D3 – D14 как два байта, призвести их объединение и сдвинуть на три байта вправо.
При считывании отрицательных значений температур необходимо считать два байта, объединить их, затем инвертировать все биты, убрав тем самым бит знака. Далее нужно увеличить результат на 1 и сдвинуть полученное значение вправо на три байта.
Allbyte = Makeint (lowbyte, Highbyte) ‘объединение считанных байтов
Znakbyte = Highbyte * &B10000000 'выделение знака температуры
If Znakbyte=&B10000000 Then ‘знак = 1 (-)?
Allbyte = Not Allbyte ‘ инвертирование
Allbyte = Allbyte + 1 ‘ увеличение на единицу
End If
Shift Allbyte, Righ, 3 ‘ сдвиг вправо на три бита
Принципиальная схема устройства представлена Рис.1. Она состоит из микроконтроллера ATtiny2313 и подключёнными к нему датчика температуры Lm76 и ЖКИ типа MT – 16S2H фирмы - призводителя МЭЛТ. Следует отметить, что индикатор подключен по другим контактам, чем те, которые установлены в Bascom по умолчанию.
Блок – схема программы “Termometr” представлена на Рис.2. Программа находится в приложении 1 настоящей статьи.
Текст программы с подробными комментариями приведён ниже. Программа состоит из цикла (DO…LOOP), в котором по I2C с датчика температуры считываются значения старшего (Highbyte) и младшего (Lowbyte) байтов. Далее происходит их объединение (Allbyte), выделение знака и операции, которые описаны выше. Значение температуры получается путём умножения значения полученного модуля (Allbyte) на температурный коэффициент датчика Lm76 и выводится на ЖКИ. В конце цикла происходит ещё одна идентификация знака, в результате которой на дисплей выводится «+» или «-».
Программа “Termometr”:
$regfile = "attiny2313a.dat" 'настройки
$crystal = 4000000
$hwstack = 40
$swstack = 16
$framesize = 32
Config Sda = Portb.5 'конфигурация портов I2c
Config Scl = Portb.7
Config I2cdelay = 10 'тактовая частота I2c=100 КГц
Const Lm76 Write = &H90 'байт управления записью
Const Lm76 Read = &H91 'байт управления чтением
Const Lm76resolution = 0.0625 'температурный коэффициент Lm76
Dim Temperature As Single 'объявление переменных
Dim Allbyte As Word
Dim Lowbyte As Byte
Dim Highbyte As Byte
Dim Znakbyte As Byte
Do
Wait 1 'задержка=1с
Cls 'очистка дисплея
I2cstart 'включение I2c
I2cwbyte Lm76 Read 'команда- чтение
I2crbyte Highbyte , Ack 'считывание старшего байта '
I2crbyte Lowbyte , Nack 'считывание младшего байта
I2cstop 'выключение I2c
Allbyte = Makeint(lowbyte , Highbyte) 'объeдинение в 16 бит.переменную
Znakbyte = Highbyte And 128 'выделение знака
If Znakbyte = 128 Then 'определение знака
Allbyte = Not Allbyte 'если 1 ("-"),то инвертировать
Allbyte = Allbyte + 1 'и добавить 1
End If
Shift Allbyte , Right , 3 'сдвиг вправо на 3 знака
Temperature = Allbyte * Lm76resolution 'определение температуры
Lcd "T=" ; Temperature 'вывод на ЖКИ
If Znakbyte = 128 Then 'определение знака для вывода на ЖКИ
Lcd "-"
Else
Lcd "+"
End If
Wait 1
Loop
End 'end program