Статья №9


     Прежде, чем  познакомить  вас  с  ещё  одним  примером  использования  шины  I2C, к  которой подключены  несколько  ведомых  устройств  (SLAVE), я  должен  описать  работу  с  подпрограммами, поскольку  код  без  применения  подпрограмм  в  подобных  случаях  будет  очень  длинным  в  силу  многократного  повторения  некоторых  его  фрагментов.
     Например, при  подключении  четырёх  SLAVE  к  I2C  обращение  к  ним  и  считывание  данных  будет  иметь  место,  по  крайней  мере,  четыре  раза:
 
I2cstart                                                                                                                                                                         
I2cwbyte  Adress1 ‘запрос  первого  устройства                                                                                             
I2crbyte  Date1, Nack ‘cчитывание  данных  первого  устройства                                                               
I2cstop                                                                                                                                                                         
Print “Date1=” ; Date1
. . . . . . . . .
I2cstart                                                                                                                                                                        
I2cwbyte  Adress4                                                                                                                                                      
I2crbyte  Date4, Nack                                                                                                                                               
I2cstop                                                                                                                                                                         
Print “Data4=” ; Date4
 
     Когда  используется  много  подобных  повторяющихся  фрагментов  и  потребуется  изменить  код, вам  придётся  изменять  код  в  каждом  из  них, что  может  привести  к  ошибкам  и  долгим  поискам  этих  ошибок.
     В  связи  с  вышесказанным  отметим, что  преимущество  применения  подпрограммы  в  том, что  повторяющиеся  фрагменты  кода  используются  в  программе  только  один  раз.                                                                                                                                                   
     Подпрограмму  можно  вызвать  из  любого  места  программы. После  выполнения  подпрограммы  основная  программа  продолжает  свою  работу  с  того  же  самого  места.
     Приведём  пример  написания  подпрограммы  для  вышеприведённого  случая:
 
' описание  подпрограммы                                                                                                                                    
Declare  Sub  Dateread (Byval  Adress  As  Byte, Date As  Byte)
‘ основная  программа                                                                                                                                            
Adress = Adress1                          ‘задание  адреса  первого  устройства                                                                           
Call  Dateread (Adress, Date)     ‘ вызов  подпрограммы                                                                               
Date1 = Date                                                                                                                                                              
Print “Data1 =” ; Date1
. . . . . . . . . . . . . . .
Adress = Adress4                          ‘задание  адреса  четвёртого  устройства                                                                           
Call  Dateread (Adress, Date)      ‘ вызов  подпрограммы                                                                                
Date4 = Date                                                                                                                                                              
Print “Data4 =” ; Date4
‘ подпрограмма
Sub  Dateread (Byval  Adress  As  Byte, Date  As  Byte)                                                                                      
I2cstart                                                                                                                                                
I2cwbyte  Adress                                                                                                                                                         
I2crbyte  Date, Nack                                                                                                                                                 
I2cstop                                                                                                                                                                         
End  Sub               ‘выход  из  подпрограммы
 
     Команда  Byval  указывает  подпрограмме, что  заданные  ей  параметры  должны  остаться  неизменными. В  этом  случае  Bascom  создаёт  в  памяти  копию  переменной  и  будет  работать  с  ней. Исходная  переменная  останется  неизменной, чтобы  с  ней  не  происходило  в  подпрограмме. В  описанном  выше  примере  с  переменной  Adress  ничего  не  происходит , поэтому  здесь  Byval  можно  не  применять, если  переменная  описана  в  начале  программы.
     В  связи  с  этим  следует  подчеркнуть, что  все  переменные  и  подпрограммы  должны  быть  описаны  в  начале  программы.
     На  Рис.1  представлена  схема  подключения  четырёх  температурных  датчиков  типа  Lm76  к  шине  I2C  микроконтроллера  ATtiny2313. Контроллер  опрашивает  последовательно  каждый  из  датчиков. Полученные  значения  температуры  отображаются  на  ЖК  дисплее  типа  MT-16S2H  и  с  помощью  UART  через  преобразователь  уровня  МАХ3232  и  разъём  DB9-F  по  протоколу  RS-232  передаются  в  порт  персонального  компьютера. Более  подробно  работа  всех  элементов  схемы  была  описана  ранее  в  предыдущих  статьях  по  Bascom.
 
 
 
 
   Как  видно  из  схемы  датчик  Lm76  имеет  два  бита  адреса  А0  и  А1, которые  можно  задать  аппаратурно.  Манипулируя  подключением  данных  контактов  к  шине  питания  и  земле, можно  получить  следующие  адреса  датчика  (для считывания):
 
№1 – 10010001  при  А0 = 0, А1 = 0                                                                                                                    
№2 – 10010011  при  А0 = 1, А1 = 0                                                                                                                     
№3 – 10010101  при  А0 = 0, А1 = 1                                                                                                                   
№4 – 10010111  при  А0 = 1, А1 = 1.
 
      Подробно  датчик  Lm76  описан  в  статье  по  Bascom  №7.
      На  Рис.2  представлена  блок – схема  программы  “Termometr4”. Программа  состоит  из  основного  цикла, в  котором  происходит  опрос  датчиков  с  помощью  периодического  вызова  подпрограммы, отображения значений  температуры  на  ЖКИ  и передаче  этих  значений  в  терминал. В  самой  подпрограмме  происходит  считывание  по  I2C  значения  температуры  датчика  и  его  обработка  ( более  подробное  описание  см. статью  по  Bascom №7). 
 
 
Рис.2 - Блок-схема программы "Termometr4"
 
 
  Текст  программы  приведён  ниже.  Сама  программа  находится  в  приложение 1  этой  статьи.

                 Программа  “Termometr4”:

$regfile = "attiny2313a.dat"       'настройки
$crystal = 4000000
$hwstack = 40
$swstack = 16
$framesize = 32

Config Scl = Portb.7               'конфигурация шины I2C
Config Sda = Portb.5
Config I2cdelay = 10               'частота 100 КГц

Const Tadress1 = &B10010001        'адреса термометров Lm76
Const Tadress2 = &B10010011
Const Tadress3 = &B10010101
Const Tadress4 = &B10010111
Const Lm76resolution = 0.0625      'температурный коэффициент

Config Pind.1 = Output             'конфигурация вывода TxD

Dim T1 As Single                   'объявление переменных
Dim T2 As Single
Dim T3 As Single
Dim T4 As Single
Dim Highbyte As Byte
Dim Lowbyte As Byte
Dim Allbyte As Word
Dim Znak As Byte
Dim Tadress As Byte
Dim Tchannel As Single

Declare Sub Temp(byval Tadress As Byte , Tchannel As Single)       'определение подпрограммы

Do                                 'основная программа
  Tadress = Tadress1               'считывание температуры с первого термометра
  Call Temp(tadress , Tchannel)    'вызов подпрограммы считывания знач. температуры
  T1 = Tchannel
  Print "T1=" ; T1                 'передача знач. температуры в терминал по RS-232
  Lcd "T1=" ; T1                   'отражение знач.температуры на ЖКИ
  Wait 1                           'задержка 1 сек

  Tadress = Tadress2               'cчитывание знач.температуры со второго термометра
  Call Temp(tadress , Tchannel)
  T2 = Tchannel
  Print "T2=" ; T2
  Lcd "T2=" ; T2
  Wait 1

  Tadress = Tadress3               'считывание знач. температуры с третьего термометра
  Call Temp(tadress , Tchannel)
  T3 = Tchannel
  Print "T3=" ; T3
  Lcd "T3=" ; T3
  Wait 1

  Tadress = Tadress4               'считывание знач. температуры с четвёртого термометра
  Call Temp(tadress , Tchannel)
  T4 = Tchannel
  Print "T4=" ; T4
  Lcd "T4=" ; T4
  Wait 1
Loop

Sub Temp(byval Tadress As Byte , Tchannel As Single)       'подпрограмма считывания  температуры
I2cstart                           'включение I2C
I2cwbyte Tadress                   'посылка адреса термометра
I2crbyte Highbyte , Ack            'cчитывание старшего байта
I2crbyte Lowbyte , Nack            'считывание младшего байта
I2cstop                            'выключение I2C

Allbyte = Makeint(lowbyte , Highbyte)       'объединение байтов
Znak = Highbyte And 128      ’ выделение  знака
Cls
If Znak = 128 Then                 'если знак=1 ("-")
Allbyte = Not Allbyte              'то инвертирование модуля температуры
Allbyte = Allbyte + 1              'и увеличение на единицу
Print "-"
Lcd "-"
Else
Print "+"
Lcd "+"
End If
Shift Allbyte , Right , 3          'сдвиг вправо на три бита
Tchannel = Allbyte * Lm76resolution       'определение реальной температуры
End Sub

End                                'end program

     Результаты  симулирования  программы  показаны  на  Рис.3. 
 
Рис. 3