'**************************************************************** '* Name : MyNewTimer.BAS * '* Author : Dobryanskyy Sergey * '* Notice : Copyright (c) 2010 [select VIEW...EDITOR OPTIONS] * '* : All Rights Reserved * '* Date : 16.09.2010 * '* Version : 1.0 * '* Notes : * '* : * '**************************************************************** Declare SHOW_SYSTEM_VARIABLES = OFF ' При симуляции в Proteus не показывать внутренние переменные Declare FSR_CONTEXT_SAVE = OFF ' Не заботиться о сохранении содержимого регистра FSR Declare Reminders = OFF ' Выключить напоминания компилятора Declare Warnings = OFF ' Выключить предупреждения компилятора Declare Optimiser_Level 0 ' Выключить оптимизацию программы Declare Bootloader = OFF ' Выключить загрузчик ;-------------------------- Общие настройки------------------------------------ Device = 16F877A ' Используемый микроконтроллер Xtal = 4 ' Частота осциллятора 4 МГц '-------------------------- Настройки портов --------------------------------- PortB_Pullups = On ' Включить подтягивающие резисторы на PORTB Declare All_Digital = On ' Установить все порты цифровыми входами/выходами TRISB=%00000000 TRISC=%11110000 TRISD=%00000111 PORTB=%11111111 PORTC=%00000000 PORTD=%00000000 '-------------------------- Регистры специального назначения------------------- '-------------------------- OPTION_REG ---------------------------------------- Symbol PS0 = OPTION_REG.0 ' Бит установки предделителя TMR0 Symbol PS1 = OPTION_REG.1 ' Бит установки предделителя TMR0 Symbol PS2 = OPTION_REG.2 ' Бит установки предделителя TMR0 Symbol PSA = OPTION_REG.3 ' Выбор включения предделителя Symbol T0SE = OPTION_REG.4 ' Выбор фронта приращения TMR0 при внешнем тактовом сигнале Symbol T0CS = OPTION_REG.5 ' Выбор тактового сигнала для TMR0 Symbol INTEDG = OPTION_REG.6 ' Выбор активного фронта сигнала на входе внешнего прерывания INT Symbol NOT_RBPU = OPTION_REG.7 ' Включение подтягивающих резисторов на PORTB '-------------------------- INTCON -------------------------------------------- Symbol RBIF = INTCON.0 ' Флаг внешнего прерывания по PORTB.4-PORTB.7 Symbol INTF = INTCON.1 ' Флаг внешнего прерывания по PORTB.0(INT) Symbol T0IF = INTCON.2 ' Флаг переполнения TMR0 Symbol RBIE = INTCON.3 ' Бит разрешения прерывания по PORTB.4-PORTB.7 Symbol INTE = INTCON.4 ' Бит разрешения прерывания по PORTB.0(INT) Symbol T0IE = INTCON.5 ' Бит разрешения прерывания по переполнению TMR0 Symbol PEIE = INTCON.6 ' Бит разрешения прерывания от периферийных устройств Symbol GIE = INTCON.7 ' Бит глобального разрешения прерываний '-------------------------- Начало ------------------------------------------- Dim NoteOne As Byte Dim NoteTwo As Byte Dim NoteThree As Byte Dim NoteFor As Byte Dim NoteFive As Byte Dim NoteSix As Byte Dim NoteSeven As Byte Dim NoteEathe As Byte Dim NoteNine As Byte Dim NoteZero As Byte Dim NoteTire As Byte Dim NotePoint As Byte NoteOne = %11111001 ' Цифра 1 NoteTwo = %10100100 ' Цифра 2 NoteThree = %10110000 ' Цифра 3 NoteFor = %10011001 ' Цифра 4 NoteFive = %10010010 ' Цифра 5 NoteSix = %10000010 ' Цифра 6 NoteSeven = %11111000 ' Цифра 7 NoteEathe = %10000000 ' Цифра 8 NoteNine = %10010000 ' Цифра 9 NoteZero = %11000000 ' Цифра 0 NoteTire = %10111111 ' Дефис NotePoint = %01111111 ' Точка Dim i As Dword Dim y As Dword Dim BIG As Dword ' Переменная для счета секунд Dim Minute As Byte 'Минуты Dim Sec As Byte 'Секунды Dim MinuteOne As Byte ' Первая цифра минут Dim MinuteTwo As Byte ' Вторая цифра минут Dim SecOne As Byte ' Первая цифра секунд Dim SecTwo As Byte ' Вторая цифра секунд Dim Min1 As Byte ' Первая цифра индикатора Dim Min2 As Byte ' Вторая цифра индикатора Dim Sec1 As Byte ' Третья цифра индикатора Dim Sec2 As Byte ' Четвертая цифра индикатора Dim TimerOn As Bit ' Признак работы одного из таймеров Dim TimerInMin As Byte ' Время работы таймера нагрева Dim TimerOutMin As Byte ' Время работы таймера вытяжки Dim TimeCor As Dword ' Переменная коррекции времени '-------------------------- Настройка TMR0 для прерываний -------------------- OPTION_REG = %10001000 TMR0 = $EF' Значение регистра TMR0 T0IE = 1 GIE = 1 ' Разрешение глобального прерывания TimerInMin = ERead 0 ' Читаем данные из памяти контроллера TimerOutMin = ERead 1 ' Читаем данные из памяти контроллера '---------------------------Стартовые значения переменных------------------------ TimeCor = 3100 ' Число коррекции времени BIG = TimeCor ' Коррекция секунды TimerOn=0 On_Interrupt GoTo Int_Label GoTo MainProgram '--------------------------------------------------------------- Главная программа --------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- MainProgram: PORTD.5 = 0 ' Выключаем звонок GoSub LedGood ' Светин на табло надпись " Good. " Sec = 0 Minute = TimerInMin ' Читаем данные таймера нагрева StartProgram: If PORTC.4 = 1 Then GoTo StartTimerIn ' Если нажата кнопка "Старт" - переходим на программу старта нагрева If PORTC.7 = 0 Then GoTo FinishTimerAvral ' Если пришел сигнал аварии - переходим на подпрограмму аварийной остановки печи If PORTD.0 = 1 Then GoSub SetTimer ' Если нажата кнопка "Устанока" - переходим на подпрограмму установки таймера GoSub OutOnLedPanel ' Переход на подпрограмму отображения показаний таймера GoTo StartProgram '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- Int_Label: ' Программа обработки прерывания Context Save 'Сохраним значения системных регистров If TimerOn = 0 Then GoTo Loop ' Если таймер не включен, то выходим BIG = BIG - 1 ' отнимаем единицу из BIG If BIG > 0 Then GoTo Loop If BIG = 0 Then BIG = BIG + TimeCor 'Если BIG = 0 то значит прошла секунда. Dec Sec ' Денкрементируем секунды If Sec < 0 Then Minute = Minute - 1 ' Денкрементируем минуты If Sec < 0 Then Sec = 59 'Если прошло 60 сек, то сбрасываем в 59 Loop: T0IF = 0 'Сбросим флаг прерывания Context Restore ' Возврат из обработчика прерывания End '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- StartTimerIn: ' Подпрограмма старта нагрева If TimerOn = 1 Then GoTo StartProgram ' Если работает таймер - возвращаемся назад TimerOn = 0 GoSub OutOnLedPanel ' Выводим данные на табло PORTD.3 = 1 PORTD.6 = 1 ' Включаем нагрев If PORTC.5 = 1 Then GoTo FinishTimerAvral ' Если нажата кнопка "Стоп" - переходим на подпрограмму аварийной остановки печи If PORTC.7 = 0 Then GoTo FinishTimerAvral ' Если пришел сигнал аварии - переходим на подпрограмму аварийной остановки печи If PORTC.6=0 Then GoTo StartTimerIn ' Пока не пришло разрешение на включение таймера - ждем Minute = TimerInMin-1 Sec = 59 TimerOn = 1 ' Включаем признак работы таймера StartTimerInWork: ' Считываем данные MinuteOne = Dig Minute, 0 ' Вычисляем первую цифру минут MinuteTwo = Dig Minute, 1 ' Вычисляем вторую цифру минут SecOne = Dig Sec, 0 ' Вычисляем первую цифру секунд SecTwo = Dig Sec, 1 ' Вычисляем вторую цифру секунд If Sec=1 And MinuteOne = 0 Then GoTo StartTimerOut ' При окончании таймера нагрева - переходим на запуск таймера вытяжки Min1 = LookUpL MinuteOne, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 1-й цифры индикатора Min2 = LookUpL MinuteTwo, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 2-й цифры индикатора Sec1 = LookUpL SecOne, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 3-й цифры индикатора Sec2 = LookUpL SecTwo, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 4-й цифры индикатора ' Высвечиваем данные на индикатор PORTC = %000000001 PORTB = Min2 For i=0 To 10 :Next PORTC = %00000010 PORTB = Min1 + 128 For i=0 To 10 :Next PORTC = %000001000 PORTB = Sec1 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec2 For i=0 To 10 :Next If PORTC.5 = 1 Then GoTo FinishTimerAvral ' Если нажата кнопка "Стоп" - переходим на подпрограмму аварийной остановки печи If PORTC.7 = 0 Then GoTo FinishTimerAvral ' Если пришел сигнал аварии - переходим на подпрограмму аварийной остановки печи GoTo StartTimerInWork '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- StartTimerOut: ' Подпрограмма запуска таймера вытяжки TimerOn = 0 PORTD.3 = 0 PORTD.4 = 1 PORTD.6 = 0 ' Выключаем нагрев PORTD.7 = 1 ' Включаем вытяжной вентилятор If PORTC.5 = 1 Then GoTo FinishTimerAvral ' Если нажата кнопка "Стоп" - переходим на подпрограмму аварийной остановки печи If PORTC.7 = 0 Then GoTo FinishTimerAvral ' Если пришел сигнал аварии - переходим на подпрограмму аварийной остановки печи If TimerOutMin = 0 Then GoTo FullFinish Minute = TimerOutMin - 1 ' Отнимаем 1 Sec=59 ' Секунды выставляем в 59 TimerOn = 1 OutOnLedPanelOut: ' Вывод данных таймера вытяжки на панель MinuteOne = Dig Minute, 0 ' Вычисляем первую цифру минут MinuteTwo = Dig Minute, 1 ' Вычисляем вторую цифру минут SecOne = Dig Sec, 0 ' Вычисляем первую цифру секунд SecTwo = Dig Sec, 1 ' Вычисляем вторую цифру секунд If MinuteOne = 0 And Sec = 1 Then GoTo FullFinish ' При окончании таймера вытяжки - переходим на конец работы программы Min1 = LookUpL MinuteOne, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 1-й цифры индикатора Min2 = LookUpL MinuteTwo, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 2-й цифры индикатора Sec1 = LookUpL SecOne, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 3-й цифры индикатора Sec2 = LookUpL SecTwo, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 4-й цифры индикатора ' Высвечиваем данные на индикатор For y=0 To 50 PORTC = %000000001 PORTB = Min2 For i=0 To 10 :Next PORTC = %00000010 PORTB = Min1 + 128 For i=0 To 10 :Next PORTC = %000001000 PORTB = Sec1 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec2 For i=0 To 10 :Next Next ' Высвечиваем данные на индикатор без точки For y=0 To 100 PORTC = %000000001 PORTB = Min2 For i=0 To 10 :Next PORTC = %00000010 PORTB = Min1 For i=0 To 10 :Next PORTC = %000001000 PORTB = Sec1 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec2 For i=0 To 10 :Next Next If PORTC.5 = 1 Then GoTo FinishTimerAvral ' Если нажата кнопка "Стоп" - переходим на подпрограмму аварийной остановки печи If PORTC.7 = 0 Then GoTo FinishTimerAvral ' Если пришел сигнал аварии - переходим на подпрограмму аварийной остановки печи GoTo OutOnLedPanelOut '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- FinishTimerAvral: ' Подпрограмма аварийной остановки печи PORTD.3 = 0 PORTD.4 = 0 PORTD.6 = 0 ' Выключаем нагрев PORTD.7 = 0 ' Выключаем вытяжку TimerOn = 0 ' Выводим на индикатор " Err. " Min1 = %11111111 ' Символ "" Min2 = %10000110 ' Символ "E" Sec1 = %10101111 ' Символ "r" Sec2 = %00101111 ' Символ "r." ' Высвечиваем данные на индикатор For y=0 To 100 PORTC = %000000001 PORTB = Min1 For i=0 To 10: Next PORTC = %00000010 PORTB = Min2 For i=0 To 10: Next PORTC = %000001000 PORTB = Sec2 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec1 For i=0 To 10 :Next PORTD.5 = 1 ' Включаем звонок Next For y=0 To 10000 PORTC = %00000000 PORTB = %11111111 PORTD.5 = 0 ' Выключаем звонок Next If PORTC.5 = 1 Then GoTo MainProgram ' Если нажата кнопка "Стоп" - переходим на начало программы GoTo FinishTimerAvral '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- OutOnLedPanel: ' Подпрограмма вывода данных таймера на панель MinuteOne = Dig Minute, 0 ' Вычисляем первую цифру минут MinuteTwo = Dig Minute, 1 ' Вычисляем вторую цифру минут SecOne = Dig Sec, 0 ' Вычисляем первую цифру секунд SecTwo = Dig Sec, 1 ' Вычисляем вторую цифру секунд Min1 = LookUpL MinuteOne, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 1-й цифры индикатора Min2 = LookUpL MinuteTwo, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 2-й цифры индикатора Sec1 = LookUpL SecOne, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 3-й цифры индикатора Sec2 = LookUpL SecTwo, [NoteZero, NoteOne,NoteTwo,NoteThree,NoteFor,NoteFive,NoteSix,NoteSeven,NoteEathe,NoteNine] ' Получаем битовое значение 4-й цифры индикатора ' Высвечиваем данные на индикатор PORTC = %000000001 PORTB = Min2 For i=0 To 10 :Next PORTC = %00000010 PORTB = Min1 + 128 For i=0 To 10 :Next PORTC = %000001000 PORTB = Sec1 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec2 For i=0 To 10 :Next Return '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- SetTimer: If TimerOn = 1 Then Return ' Если таймер работает - возвращаемся назад Sec=0 ' Сбрасываем секунды в 0 Minute = TimerInMin ' GoSub LedSet1' Выводим на индикатор " SET1 " SetTimerIn: GoSub OutOnLedPanel' Выводим на индикатор значение текущего таймера ' Выставление таймера нагрева If PORTD.1 = 1 Then Inc Minute ' Если нажата кнопка "+", добавляем к минутам единицу If PORTD.2 = 1 Then Dec Minute ' Если нажата кнопка "-", минусуем единицу For y=0 To 100 ' Задержка для устранения дребезка GoSub OutOnLedPanel ' Вывод данных на табло Next If PORTD.0 = 0 Then GoTo SetTimerIn ' Переходим на установку таймера вытяжки TimerInMin = Minute ' Запоминаем значение таймера нагрева Minute = TimerOutMin GoSub LedSet2' Выводим на индикатор " SET2 " SetTimerOut: ' Установка таймера вытяжки GoSub OutOnLedPanel' Выводим на индикатор значение текущего таймера ' Выставление таймера вытяжки If PORTD.1 = 1 Then Inc Minute ' Если нажата кнопка "+", добавляем к минутам единицу If Minute = 100 Then Dec Minute ' Если кол-во минут превысило 99 - убавляем одну минуту If PORTD.2 = 1 Then Dec Minute ' Если нажата кнопка "-", минусуем единицу If Minute < 0 Then Inc Minute ' Если кол-во минут меньше 1 - добавляем одну минуту For y=0 To 100 ' Задержка для устранения дребезка GoSub OutOnLedPanel ' Вывод данных на табло Next If PORTD.0 = 0 Then GoTo SetTimerOut TimerOutMin = Minute ' Сохраняем текущее значение таймера вытяжки GoSub LedGood ' Светим на табло надпись " Good. " Minute = TimerInMin EWrite 0, [TimerInMin] ' Запись данных в память контроллера EWrite 1, [TimerOutMin] ' Запись данных в память контроллера Return '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- FullFinish: PORTD.3 = 0 PORTD.4 = 0 PORTD.5 = 1 ' Включаем звонок PORTD.7 = 0 ' Выключаем вытяжку TimerOn = 0 If PORTC.5 = 1 Then GoTo MainProgram ' Если нажата кнопка "Стоп" - переходим на начало программы If PORTC.7 = 0 Then GoTo FinishTimerAvral ' Если пришел сигнал аварии - переходим на подпрограмму аварийной остановки печи GoSub LedEnd' Выводим на индикатор " End. " GoTo FullFinish '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- LedGood: ' Вывод на табло надписи Good ' Выводим на индикатор "Good" Min1 = %11000010 ' Символ "G" Min2 = %10100011 ' Символ "o" Sec1 = %10100011 ' Символ "o" Sec2 = %00100001 ' Символ "d." ' Высвечиваем данные на индикатор For y=0 To 1000 PORTC = %000000001 PORTB = Min1 For i=0 To 10: Next PORTC = %00000010 PORTB = Min2 For i=0 To 10: Next PORTC = %000001000 PORTB = Sec2 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec1 For i=0 To 10 :Next Next Return '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- LedSet1: ' Вывод на табло надписи SEt1 Min1 = %10010010 ' Символ "S" Min2 = %10000110 ' Символ "E" Sec1 = %10000111 ' Символ "t" Sec2 = NoteOne ' Символ "1" For y=0 To 1000 PORTC = %000000001 PORTB = Min1 For i=0 To 10: Next PORTC = %00000010 PORTB = Min2 For i=0 To 10: Next PORTC = %000001000 PORTB = Sec2 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec1 For i=0 To 10 :Next Next Return '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- LedSet2: ' Вывод на табло надписи SEt2 Min1 = %10010010 ' Символ "S" Min2 = %10000110 ' Символ "E" Sec1 = %10000111 ' Символ "t" Sec2 = NoteTwo ' Символ "2" ' Высвечиваем на табло надпись " SEt2" For y=0 To 1000 PORTC = %000000001 PORTB = Min1 For i=0 To 10: Next PORTC = %00000010 PORTB = Min2 For i=0 To 10: Next PORTC = %000001000 PORTB = Sec2 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec1 For i=0 To 10 :Next Next Return '------------------------------------------------------------------------------------------------------------------------------------------- '------------------------------------------------------------------------------------------------------------------------------------------- LedEnd: ' Вывод на табло надписи End. Min1 = %11111111 ' Символ "" Min2 = %10000110 ' Символ "E" Sec1 = %10101011 ' Символ "n" Sec2 = %00100001 ' Символ "d." ' Высвечиваем данные на индикатор PORTC = %000000001 PORTB = Min1 For i=0 To 10: Next PORTC = %00000010 PORTB = Min2 For i=0 To 10: Next PORTC = %000001000 PORTB = Sec2 For i=0 To 10 :Next PORTC = %000000100 PORTB = Sec1 For i=0 To 10 :Next Return '------------------------------------------------------------------------------------------------------------------------------------------- '-------------------------------------------------------------------------------------------------------------------------------------------