Еще прграмка с использованием RC5. Обучение под любые кнопки пульта.
Рассчитана только под пульты RC5-6. Они доступны. Стоят в районе 200р. RTC использую DS3231. От DS1307 давно отказался. Сильно бегают по времени. RC5 используется только для экономии портов(вместо кнопок). КР514ИД1 использую для отладки. В дальнейшем индикатор будет собран на высоковольтных неоновых, и дешифратор будет стоять К155ИД1. 9 портов для каждого символа это уже много, и все равно ИНки кроме цифр отображать больше ничего не умеют. Поэтому знак минус выведен на отдельный порт.
Частоту догнал до 16мГц, из-за ненужных морганий сегментов. Думаю при опросе 18в20 с прерываниями накладки происходят. Может чего спецы посоветуют.
$regfile = "m8adef.dat" ' тип МК
$crystal = 16000000 ' выбор кристала для расчета задержек
' Open "comb.0:9600,8,n,1" For Output As #1
'*****************************************[Определение переменных и констант]************************************
Dim I(6) As Word ' четыре разряда
Dim Count As Byte ' счетчик для перебора разрядов
Dim Count_blink As Byte ' счетчик длительности мигания точки
'***********************************************
Dim Sstr As String * 6
Dim Ind_str As String * 1
Dim K As Byte
Dim L As Byte
Dim W As Byte
'=====конфигурация I2C интерфейса scl и sda пины
'===============================================================================
Config Sda = Portc.4 ' I2C Data
Config Scl = Portc.5 ' I2C Clock
Config I2cdelay = 1 ' Скорость работы шины I2c на программном уровне
I2cinit
Waitms 50
'=====заводим константы на биты чтения и записи ds3231
Const Ds3231w = &HD0 ' бит записи
Const Ds3231r = &HD1 ' бит чтения
'===========переменные для работы датчика температуры DS3231
'===============================================================================
Declare Sub Ds3231
Dim Tds3231_bcd As Integer
Dim Temper_z As Byte At Tds3231_bcd + 1 Overlay ' целая часть температуры со знаком
Dim Temper_d As Byte At Tds3231_bcd + 0 Overlay ' дробная часть
Dim Tds3231 As Integer
Dim Tds3231_str As String * 5
'=====переменные для работы с DS3231
'===============================================================================
'=====в десятичном формате
Dim Seco As Byte
Dim Mine As Byte
Dim Hour As Word
Dim Day As Byte
Dim Dat As Byte
Dim Month As Byte
Dim Year As Byte
'=====в двоично-десятичном формате
Dim Seco_bcd As Byte
Dim Mine_bcd As Byte
Dim Hour_bcd As Byte
Dim Day_bcd As Byte
Dim Dat_bcd As Byte
Dim Month_bcd As Byte
Dim Year_bcd As Byte
'=====в текстовом формате
Dim Secostr As String * 2
Dim Minestr As String * 2
Dim Hourstr As String * 2
'=============================================================================
Dim Address As Byte
Dim Command As Byte
Dim Flag As Byte
Dim Flagstr As String * 1
Dim Menu As Bit
Dim Время(6) As Byte
Dim Время_str(6) As String * 2
Dim H As Byte
Dim Hstr As String * 1
'команды хранящиеся в EEPROM
Dim Ee1 As Eram Byte
Dim Ee2 As Eram Byte
Dim Ee3 As Eram Byte
Dim Ee4 As Eram Byte
Dim Ee5 As Eram Byte
Dim Ee6 As Eram Byte
Dim Ee7 As Eram Byte
'команды для сравнения с командами с пульта
'-----------------------------------------------------------------------------
Dim Aa1 As Byte
Dim Aa2 As Byte
Dim Aa3 As Byte
Dim Aa4 As Byte
Dim Aa5 As Byte
Dim Aa6 As Byte
Dim Aa7 As Byte
'Переменные 1 датчика 18В20
'============================================================================================================
Dim Tds1 As Integer 'температура получаемая с 1 датчика в 0.1градуса. 10 = 1,0 градус
Dim Tds1_str As String * 4
Dim Err_c1 As Bit 'ошибка датчика
'Переменные 2 датчика 18В20
'============================================================================================================
Dim Tds2 As Integer 'температура получаемая с 1 датчика в 0.1градуса. 10 = 1,0 градус
Dim Tds2_str As String * 4
Dim Err_c2 As Bit 'ошибка датчика
'***********************************************[Инициализация портов]*******************************************
Ddrb = &B00111111 ' разряды индикатора (выходы), 2 кнопки (входы)
Portb = &B00111111 ' разряды выключены, кнопки к питанию подтянуты
'-------------------------
Ddrd = &B00111111 ' сегменты индикатора (выходы)
Portd = &B00000000 ' сегменты выключены
'-----------------------------------------------------------------------------
Config Pinc.3 = Input 'Кнопка валкодера
Pult Alias Pinc.3
'*********************************************[Инициализация прерываний]*****************************************
Const Ds1820 = 100
Config Timer0 = Timer , Prescale = 256 ' конфигурируем таймер (~250 Гц)
On Timer0 Refresh ' обзываем прерывание
'-----------------------------------------------------------------------------
Config Rc5 = Pinc.2 , Timer = 1 , Wait = 2000 'конфигурируем ногу для подключения датчика RC5
'-----------------------------------------------------------------------------
Enable Interrupts ' разрешаем все прерывания
Enable Timer0 ' и для таймера в частности (индикация)
Declare Sub Look_timer()
'********************************************[Присвоение уникальных имен]****************************************
Dig1 Alias Portb.0 : Dig2 Alias Portb.1 : Dig3 Alias Portb.2 : Dig4 Alias Portb.3 : Dig5 Alias Portb.4 : Dig6 Alias Portb.5 : Dot Alias Portd.0
A Alias Portd.1 : B Alias Portd.2 : C Alias Portd.3 : D Alias Portd.4 : E Alias Portd.5
'*********************************************[Начало основной программы]****************************************
'-----------------------------------------------------------------------------
'вытаскиваем значения команд из энергонезависимой памяти и присваиваем рабочим переменным
'-----------------------------------------------------------------------------
Aa1 = Ee1
Aa2 = Ee2
Aa3 = Ee3
Aa4 = Ee4
Aa5 = Ee5
Aa6 = Ee6
Aa7 = Ee7
L = 1 : K = 0 : Menu = 0
'******************************************************************************************
Do
Getrc5(address , Command) 'принимаем адресс и команду с пульта
If Address = 0 Then 'работаем с любым пультом
Command = Command And &B01111111
If Flag = 0 Then
Select Case Command
Waitms 300
Case Aa1 : Toggle Menu 'Входим в меню установки
Case Aa2 : Incr H 'Выбираем, что будем утанавливать
Case Aa3 : Decr H '
Case Aa4 : Incr Время(h) 'Увеличиваем значение Год, Месяц, и тд
Case Aa5 : Decr Время(h) '
Case Aa6 : K = 1 'Запись в
Case Aa7 : Incr L 'Переключение индикации время, термометры
End Select
End If
If Flag <> 0 Then '
Select Case Flag 'в зависимости от номера флага запишем команду в свою ячейку памяти
Case 1 : Ee1 = Command 'записываем номер команды в EEPROM
Case 2 : Ee2 = Command
Case 3 : Ee3 = Command
Case 4 : Ee4 = Command
Case 5 : Ee5 = Command
Case 6 : Ee6 = Command
Case 7 : Ee7 = Command
End Select
Flag = 0 'сбрасываем флаг записи
Aa1 = Ee1 'вытаскиваем все из энергонезависимой памяти
Aa2 = Ee2
Aa3 = Ee3
Aa4 = Ee4
Aa5 = Ee5
Aa6 = Ee6
Aa7 = Ee7
End If
Waitms 10
End If
If Pult = 0 Then 'Кнопка флага для записи команд с пульта
Waitms 100 'избавляемся от дребезга кнопки
Incr Flag
If Flag > 7 Then Flag = 0 'если нажали кнопку 8 раз
End If
If L > 4 Then L = 1
'****************************************************************************************** ' основной цикл
If Menu = 0 Then Gosub Ds3231
Gosub Temper
Gosub Ind ' обновление значения времени на индикаторе
' Waitms 500
Loop
'***********************************[Процедуры обработки подпрограмм и прерываний]*******************************
Refresh: ' прерывание таймера Т0 (переполнение каждые ~4 мс)
Set Dig1 : Set Dig2 : Set Dig3 : Set Dig4 : Set Dig5 : Set Dig6 : Reset Dot ' гасим индикатор
Incr Count : If Count > 6 Then Count = 1 ' выбираем какой разряд сейчас включать
Incr Count_blink : If Count_blink > 250 Then Count_blink = 1 ' длительность мигания точки
Ind_str = Mid(sstr , Count , 1)
Select Case Ind_str
Case "0" : D = 0 : C = 0 : B = 0 : A = 0 '&b0000
Case "1" : D = 0 : C = 0 : B = 0 : A = 1 '&b0001
Case "2" : D = 0 : C = 0 : B = 1 : A = 0 '&b0010
Case "3" : D = 0 : C = 0 : B = 1 : A = 1 '&b0011
Case "4" : D = 0 : C = 1 : B = 0 : A = 0 '&b0100
Case "5" : D = 0 : C = 1 : B = 0 : A = 1 '&b0101
Case "6" : D = 0 : C = 1 : B = 1 : A = 0 '&b0110
Case "7" : D = 0 : C = 1 : B = 1 : A = 1 '&b0111
Case "8" : D = 1 : C = 0 : B = 0 : A = 0 '&b1000
Case "9" : D = 1 : C = 0 : B = 0 : A = 1 '&b1001
Case " " : D = 1 : C = 1 : B = 1 : A = 1 '&b1111 гасит
End Select
If W = 1 And Count_blink < 125 Then ' включаем точку в нужном разряде
If Count = 2 Or Count = 4 Then Set Dot
End If
If W = 0 And Count = 3 Then Set Dot 'Точка при отображении температуры без мигания
Select Case Count ' и включаем соответствующий разряд индикатора
Case 1 : Reset Dig1
Case 2 : Reset Dig2
Case 3 : Reset Dig3
Case 4 : Reset Dig4
Case 5 : Reset Dig5
Case 6 : Reset Dig6
End Select
Return
'----------------------------------------------------------------------------------------------------------------
Ind:
If Menu = 0 Then 'Если нужно только подвести
Время(1) = Year
Время(2) = Month
Время(3) = Dat
Время(4) = Day
Время(5) = Hour
Время(6) = Mine
End If
Tds1_str = Mid(tds1_str , 2 , 3)
Tds2_str = Mid(tds2_str , 2 , 3)
If H = 1 And Menu = 1 Then Year = Время(1) 'Установка переменных для аписи RTC
If H = 2 And Menu = 1 Then Month = Время(2)
If H = 3 And Menu = 1 Then Dat = Время(3)
If H = 4 And Menu = 1 Then Day = Время(4)
If H = 5 And Menu = 1 Then Hour = Время(5)
If H = 6 And Menu = 1 Then Mine = Время(6)
If H > 6 And Menu = 1 Then H = 6
If H < 1 And Menu = 1 Then H = 1
Hstr = Str(h)
Время_str(h) = Str(время(h))
Время_str(h) = Format(время_str(h) , "00")
Flagstr = Str(flag)
If K = 1 And Menu = 1 Then 'Запись RTC
Seco = 0
Seco = Makedec(seco)
Gosub Setup_rtc
K = 0
End If
If Flag = 0 And Menu = 0 And L = 1 Then 'Выводим на индикатор часы минуты секунды
Sstr = Hourstr + Minestr + Secostr
W = 1
End If
If Flag = 0 And Menu = 0 And L = 2 Then 'Уличный 18в20
Sstr = " " + Tds1_str + " "
W = 0
End If
If Flag = 0 And Menu = 0 And L = 3 Then 'Комнатный 18в20
Sstr = " " + Tds2_str + " "
W = 0
End If
If Flag = 0 And Menu = 0 And L = 4 Then 'Температура DS3231(тоже комнатная. Но в корпусе все греется)
Sstr = " " + Tds3231_str + " "
W = 0
End If
If Flag <> 0 Then
Sstr = Flagstr + " "
W = 2
End If
If Menu = 1 Then
Sstr = " " + Hstr + " " + Время_str(h) + " " 'Индикация в менюхе
W = 2
End If
If Left(tds1_str , 1) = "-" Then 'Отдельный порт при отрицательной температуре
E = 1
Else
E = 0
End If
Return
'*****************************************************[Прочее]***************************************************
'Обработка датчика температуры DS18B20
'====================================================================================================
Temper:
Gosub Look_timer
1wreset Pinc , 0
Gosub Look_timer
If Err = 1 Then
Err_c1 = 1 'ставим флаг ошибки датчика
Tds1 = 32767 'если при опросе небыло ответа ставим флаг ошибки
Else
Err_c1 = 0
1wwrite &HCC , 1 , Pinc , 0 'пропуск ROM(для всех)
1wwrite &H44 , 2 , Pinc , 0 'конвертировать температуру(для всех)
End If
' Waitms 94
If Err_c1 = 0 Then
Gosub Look_timer 'если небыло ошибки при начале конвертирования
1wreset Pinc , 0
Gosub Look_timer
If Err = 1 Then
Tds1 = 32767 'если при опросе небыло ответа ставим флаг ошибки
Else 'иначе, если ошибки не было, продолжаем опрос датчика
1wwrite &HCC , 1 , Pinc , 0
1wwrite &HBE , 1 , Pinc , 0
Tds1 = 1wread(2 , Pinc , 0)
Tds1 = Tds1 * 10
Tds1 = Tds1 \ 16
End If
Tds1_str = Str(tds1)
Tds1_str = Format(tds1_str , "+000")
Else
Tds1 = 32767
Tds1_str = " 000"
End If
'===================================================================
Gosub Look_timer
1wreset Pinc , 1
Gosub Look_timer
If Err = 1 Then
Err_c2 = 1 'ставим флаг ошибки датчика
Tds2 = 32767 'если при опросе небыло ответа ставим флаг ошибки
Else
Err_c2 = 0
1wwrite &HCC , 1 , Pinc , 1 'пропуск ROM(для всех)
1wwrite &H44 , 2 , Pinc , 1 'конвертировать температуру(для всех)
End If
' Waitms 94 'время преобразования для 9 битного разрешения
If Err_c2 = 0 Then
Gosub Look_timer 'если небыло ошибки при начале конвертирования
1wreset Pinc , 1
Gosub Look_timer
If Err = 1 Then
Tds2 = 32767 'если при опросе небыло ответа ставим флаг ошибки
Else 'иначе, если ошибки не было, продолжаем опрос датчика
1wwrite &HCC , 1 , Pinc , 1
1wwrite &HBE , 1 , Pinc , 1
Tds2 = 1wread(2 , Pinc , 1)
Tds2 = Tds2 * 10
Tds2 = Tds2 \ 16
End If
Tds2_str = Str(tds2)
Tds2_str = Format(tds2_str , "+000")
Else
Tds2 = 32767
Tds2_str = " 000"
End If
Return
'=====опрос микросхемы DS3231
'===============================================================================
Ds3231:
I2cstart
I2cwbyte Ds3231w
I2cwbyte &H00 'стартовый адрес
I2cstart
I2cwbyte Ds3231r
'=====прием и запись данных
I2crbyte Seco_bcd , Ack
I2crbyte Mine_bcd , Ack
I2crbyte Hour_bcd , Ack
I2crbyte Day_bcd , Ack
I2crbyte Dat_bcd , Ack
I2crbyte Month_bcd , Ack
I2crbyte Year_bcd , Nack
I2cstop
I2cstart ' даем режим готовности часам
I2cwbyte Ds3231w ' адрес микросхемы
I2cwbyte &H11 ' адрес откуда начинаем читать данные
I2cstart ' даем сигнал старт на прочтение данных
I2cwbyte Ds3231r ' даем понять что готовы принимать данные
I2crbyte Temper_z , Ack ' целая часть температуры со знаком
I2crbyte Temper_d , Nack ' дробная часть
I2cstop ' закончили
Gosub Convert
Return
'=====Преобразование и форматирование переменных времени и даты
'===============================================================================
Convert:
'=====преобразование в десятичную систему
Seco = Makedec(seco_bcd)
Mine = Makedec(mine_bcd)
Hour = Makedec(hour_bcd)
Day = Makedec(day_bcd)
Dat = Makedec(dat_bcd)
Month = Makedec(month_bcd)
Year = Makedec(year_bcd)
If Temper_z < 128 Then
Select Case Temper_d
Case 0 : Temper_d = 0 '0000_0000
Case 64 : Temper_d = 2 '0100_0000
Case 128 : Temper_d = 5 '1000_0000
Case 192 : Temper_d = 7 '1100_0000
End Select
Tds3231 = Temper_z * 10
Tds3231 = Tds3231 + Temper_d
Else
Temper_z = Not Temper_z
Temper_d = Not Temper_d
Select Case Temper_d
Case 0 : Temper_d = 0 '1111_1111
Case 63 : Temper_d = 2 '0011_1111
Case 127 : Temper_d = 5 '0111_1111
Case 191 : Temper_d = 7 '1011_1111
End Select
Tds3231 = Temper_z * 10
Tds3231 = Tds3231 + Temper_d
Tds3231 = Tds3231 * -1
End If
'=====форматирование
Secostr = Str(seco)
Secostr = Format(secostr , "00")
Minestr = Str(mine)
Minestr = Format(minestr , "00")
Hourstr = Str(hour)
Hourstr = Format(hourstr , "00")
Tds3231_str = Str(tds3231)
Tds3231_str = Format(tds3231_str , "000")
Return
'===============================================================================
Look_timer:
Do
nop
Loop Until Tcnt0 < Ds1820
Return
'=====отправление данных в часы
'===============================================================================
Setup_rtc:
Sstr = "000000"
Seco_bcd = Makebcd(seco)
I2cstart
I2cwbyte Ds3231w
I2cwbyte 0
I2cwbyte Seco_bcd
I2cstop
Mine_bcd = Makebcd(mine)
I2cstart
I2cwbyte Ds3231w
I2cwbyte 1
I2cwbyte Mine_bcd
I2cstop
Hour_bcd = Makebcd(hour)
I2cstart
I2cwbyte Ds3231w
I2cwbyte 2
I2cwbyte Hour_bcd
I2cstop
Day_bcd = Makebcd(day)
I2cstart
I2cwbyte Ds3231w
I2cwbyte 3
I2cwbyte Day_bcd
I2cstop
Dat_bcd = Makebcd(dat)
I2cstart
I2cwbyte Ds3231w
I2cwbyte 4
I2cwbyte Dat_bcd
I2cstop
Month_bcd = Makebcd(month)
I2cstart
I2cwbyte Ds3231w
I2cwbyte 5
I2cwbyte Month_bcd
I2cstop
Year_bcd = Makebcd(year)
I2cstart
I2cwbyte Ds3231w
I2cwbyte 6
I2cwbyte Year_bcd
I2cstop
Wait 1
Return


И эти коды рабочие. Проверял. 