Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Исходники » Библиотека для аппартаного модуля 1Wire на основе USART


Библиотека для аппартаного модуля 1Wire на основе USART

Сообщений 1 страница 4 из 4

1

В AVR нет специализированного аппаратного модуля 1Wire из-за чего обычно используют его программную эмуляцию, что не всегда приемлемо, например при множестве различных прерываний, длительность временных интервалов будет больше чем должна быть и это может привести к нестабильной работе с 1Wire устройствами.
Тем не менее, во многих моделях AVR контроллеров есть аппаратный модуль USART, который с успехом может заменить модуль 1Wire. Не скажу что эта идея нова. В интернете, да и в печатной литературе можно встретить различные реализации 1Wire на основе USART, для микроконтроллеров и компьютера. Есть и для Bascom. Исследование Ds18b20 (датчик температуры)
Я же написал свой вариант библиотеки. В ней функций не много. Их три - сброс, чтение и запись, но их достаточно в большинстве случаев.

1wire_reset  ' Сброс. Аналогична команде 1WRESET.
1wire_read  ' Чтение. Аналогична команде 1WREAD.
1wire_write  ' Запись. Аналогична команде 1WWRITE.


Библиотека.

Код:
$nocompile

Declare Sub 1wire_reset()
Declare Sub 1wire_write(byval Var As Byte)
Declare Function 1wire_writebyte(byval Var As Byte) As Byte
Declare Function 1wire_read() As Byte
Declare Function 1wire_err() As Byte

Const 1wire_9600 = _xtal /(9600 * 16) - 1
Const 1wire_115200 = _xtal /(115200 * 16) - 1

Dim 1wire_byte As Byte
Dim 1wire_errcode As Byte
Dim 1wire_i As Byte

Goto 1wire_usart

Function 1wire_err() As Byte
  1wire_err = 1wire_errcode
End Function

Sub 1wire_reset()
    Ubrr = 1wire_9600
   'Baud = 9600
   'Ucsr0a.1 = 0
   Gosub 1wire_clear_in_buff                      ' Очистка буфера приема.
   1wire_errcode = 0

   Printbin &HF0                                  ' Запить данныы в передачик USART.
   1wire_byte = 20
   While 1wire_byte > 0
     Waitus 250
     Decr 1wire_byte

     If Ucsr0a.7 = 1 Then

       Inputbin 1wire_byte
       If 1wire_byte = &HF0 Then
         1wire_byte = 0
       Else
         1wire_byte = 1
       End If

       Exit While
     End If
   Wend
   Ubrr = 1wire_115200
   'Baud = 115200
   'Ucsr0a.1 = 0
   Toggle 1wire_byte.0

   1wire_errcode = 1wire_byte
End Sub

Function 1wire_writebyte(byval Var As Byte) As Byte

   For 1wire_i = 0 To 7

      If Var.0 = 1 Then
        Printbin &HFF
      Else
        Printbin &H00
      End If

      1wire_byte = 200
      While 1wire_byte > 0
        Waitus 50
        Decr 1wire_byte
        If Ucsr0a.7 = 1 Then
          Inputbin 1wire_byte
          Exit While
        End If
      Wend

      If 1wire_byte = &HFF Then
        Var.0 = 1
      Else
        Var.0 = 0
      End If

      Rotate Var , Right , 1

   Next

   1wire_writebyte = Var
End Function


Function 1wire_read() As Byte
  Gosub 1wire_clear_in_buff                       ' Очистка буфера приема.

  1wire_errcode = 0
  1wire_byte = 1wire_writebyte(&Hff)
  1wire_read = 1wire_byte
End Function


Sub 1wire_write(byval Var As Byte)
  Gosub 1wire_clear_in_buff                       ' Очистка буфера приема.
  1wire_errcode = 0
  1wire_byte = 1wire_writebyte(var)
End Sub


1wire_clear_in_buff:                              ' Очистка буфера приема.
  While Ucsr0a.7 = 1
   Inputbin 1wire_byte
  Wend
Return

1wire_usart:

Пример использования.

Код:
$regfile = "m8def.dat"                            ' Выбор типа контроллера.
$crystal = 12000000                               ' Частота генератора, Гц.
$hwstack = 128                                    ' Размер аппаратного.
$swstack = 64                                     ' и программных стеков.
$framesize = 64

$baud = 9600

Declare Sub Termo_to_ind()

Config Portb = Output
Config Portc = Output

Dim I_dinamindex As Byte
Dim I_temp As Byte
Dim Temp As Byte
Dim Dinaminfo(4) As Byte
Dim 1wire_array(9) As Byte                        ' Объявление массивов
Dim Currenttermo As Integer At 1wire_array Overlay
Dim Termo_out_buff As Integer
Dim Temp_i As Integer
Dim 1w_err As Byte                                ' Принзнак ошибки 1wire

$include "1Wire_Usart.bas"

Portc = 0
For Temp = 1 To 4
 Dinaminfo(temp) = 10
Next Temp


Config Timer0 = Timer , Prescale = 256            ' Конфигурация таймера Timer1.
On Timer0 Dinam                                   ' Назначение подпрограммы прерываний от Timer1
Enable Timer0                                     ' Разрешение прерываний от Timer1

Enable Interrupts

Do
   Gosub Gettermo
   Call Termo_to_ind()
Loop
End


Dinam:
 Incr I_dinamindex
 If I_dinamindex > 4 Then I_dinamindex = 1

 I_temp = Dinaminfo(i_dinamindex)

 Portc = 0
 Portb = Lookup(i_temp , Ind)
 If I_dinamindex = 2 Then Portb.7 = 0
 I_temp = 1
 Decr I_dinamindex
 Shift I_temp , Left , I_dinamindex
 Incr I_dinamindex

 Portc = I_temp

Return



Gettermo:
   1w_err = 0
   1wire_reset                                    ' Сброс датчика.
   1w_err = 1wire_err()
   If 1w_err = 0 Then
     1wire_write &HCC                             ' Команда "Skip ROM".
     1wire_write &H44                             ' Команда "Convert  T".
     Waitms 800

     1wire_reset                                  ' Сброс датчика.
     1w_err = 1wire_err()
     If 1w_err = 0 Then
       1wire_write &HCC                           ' Команда "Skip ROM"
       1wire_write &HBE

       For Temp = 1 To 9
         1wire_array(temp) = 1wire_read()
       Next

       If 1wire_array(9) = Crc8(1wire_array(1) , 8) Then
          Currenttermo = Currenttermo * 10
          Shift Currenttermo , Right , 4 , Signed
       Else
         1w_err = 1
       End If

     End If

   Else
     Waitms 400
   End If
Return


Sub Termo_to_ind()
  Stop Timer0
   If 1w_err = 0 Then

      Termo_out_buff = Currenttermo

      If 1wire_array(2).7 = 1 Then
        Toggle Termo_out_buff
        Incr Termo_out_buff
      End If

      Dinaminfo(3) = 11
      Dinaminfo(4) = 11

      For Temp = 1 To 4
        Temp_i = Termo_out_buff Mod 10
        If Termo_out_buff > 0 Or Temp <= 2 Then
          Dinaminfo(temp) = Low(temp_i)
        Else
          If 1wire_array(2).7 = 1 Then
            Dinaminfo(temp) = 10
          End If
          Exit For
        End If
        Termo_out_buff = Termo_out_buff / 10
      Next

   Else
      Dinaminfo(4) = 12
      Dinaminfo(3) = 13
      Dinaminfo(2) = 14
      Dinaminfo(1) = 13
   End If
 Start Timer0
End Sub

Ind:
Data &B11000000                                   ' 0
Data &B11111001                                   ' 1
Data &B10100100                                   ' 2
Data &B10110000                                   ' 3
Data &B10011001                                   ' 4
Data &B10010010                                   ' 5
Data &B10000010                                   ' 6
Data &B11111000                                   ' 7
Data &B10000000                                   ' 8
Data &B10010000                                   ' 9
Data &B10111111                                   ' -
Data &B11111111                                   ' Пусто
Data &B10000110                                   ' E
Data &B10101111                                   ' r
Data &B10100011                                   ' o

Файлы. http://pure-basic.narod.ru/forum_files/ … _Usart.zip

Хочу обратить внимание на код смены скорости в 1wire_reset. В протеусе нормально работает вариант с прямой записью в регистр Ubrr. Команда Baud отказывается нормально работать без обнуления 1 бита в регистре Ucsr0a. В железе нормально работают все эти варианты. Возможно ошибка протеуса.

+3

2

Спасибо за библиотеку.
Можно ли её приспособить для датчика влажности DHT11/DHT22 ?

0

3

У DHT11/DHT22 другой протокол. В сети примеров не нашел.

0

4

не в тему, потом Админ перенесёт:
пример работы с DHT11
не моё, найдено в Сети

Код:
$regfile = "attiny13a.dat"
$crystal = 1200000
$hwstack = 15
$swstack = 15
$framesize = 15

Dim T As Byte                 'переменная для хранения температуры
Dim H As Byte                 'переменная для хранения влажности
Dim Crc As Byte               'переменная для хранения байта четности

Dim Mybyte As Byte , Temp As Byte , Volts As Word


'подключение датчика к Portb.3
Dht_put Alias Portb.3
Dht_get Alias Pinb.3
Dht_io_set Alias Ddrb.3

Rele_hotmirror Alias Portb.0  ' Реле нагрева зеркал
Config Rele_hotmirror = Output

Rele_good_power Alias Portb.2 ' Реле "U > 11v"
Config Rele_good_power = Output


Config Adc = Single , Prescaler = Auto , Reference = Avcc : Start Adc

Rele_hotmirror = 0

Dht_io_set = 1 : Dht_put = 1

' Open "comb.1:2400,8,n,1" For Output As #1        'Open a TRANSMIT channel for output




Start_prg:

'' ===    Измеряем напряжение в канале   ===
  Volts = Getadc(2)           ' Измеряем напряжение в канале 2
  Shift Volts , Right , 2     ' Превращаем 12 бит в 10 бит
'    Print #1 , Volts

 If Volts < 131 Then
    Rele_good_power = 0       ' откл Реле "U > 11v"
    Rele_hotmirror = 0        ' откл Реле "Нагрев зеркал"
   Goto Start_prg
 End If

 Rele_good_power = 1          ' Вкл Реле "U > 11v"

 Wait 5

 Gosub Get_th                 ' опрос Т и Н
'    Print #1 , T
'    Print #1 , H


  If T < 5 Or H > 45 Then Rele_hotmirror = 1       ' 45

  If T > 10 And H < 40 Then Rele_hotmirror = 0

Goto Start_prg


'  Close #1


' ===========================================================================================

Get_th:                       ' (t As Byte , H As Byte)
 Set Dht_io_set               'делаем  выходом
 Reset Dht_put                'прижимаем шину к земле
 Waitms 25                    'ждем более 18мс

 Set Dht_put                  'отпускаем шину
 Waitus 40
 Reset Dht_io_set             'делаем  входом
 Waitus 40                    'ждем 40 мкс
 If Dht_get = 1 Then          'если на нем = 1
    H = 0 : T = 255           'значит датчик не ответил
    Goto Exit_sub             'выходим из подпрограммы
 End If

'если датчик ответил и прижал шину к земле - продолжаем работу
  Waitus 80                   'ждем еще 80 мкс
  If Dht_get = 0 Then         'если на линии по-прежнему 0
    H = 0 : T = 255           'значит датчик сошел с ума
    Goto Exit_sub             'выходим из подпрограммы
  End If

'если все нормально и датчик ответил правильно, тогда продолжаем

  Bitwait Dht_get , Reset     'ждем пока на шине появится 1

  H = 0
  For Temp = 7 To 0 Step -1   ' читаем челое значение температуры
    Bitwait Dht_get , Set     'ждем появления на шине 0
     Waitus 30                'после появления 0 ждем 30мкс
     If Dht_get = 1 Then H.temp = 1       'если на шине 1
  Next

  For Temp = 7 To 0 Step -1   ' пропускаем десятичную часть температуры
    While Dht_get = 0 : Wend  'ждем появления на шине 0
     Waitus 30                'после появления 0 ждем 30мкс
  Next


  T = 0
  For Temp = 7 To 0 Step -1   ' читаем челое значение температуры
    Bitwait Dht_get , Set     'ждем появления на шине 0
     Waitus 30                'после появления 0 ждем 30мкс
     If Dht_get = 1 Then T.temp = 1       'если на шине 1
  Next

  For Temp = 7 To 0 Step -1   ' пропускаем десятичную часть температуры
    Bitwait Dht_get , Set     'ждем появления на шине 0
     Waitus 30                'после появления 0 ждем 30мкс
  Next


  Crc = 0
  For Temp = 7 To 0 Step -1   ' читаем челое значение температуры
    Bitwait Dht_get , Set     'ждем появления на шине 0
     Waitus 30                'после появления 0 ждем 30мкс
     If Dht_get = 1 Then Crc.temp = 1       'если на шине 1
  Next


   Set Dht_io_set
   Set Dht_put



'проверка контрольной суммы

   Mybyte = T + H             'складываем значение температуры и влажности
   If Mybyte <> Crc Then      'если контрольная сумма не сошлась
      H = 1 : T = 111         'значит полученные данные не верны
   End If

 Exit_sub:

Return                        'возвращаемся в главный цикл программы

0

Похожие темы


Вы здесь » Программирование ATMEL в BASCOM. » Исходники » Библиотека для аппартаного модуля 1Wire на основе USART