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

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

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

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


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Мерцание семисегментного индикатора во время опрса DS18B20.


Мерцание семисегментного индикатора во время опрса DS18B20.

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

1

Всем привет. Тема уже обсуждалась - знаю. Но нигде нет конкретного РАБОТАЮЩЕГО примера. Потому и прощу помощи. Видео снять не получилось. На камеру мерцание не видно. Прилагаю листинг программы.

$regfile = "m8adef.dat"
$crystal = 4000000

Dim N1 As Integer
Dim N2 As Integer
Dim N3 As Integer
Dim N4 As Integer
Dim M2 As Integer
Dim M3 As Integer
Dim K As Integer
Dim S As Integer
Dim T1 As Byte
Dim T2 As Byte
Dim Byte0 As Byte
Dim Byte1 As Byte
Dim Sign As Bit
Dim F As Bit
Dim A As Bit                                                'флаг запуска преобразования
Dim B As Bit
Config Portd = Output
Config Portc = Output

Config Timer0 = Timer , Prescale = 256
Config Timer1 = Timer , Prescale = 64

Config 1wire = Portb.2

Enable Timer0
Enable Timer1

Enable Interrupts
On Timer0 Led
On Timer1 Dat

Do

Portc = &B0001
Portd = Lookup(n1 , Pattern)
Waitms 3

Portc = &B0010
Portd = Lookup(n2 , Pattern)
Waitms 3

Portc = &B0100
Portd = Lookup(n3 , Pattern)
Waitms 3

Portc = &B1000
Portd = Lookup(n4 , Pattern)
Waitms 3

Loop

Dat:

Gosub Temperatura

Return

Temperatura:

1wreset

1wwrite &HCC

1wwrite &H44

  'чтение результата
1wreset

1wwrite &HCC

1wwrite &HBE

Byte0 = 1wread()
Byte1 = 1wread()

If Byte1 >= 248 Then
Byte0 = &HFF - Byte0
Byte1 = &HFF - Byte1
Sign = 0
Else
Sign = 1
End If

T1 = Byte0 / 16
T2 = Byte1 * 16
T1 = T1 + T2

N3 = T1 / 10
N3 = Abs(n3)
N4 = N3 * 10
N4 = T1 - N4
N4 = Abs(n4)


Return

Led:

Return

End

Pattern:

Data &B00111111
Data &B00000110
Data &B01011011
Data &B01001111
Data &B01100110
Data &B01101101
Data &B01111101
Data &B00000111
Data &B01111111
Data &B01101111

0

2

делаете две фишки:
1. запускаете процесс измерения
2. через 0.75 sec выполняете чтение данных из регистров датчика

т.е., разделите процедуру опроса

у вас нет паузы, кстати
или я не так понял алгоритм?

0

3

Если поставить паузу (согласно даташиту вообще -то) то будет не просто мерцать, а мигать с этой паузой. Без паузы вычисление проходит вполне корректно. Пробовал по таймеру - та же фигня, мерцает.

0

4

А что вы вообще хотели при линейном алгоритме программы, с медленным опросом данных (с датчика).
Меняйте.

0

5

Что менять? Друзья, если это невозможно - опишите почему. Если возможно - приведите, пожалуйста, пример кода.

0

6

Попробуйте:

- Вывод на индикатор делаете так же через таймер, скажем не быстрее 25 кадров в секунду. Для эксперимента можно вообще раз в секунду выводить, а не как сейчас более 15000 в секунду.
- Опрос датчика со всеми задержками в основном теле программы.

Остальное потом доработаете.

0

7

Обычно динамическую индикацию производят в прерывании от таймера, а  опрос датчика в основном цикле программы. В вашем коде наоборот.

Пример. http://pure-basic.narod.ru/forum_files/ … mo_Led.rar

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

Declare Sub Termo()

Config 1wire = Portb.0
Config Portd = Output
Config Portc = Output

Dim Dinamindex As Byte
Dim Temp As Byte
Dim Dinaminfo(4) As Byte
Dim 1wire_array(9) As Byte                                  ' Объявление массива
Dim Currenttermo As Word At 1wire_array Overlay

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


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

Enable Interrupts

Do
   1wreset                                                  ' Сброс датчика.
   1wwrite &HCC                                             ' Команда "Skip ROM".
   1wwrite &H44                                             ' Команда "Convert  T".
   Waitms 800
   1wreset                                                  ' Сброс датчика.
   1wwrite &HCC                                             ' Команда "Skip ROM"
   1wwrite &HBE
   1wire_array(1) = 1wread(2)
   If Err = 0 Then
     Call Termo()
   End If
Loop
End

Sub Termo()
  Stop Timer0

   If 1wire_array(2).7 = 1 Then
     Toggle Currenttermo
     Incr Currenttermo
     Dinaminfo(4) = 10
   Else
     Dinaminfo(4) = 11
   End If

   Temp = 1wire_array(1) And 15
   Dinaminfo(1) = Lookup(temp , Ds_dec)
   Shift Currenttermo , Right , 4
   Dinaminfo(2) = 1wire_array(1) Mod 10
   Dinaminfo(3) = Currenttermo / 10

 Start Timer0
End Sub


Dinam:
 DinamIndex = DinamIndex + 1
 If Dinamindex > 4 Then Dinamindex = 1

 Temp = Dinaminfo(dinamindex)

 Portc = 0
 Portd = Lookup(temp , Ind)
 If Dinamindex = 2 Then Portd.7 = 0
 Temp = 1
 Decr Dinamindex
 Shift Temp , Left , Dinamindex
 Incr Dinamindex

 Portc = Temp

Return

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                                             ' Пусто

Ds_dec:
Data 0 , 1 , 1 , 2 , 2 , 3 , 3 , 4 , 5 , 5 , 6 , 7 , 7 , 8 , 9 , 9

0

8

Пётр, спасибо. Вы подарили надежду, что такое возможно, но постичь код без комментариев - не могу.  Даже не могу понять как там динам индикация работает. Круто написано. Возвращаюсь к своему быдлокоду. Сделал как рекомендовали трудящиеся.

Теперь горят два нуля - температура не вычисляется, такое чувство будто конвейер вообще не заглядывает в главный цикл. Все крутится только в прерывании по таймеру 0.

$regfile = "m8adef.dat"
$crystal = 1000000

Dim N1 As Integer
Dim N2 As Integer
Dim N3 As Integer
Dim N4 As Integer
Dim M2 As Integer
Dim M3 As Integer
Dim K As Integer
Dim S As Integer
Dim T1 As Byte
Dim T2 As Byte
Dim Byte0 As Byte
Dim Byte1 As Byte
Dim Sign As Bit
Config Portd = Output
Config Portc = Output
Config Timer0 = Timer , Prescale = 64
Config 1wire = Portb.2
Enable Timer0
Enable Interrupts
On Timer0 Led

Do

1wreset
1wwrite &HCC
1wwrite &H44
Waitms 750
1wreset
1wwrite &HCC
1wwrite &HBE
Byte0 = 1wread()
Byte1 = 1wread()
If Byte1 >= 248 Then
Byte0 = &HFF - Byte0
Byte1 = &HFF - Byte1
Sign = 0
Else
Sign = 1
End If
T1 = Byte0 / 16
T2 = Byte1 * 16
T1 = T1 + T2
N3 = T1 / 10
N3 = Abs(n3)
N4 = N3 * 10
N4 = T1 - N4
N4 = Abs(n4)

Loop

End

Led:

Portc = &B0001
Portd = Lookup(n1 , Pattern)
Waitms 5

Portc = &B0010
Portd = Lookup(n2 , Pattern)
Waitms 5

Portc = &B0100
Portd = Lookup(n3 , Pattern)
Waitms 5

Portc = &B1000
Portd = Lookup(n4 , Pattern)
Waitms 5

Return


Pattern:

Data &B00111111
Data &B00000110
Data &B01011011
Data &B01001111
Data &B01100110
Data &B01101101
Data &B01111101
Data &B00000111
Data &B01111111
Data &B01101111

Сделал такую проверку. В основном цикле просто присвоил для N3 и N4 конкретные значения, и нифига не выодит если в теле есть waitms, а если без waitms - то выводит на экран. Хз что такое...

Do ' так не выводит на экран
Waitms 800
N3 = 5
N4 = 8
Loop
End

Do ' так выводит на экран
N3 = 5
N4 = 8
Loop
End

Отредактировано Gin87 (2014-07-03 12:39:20)

0

9

Из прерывания динамической индикации нужно убрать задержки. Вообще в данном случае прерывания для того и нужны чтобы в промежутках между ними светилась только одна цифра. В простейшем случае, ваш код обработки прерывания можно переделать так.

Код:
Led:

   Select Case IndPos
      Case 0
         Portc = &B0001
         Portd = Lookup(n1 , Pattern)

      Case 1
         Portc = &B0010
         Portd = Lookup(n2 , Pattern)

      Case 2
         Portc = &B0100
         Portd = Lookup(n3 , Pattern)

      Case 3
         Portc = &B1000
         Portd = Lookup(n4 , Pattern)
   End Select

   IndPos = IndPos + 1
   If IndPos > 3 Then IndPos = 0

Return

В начале кода добавляете декларацию переменной.

Код:
Dim IndPos As Byte

0

10

Пётр, спасибо. Я уже нашел причину. Нужно было сделать так, чтобы обновление индикатора было не слишком быстрым, об этом писалось выше, за что спасибо. Ради интереса вставил Ваш кусок кода - работает. НО цифры стали светить тусклее. Вот финальный код:

$regfile = "m8adef.dat"
$crystal = 4000000

Dim IndPos As Byte
Dim Sc(10) As Byte
Dim N1 As Integer
Dim N2 As Integer
Dim N3 As Integer
Dim N4 As Integer
Dim T1 As Byte
Dim Byte0 As Byte
Dim Byte1 As Byte
Dim Sign As Bit
Dim A As Bit
Config Portd = Output
Config Portc = Output
Config Timer0 = Timer , Prescale = 64

Config 1wire = Portb.2
Enable Timer0
Enable Interrupts
On Timer0 Led

Do

If A = 0 Then
1wreset
1wwrite &HCC
1wwrite &H44

Waitms 300

1wreset
1wwrite &HCC
1wwrite &HBE

Byte0 = 1wread()
Byte1 = 1wread()

If Byte1 >= 248 Then
Byte0 = &HFF - Byte0
Byte1 = &HFF - Byte1
Sign = 0
Else
Sign = 1
End If
Shift Byte0 , Right , 4
Shift Byte1 , Left , 4
T1 = Byte0 + Byte1

N3 = T1 / 10
N3 = Abs(n3)
N4 = N3 * 10
N4 = T1 - N4
N4 = Abs(n4)
A = 1

End If

Loop

Led:

A = 0

Select Case Indpos
      Case 0
         Portc = &B0001
         Portd = Lookup(n1 , Pattern)

      Case 1
         Portc = &B0010
         Portd = Lookup(n2 , Pattern)

      Case 2
         Portc = &B0100
         Portd = Lookup(n3 , Pattern)

      Case 3
         Portc = &B1000
         Portd = Lookup(n4 , Pattern)
   End Select

   IndPos = IndPos + 1
   If IndPos > 3 Then IndPos = 0

Return

End

Pattern:

Data &B00111111
Data &B00000110
Data &B01011011
Data &B01001111
Data &B01100110
Data &B01101101
Data &B01111101
Data &B00000111
Data &B01111111
Data &B01101111

Флаг A нужен для единичного опроса датчика за один цикл, без него проскакивают нули периодически.

0

11

Gin87 написал(а):

Флаг A нужен для единичного опроса датчика за один цикл, без него проскакивают нули периодически.

Что не удивительно.

Gin87 написал(а):

1wreset
1wwrite &HCC
1wwrite &H44
Waitms 300
1wreset
1wwrite &HCC
1wwrite &HBE

Посмотрите в описании DS18B20 какое должно быть время задержки при 12-ти битном преобразовании.

0

12

Gin87 написал(а):

Если возможно - приведите, пожалуйста, пример кода.

Рабочий вариант семисегментники + 4 х Ds18b20, отправил Вам на mail.

0

13

Пётр написал(а):

Что не удивительно.

Посмотрите в описании DS18B20 какое должно быть время задержки при 12-ти битном преобразовании.

Да я знаю, минимум 750, хотел выгадать в быстродействии. Изменю. Спасибо.

P.S. Подскажите с вычислением дробной части температуры. Только, пожалуйста в доступной форме (кусочек кода).

Отредактировано Gin87 (2014-07-04 08:44:55)

0

14

Решил задачу. Привожу код с десятичными.

1wreset
1wwrite &HCC
1wwrite &HBE

Byte0 = 1wread()                                            ' Читаем нулевой байт
Byte1 = 1wread()                                            ' Читаем первый байт
If Byte1 >= 248 Then                                        ' Проверяем на отрицательную температуру.248 в десятичном - 11111000 в двоичном. Если температура отрицательная - вычитаем из &HFF
Byte0 = &HFF - Byte0
Byte1 = &HFF - Byte1
Sign = 1
Else
Sign = 0
End If
T1 = Byte0 / 16                                             ' Сдвигаем нулевой байт вправо на 4 бита (2*2*2*2=16)
T2 = Byte1 * 16                                             ' Сдвигаем первый байт влево на 4 бита (2*2*2*2=16)
T1 = T1 + T2
T1 = T1 * 10
If Sign = 1 Then
T1 = T1 + 1
End If

'Десятки
N1 = T1 / 100
N1 = Abs(n1)
'единицы
N2 = N1 * 100
N2 = T1 - N2
M = N2
N2 = N2 / 10
N2 = Abs(n2)
'дробная часть
N3 = N2 * 10
N3 = M - N3
N3 = Abs(n3)

N4 = 10

A = 1

End If

На этом всем спасибо, вопросов больше нет.

Отредактировано Gin87 (2014-07-04 14:52:07)

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » Мерцание семисегментного индикатора во время опрса DS18B20.