Особенностью работы датчика температуры DS18b20, рассмотренного в предыдущей статье является то, что от запроса на преобразование до чтения значения температуры должно пройти определенное время (не менее 0,75 сек по даташиту). Это время требуется датчику для преобразования аналогового сигнала в цифровую форму, к тому же при частом опросе возможен нагрев датчика, что вызовет искажение показаний. Для совместной работы с семисегментным индикатором необходимо учитывать, что индикация происходит в динамическом режиме и поэтому запихивать запуск преобразования и чтение результата в один цикл с обработкой индикации не следует. Иначе индикация во время ожидания преобразования заглохет и вывод показаний прекратится, что вызовет моргание индикатора. Чтобы этого избежать можно индикацию оставить в главном цикле, а работу с датчиком повесить в обработчик прерывания от таймера. Таким образом распараллелить задачу – пока датчик ведет преобразование микроконтроллер обрабатывает индикацию. Тут я поступил практически также: в главном цикле происходит вывод текущей температуры на индикатор, когда очередь доходит до работы с датчиком, проверяется переменная отвечающая за то, что нужно сделать – начать преобразование или считать результат преобразования. Значение этой переменной изменяется в обработчике прерывания от таймера (каждые 0,5 сек). Таким образом, работа с датчиком и динамическая индикация находятся в одном цикле, но за один цикл выполняется либо преобразование, либо чтение результата или работа с датчиком пропускается совсем.
В качестве таймера задействован Timer1 с предделителем на 64, таким образом при частоте работы МК 8 МГц переполнение и изменение переменной будет происходить каждые 0,52 сек. Схему подключения индикатора взял со статьи о подключении энкодера, сигнальный провод датчика прицепил к ноге PortD.2
Листинг программы в Bascom-AVR:
$regfile = “attiny2313.dat”
$crystal = 8000000
Dim A As Bit ‘флаг запуска преобразования
Dim B As Bit ‘флаг готовности опроса датчика
Dim N1 As Bit ‘переменные для хранения чисел в разрядах индикатора
Dim N2 As Byte
Dim N3 As Byte
Dim N4 As Byte
Dim N5 As Byte
Dim M2 As Integer ‘переменные для предварительных преобразований
Dim M3 As Integer
Dim Byte0 As Byte ‘переменные для приема данных с датчика
Dim Byte1 As Byte
Dim T1 As Byte ‘переменные для хранения температуры
Dim T2 As Byte
Ddrd = &B11011011 ‘порт для подключения анодов
Ddrb = &B11111111 ‘порт для подключения сегментов
Config 1wire = Portd.2 ‘конфигурируем ногу для подключения датчика
Config Timer1 = Timer , Prescale = 64 ‘при 8МГц переполнение таймера за 0,52 сек
On Timer1 Dat ‘даем ссылку на обработчик прерывания по переполнению таймера
‘разрешаем прерывания
Enable Interrupts
Enable Timer1
‘останавливаем таймер
Stop Timer1
N2 = 11
N3 = 11
Waitms 100
‘ГЛАВНЫЙ ЦИКЛ ПРОГРАММЫ
Do
Portd = &B11111110 ‘первый разряд
Select Case N1
Case 0 : Portb = &B10111111 ‘-
Case 1 : Portb = &B11111111
End Select
Waitus 500
Portd = &B11111101 ‘второй разряд
Select Case N2
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
Case 10 : Portb = &B10000110 ‘E
Case 11 : Portb = &B10111111 ‘-
End Select
Waitus 500
Portd = &B11110111 ‘третий разряд
Select Case N3
Case 0 : Portb = &B11000000
Case 1 : Portb = &B11111001
Case 2 : Portb = &B10100100
Case 3 : Portb = &B10110000
Case 4 : Portb = &B10011001
Case 5 : Portb = &B10010010
Case 6 : Portb = &B10000010
Case 7 : Portb = &B11111000
Case 8 : Portb = &B10000000
Case 9 : Portb = &B10010000
Case 10 : Portb = &B10101111 ‘r
Case 11 : Portb = &B10111111 ‘-
End Select
Waitus 500
Portd = &B11101111 ‘четвертый разряд
Select Case N4
Case 0 : Portb = &B10111111 ‘-
Case 1 : Portb = &B10011100 ‘градус
Case 2 : Portb = &B10101111 ‘r
End Select
Waitus 500
Portd = &B10111111 ‘пятый разряд
Select Case N5
Case 0 : Portb = &B10111111 ‘-
Case 1 : Portb = &B11000110 ‘C
End Select
Waitus 500
‘*** РАБОТА С ДАТЧИКОМ ***
‘запускаем преобразование
If A = 0 Then ‘пока переменная А=0 запускаем опрос датчика
1wreset ‘сбрасываем линию
1wwrite &HCC ‘пропуск ПЗУ
1wwrite &H44 ‘запускаем преобразование
If Err = 1 Then ‘если ответа небыло, выводим сообщение об ошибке
N1 = 0
N2 = 10
N3 = 10
N4 = 2
N5 = 0
Else
A = 1 ‘увеличиваем, чтобы в следующем цикле пропустить опрос датчика
Start Timer1 ‘запускаем таймер
End If
End If
‘чтение результата
If A = 1 And B = 1 Then ‘чтение не произойдет пока В не станет равна 1
Stop Timer1 ‘останавливаем и обнуляем таймер
Timer1 = 0
1wreset ‘сбрасываем линию
1wwrite &HCC ‘пропуск ПЗУ
1wwrite &HBE ‘читаем из ОЗУ, чего мы там наизмеряли
Byte0 = 1wread() ‘читаем нулевой и первый байт памяти датчика
Byte1 = 1wread() ‘в них хранится считанная температура
If Byte1 > 248 Then ‘Проверка на отрицательность температуры
Byte0 = &HFF – Byte0
Byte1 = &HFF – Byte1
N1 = 0 ‘отрицательная температура
Else
N1 = 1 ‘иначе, положительная
End If
T1 = Byte0 / 16 ‘Сдвигаем нулевой байт вправо на 4 бита (2*2*2*2=16)
T2 = Byte1 * 16 ‘Сдвигаем первый байт влево на 4 бита (2*2*2*2=16)
T1 = T1 + T2 ‘Формируем результат для вывода на индикатор
If N1 = 0 Then ‘для корректного вывода отрицательных температур
T1 = T1 + 1
End If
If N1 = 1 And T1 = 0 Then ‘убираем знак “+” с нулевой температуры
N1 = 1
End If
‘ГОТОВИМ ПЕРЕМЕННЫЕ ДЛЯ ВЫВОДА НА ИНДИКАТОР
M2 = T1
M3 = T1
M2 = M2 / 10 ‘обработка второго разряда
N2 = Abs(m2)
M3 = M3 Mod 10 ‘обработка третьего разряда
N3 = Abs(m3)
N4 = 1 ‘если 1 то отобразим символ градус
N5 = 1 ‘если 1 отобразим С
A = 0
B = 0
End If
Loop
‘ПРЕРЫВАНИЕ ОТ ТАЙМЕРА
Dat:
B = 1 ‘ставим флаг готовности опроса датчика
Return
End
При ошибке чтения или при отсутствии датчика отображается сообщение об ошибке:
А это отображение измеренной температуры:
Скачать файлы к проекту
Взято с: avrproject.ru
Последние статьи
- Лучшая практика проектирования при размещении компонентов печатной платы
- Android 6.0 на lancer X
- Простой усилитель мощности класса АВ своими руками.
- Двухтактный ультралинейный ламповый УНЧ на EL84 (6П14П).
- Люксметр на ATmega8 и цифровом датчике BH1750
- Контроллер для светодиодной ленты с ИК управлением
- Самодельный LED светильник на основе ИК датчика HC-SR501
- Простой усилитель низкой частоты на TDA7377 и NE5532
- Простейший звонок с двумя мелодиями
- LED Cube 8x8x8 на Arduino с RTC