Статья №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  настоящей  статьи.  
 
Рис.2 - Блок-схема  программы Termometr
 
Текст  программы  с  подробными  комментариями  приведён  ниже. Программа  состоит  из  цикла  (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