| EData 0,100,40,2,$FF,%00111100," DVERI1 "," DVERI1 "," DVERI1 "," DVERI1 ","79139990000","F","79139991111", "F","79139992222","F"Declare Reminders= OFF'
 Declare Warnings = OFF '
 Declare FSR_CONTEXT_SAVE = OFF'
 Declare Optimiser_Level 3 '
 '-------------------------- ------------------------------------
 Device = 16F628 '
 Xtal = 4 '
 Config BODEN_OFF, PWRTE_ON, WDT_OFF, LVP_OFF, MCLRE_OFF, INTRC_OSC_NOCLKOUT,  DATA_CP_ON
 'intrc_osc_noclockout - чтобы кварц не ставить
 'mclre_off - потому что используется porta.5, можно и другой порт использовать
 'pwrte_on - обязательно для лучшего запуска
 'cp_on, data_cp_on - чтобы никто не считал программу
 '-------------------------- Описание проекта ---------------------------------
 'Проект : GSMSTOR
 'Автор :  Admin
 'Версия : 1.0.0 от 21.10.2009
 '-------------------------- Опции компилятора --------------------------------
 '-------------------------- Настройки USART ----------------------------------
 
 Declare Hserial_Baud 19200 ' Скорость передачи данных, бод для сименсов C35 и C45
 Declare Hserial_TXSTA = %00100100 ' Включить передатчик USART
 Declare Hserial_RCSTA = %10010000 ' Включить приемник USART
 Declare Hserial_Clear = On ' Автоматическая очистка бита ошибки переполнения
 '-------------------------- ------------------------------------
 Declare All_Digital = On 'Все порты - цифровые
 '-------------------------- START------------------------------------
 Dim char[8] As Byte'переменные для хранения букв латинского алфавита при перекодировке
 Dim pdu[8] As Byte 'Данные PDU формата
 Dim tmp[8] As Byte 'Массив временных переменных
 Dim ch[8] As Byte 'Массив временных переменных
 Dim id[8] As Byte 'Массив для считывания значений записанных ключей из EEPROM
 Dim ID_real[8] As Byte 'Массив для считанных с ключа значений кода ключа
 Dim x As Byte 'Счетчик
 Dim j As Byte 'Счетчик
 Dim I As Byte 'Счетчик
 Dim z As Byte 'Счетчик
 Dim PN[13] As Byte 'Массив для считывания телефонных номеров
 Dim ALARMFLAGS As Byte 'Переменная флагов тревоги
 Dim count_ As Byte 'Переменная - счетчик циклов дозвонов и отправки SMS
 Symbol onSMS = ALARMFLAGS .5 'Флаг разрешения отправки SMS
 Symbol onCall = ALARMFLAGS .4 'Флаг разрешения дозвона
 Symbol CH_4_ALLOW = ALARMFLAGS.3 'Флаг разрешения слежения за четвертым каналом
 Symbol CH_3_ALLOW = ALARMFLAGS.2 'Флаг разрешения слежения за третьим каналом
 Symbol CH_2_ALLOW = ALARMFLAGS.1 'Флаг разрешения слежения за вторым каналом
 Symbol CH_1_ALLOW = ALARMFLAGS.0 'Флаг разрешения слежения за первым каналом
 Dim Start_OXR As Bit 'Флаг режима охраны
 Dim delrun As Byte 'Переменная - задержка после открытия двери
 Dim DELAY As Byte 'Задержка для прослушивания при дозвоне на номер хозяина
 Dim numCall As Byte 'Планировалось использовать для счета числа дозвонов
 Dim SN As Byte 'Начало тел. номера
 Dim EN As Byte 'Конец тел. номера
 Dim SS As Byte 'Начало SMS
 Dim ES As Byte 'Конец SMS
 Dim ADDR_TEMP As Byte 'Временная переменная для адреса записи
 Dim addr As Byte 'Адрес записи
 Dim edat As Byte 'Временная переменная для записываемых данных
 Dim date As Byte 'Данные для записи
 Dim Num As Byte 'Переменная для хранения количества ключей в EEPROM
 Symbol INPUT_1 = PORTB.7 'Канал 1
 Symbol INPUT_2 = PORTB.6 'Канал 2
 Symbol INPUT_3 = PORTB.5 'Канал 3
 Symbol INPUT_4 = PORTB.4 'Канал 4
 Symbol INPORT = PORTA.5 'Вход для включения режима записи ключей
 Symbol LED = PORTA.0 'Светодиод
 Symbol dq = PORTA.1 'Вход для ключей
 Clear 'Очистим RAM
 PORTB=%11110010 'Настроим portb
 CMCON = 7 'Отключим компараторы
 TRISB = %11110010 'Каналы - на вход, ключ - на вход, остальные - на выход
 TRISA = %00100010
 OPTION_REG = %10000000 'Отключим подтяжку на portb
 LED = 1 'Моргнем светодиодом
 DelayMS 1000 'чтобы узреть начало работы
 LED = 0
      CONTr = 0           GoSub SETPARAM 'Считаем параметры из EEPROM  WRITE_KEY: 'Начало программы
 If INPORT = 0 Then 'Проверяем, если режим записи ключей включен, то
 GoSub DS1990 'считываем значение ключа
 If id[0] = $1 Then 'Если это - DS1990, то
 If Num = 255 Then 'если в памяти не записан ни один ключ, то
 addr=74 : edat = 0 'присваиваем адрес начала записи первого ключа
 EndIf 'и число, показывающее, куда записывать следующий ключ
 If Num = 0 Then 'Если в памяти уже записан один ключ, то
 addr=80 : edat = 1 'присваиваем адрес начала записи второго ключа
 EndIf 'и число, показывающее, куда записывать следующий ключ
 If Num = 1 Then 'Если в памяти уже записано два ключа, то
 addr=86 : edat = 2 'присваиваем адрес начала записи третьего ключа
 EndIf 'и число, показывающее, куда записывать следующий ключ
 If Num = 2 Then 'Если в памяти уже записано три ключа, то
 addr=92: edat = 3 'присваиваем адрес начала записи четвертого ключа
 EndIf 'и число, показывающее, куда записывать следующий ключ
 If Num = 3 Then 'Если в памяти уже записано четыре ключа, то
 addr = 74: edat = 0 'присваиваем адрес начала записи первого ключа
 EndIf 'и число, показывающее, куда записывать следующий ключ
 
 For I = 0 To 5
 ADDR_TEMP = addr + I
 date = id[I + 1]
 GoSub WRITE_ 'Теперрь записываем считанный ключ по указанному адресу
 Next
 ADDR_TEMP = 4: date = edat 'Записываем число, показывающее, куда записывать следующий ключ
 GoSub WRITE_ 'по адресу 4
 High LED 'Моргнем светодиодом, указывая пользователю, что запись
 DelayMS 1000 'ключа завершена
 Low LED
 EndIf
 GoTo WRITE_KEY 'переходим на начало
 EndIf 'Если не включен режим записи ключей
 DelayMS 2000 'то ожидаем 2 секунды перед началом работы сторожа
 CheckPhone: 'Инициализация
 GoSub TURN_LED 'Могрнем, показывая, что идет обмен с телефоном
 HSerOut ["AT" ,13]
 HSerIn 500, CheckPhone,[Wait("OK")]'Ждем ответа, если нет , то снова на CheckPhone
 CheckPhone2:
 GoSub TURN_LED 'то же самое, только
 HSerOut ["AT+CMGF=0" ,13] 'команда другая - включаем PDU формат
 HSerIn 500, CheckPhone2,[Wait("OK")]'Ждем ответа от телефона
 loop:
 DelayMS 900 'Задержка для видимости моргания светодиода
 GoSub DS1990 'Проверяем, вставлен ли ключ
 If id[0] = $1 Then 'Если поднесен ключ
 GoSub Read_ 'Сравниваем с записанными значениями
 EndIf
 SSSS:
 If Start_OXR = 1 Then 'Если включен режим охраны
 OPTION_REG.7 = 0 'Включаем подтягивающие резисторы
 LED = 1 'Зажигаем светодиод, отображая режим охраны
 If INPUT_1 = 1 Then 'И сразу проверяем канал охраны на разрыв
 If CH_1_ALLOW = 1 Then 'Если разрешено слежение за ним
 Gosub Zaderzh
                          If Start_OXR = 0 Then EEEE 'Если хозяин отключил охрану, то вернемсяSS = 6: ES = 13 'устанавливаем адрес начала и конца слова для SMS в EEPROM
 GoSub GO_EACH_CH 'и переходим на оповещение
 EndIf
 EndIf
              
              If INPUT_2 = 1 Then 'И сразу проверяем канал охраны на разрывIf CH_2_ALLOW = 1 Then 'Если разрешено слежение за ним
 Gosub Zaderzh
                          If Start_OXR = 0 Then EEEE 'Если хозяин отключил охрану, то вернемсяSS = 14: ES = 20 'устанавливаем адрес начала и конца слова для SMS в EEPROM
 GoSub GO_EACH_CH 'и переходим на оповещение
 EndIf
 EndIf
 
 EEEE:               OPTION_REG.7 = 1 'отключим подтяжку на portbLED = 0 '
             DelayMS 500 'погасим светодиодEndIf
 GoTo loop 'Начнем сначала
 
 
 GO_EACH_CH:
       LED = 1    If onSMS = 1 Then 'Если разрешена отправка SMS
 SN = 38: EN = 49 'Считаем
 GoSub SETNUM 'первый телефонный номер
 GoSub SendSMS 'и отправим на него SMS
 SN = 50: EN = 61 'Считаем
 GoSub SETNUM 'второй телефонный номер
 GoSub SendSMS 'и отправим на него SMS
 SN = 62: EN = 73 'Считаем
 GoSub SETNUM 'третий телефонный номер
 GoSub SendSMS 'и отправим на него SMS
 EndIf
 DelayMS 5000 'Задержка нужна, так как телефон не успевает отработать
 'команду отправки последнего SMS
 If onCall = 1 Then 'Если разрешен дозвон
 SN = 38: EN = 49 'считаем
 GoSub SETNUM 'первый телефонный номер
 GoSub Call_ 'и позвоним на него
 SN = 50: EN = 61 'считаем
 GoSub SETNUM 'второй телефонный номер
 GoSub Call_ 'и позвоним на него
 SN = 62: EN = 73 'считаем
 GoSub SETNUM 'третий телефонный номер
 GoSub Call_ 'и позвоним на него
 EndIf
 LED = 0 'выключим светодиод
 Return
 '-------------------------------------------------------------------------------------
 SendSMS: 'Начало подпрограммы кодирования текста в PDU формат
 j = 0
 For I = SS To ES
 char [j] = ERead I 'Считаем текст СМС в формате ASCII
 Inc j
 Next
 '-----Преобразуем в PDU
        tmp[1]=char[1] << 7 tmp[2]=char[2] << 6
 tmp[3]=char[3] << 5
 tmp[4]=char[4] << 4
 tmp[5]=char[5] << 3
 tmp[6]=char[6] << 2
 tmp[7]=char[7] << 1
 
 For z = 0 To 6
 pdu[z]=tmp[z + 1] + (char[z] >> z)
 Next z
 
 Check_: 'Начало отправки сообщения на указанный номер (PN[i]), в формате PDU (pdu[i])
        If CONTr = 2 Then  ret1  'Если произойдет сбой, то после первого раза остановимсяHSerOut ["AT+CMGS=22",13]'команда на отправку сообщения
         Inc CONTrHSerIn 5000, Check_,[Wait(">")]'ожидание подтверждения команды
 'Непосредственно отправка сообщения
 HSerOut ["0011FF0B91", PN[1],PN[0],PN[3],PN[2],PN[5],PN[4],PN[7],PN[6],PN[9],PN[8],PN[11],PN[10],_
 "0000AA","08",Hex2 pdu[0], Hex2 pdu[1], Hex2 pdu[2], Hex2 pdu[3], Hex2 pdu[4], Hex2 pdu[5], Hex2 pdu[6],Hex2 pdu[7],26]
 HSerOut [13]
          DelayMs 3000 
 ret1:   CONTr = 0Return 'Возврат из ПП отправки SMS 
 Call_:'ПП дозвона по указанному телефонному номеру (PN[i])          If CONTr = 2 Then  ret2   'Если произойдет сбой, то после первого раза остановимся         HSerOut ["ATD+",PN[0],PN[1],PN[2],PN[3],PN[4],PN[5],PN[6],PN[7],PN[8],PN[9],PN[10],";",13] 'Звоним...DelayMS 5000 'Задержка
 HSerOut ["AT+CPAS" ,13]'Проверка состояния телефона
          Inc CONTr  HSerIn 5000, Call_,[Wait("4")] 'Если состояние не то, которое нам нужно (вызов), то на метку Call_
 'чтобы попытаться еще раз
 For x = 1 To DELAY 'Даем время хозяину прослушать помещение
 DelayMS 1000
 Next
 HSerOut ["ATH",13] 'Отменяем вызов по окончанию
 ret2:   CONTr = 0Return
 
 WRITE_:
 EWrite ADDR_TEMP,[ date] 'Процедура записи переменных по указанным адресам
 Return
 
 Read_: 'ПП считывания кода ключа и сравнения с записанными в память ключами
 For z = 74 To 98 Step 6 'Ключи записаны последовательно с 74 ячейки по 98
 addr = z 'По 6 байт на каждый ключ
 For j = 0 To 5
 ID_real[j] = ERead addr + j 'Непосредственно считывание из памяти записанных ключей
 Next
 'Сравниваем только что считанные значения ключа с записанными:
 If ID_real[0]=id[1] And ID_real[1]=id[2] And ID_real[2]=id[3] And ID_real[3]=id[4] And ID_real[4]=id[5] And ID_real[5]=id[6] then
 'Если ключ совпадает с одним из записанных
 If Start_OXR = 1 Then 'то, если охрана включена
 Start_OXR = 0 'отключим ее
 LED = 0 'погасим светодиод
 Else 'Если же охрана выключена
 LED = 1 'Зажжем светодиод, указывая на начало постановки на охрану
 'DelayMS 25000 'Это время дается хозяину на выход из помещения
 Start_OXR = 1 'Включаем охрану
 EndIf
 GoTo EXIT_ 'выходим
 EndIf
 Next 'Если ключ не совпал с текущим записанным, то сравниваем со следующим
 EXIT_:
 Return
 
 DS1990:
 OWrite dq, 1, [$33] 'Процедура чтения кода ключа
 ORead dq, 0, [Str id\8] 'в переменную ID[i]
 Return
 
 TURN_LED: 'ПП моргания светодиодом
 LED = 1
 DelayMS 250
 LED = 0
 Return
 
 SETPARAM: 'ПП считывания параметров работы прибора
 flags = ERead 0 'Считаем флаги
 delrun = ERead 1 'Считаем задержки
 DELAY = ERead 2 'Считаем задержки
 ' numCall = ERead 3
 Num = ERead 4 'Считаем число, указывающее на кол-во уже записанных ключей
 ALARMFLAGS = ERead 5 'Считаем переменную установок тревоги
 Return
 
 SETNUM: 'ПП считывания телефонных номеров
 I = 0
 For x = SN To EN
 PN[I] = ERead x
 Inc I
 Next
 Return
 Zaderzh:         For I = 1 To delrun 'то задерживаемся на указанное времяHigh LED 'В это время, если зашел хозяин
 DelayMS 75 'ему дается возможность отключить охрану
 Low LED 'отображаем этот режим светодиодом
 DelayMS 100 '
 GoSub DS1990 'здесь хозяин может отключить охрану
 If id[0] = $1 Then
 GoSub Read_
 EndIf 'в нормальный режим
 Next
 ReturnEnd
 |