LIST p=16f84a ; Developer - Uladzimir Karalenka, site: tokes.ru ; 2013 yaer. ; Организовать WDT не помешало бы. ; Перечисление регистров специального назначения из нулевого банка STATUS equ 03h PORTB equ 06h EEDATA equ 08h EEADR equ 09h INTCON equ 0bh ; Перечисление регистров специального назначения из первого банка OPTIONR equ 01h TRISB equ 06h ; Для работы на вход нужно выставить 1 в номере порта EECON1 equ 08h ; Регистр для работы с флеш-памятью EECON2 equ 09h ; Регистр для работы с флеш-памятью ; Перечисление битов регистров специального назначения RBPU equ 7 ; Подтягивающие резисторы порта B (0-подтяжка включена) RP0 equ 5 ; Банк (0-нулевой банк) RB1 equ 1 ; Первый бит порта Б (на авто) RB2 equ 2 ; Второй бит порта Б (на телефон) RB3 equ 3 ; Третий бит порта Б (на сенсор) RB4 equ 4 ; Четвёртый бит порта Б (на бузер) GIE equ 7 ; Глобальное разрешение прерываний (0 - все прерывания запрещены) flagZ equ 2 ; Флаг нулевого результата RD equ 0 ; Бит инициализации чтения из памяти WR equ 1 ; Бит инициализации записи в память WREN equ 2 ; Бит разрешения записи (1=разрешить) ; Перечисление регистров общего назначения calibrate equ 0ch ; Значение времени заряда без доп. ёмкости в микросекундах trigg equ 0dh ; Триггер переключателя входов currently equ 0eh ; Текущее время заряда конденсатора 3 вывода порта Б counterTime equ 0fh ; Счётчик повторений инкремента сравнения counterInc equ 10h ; Инкрементируемое значение проверки разницы diffValue equ 11h ; Значение разницы текущее diffValuer equ 12h ; Значение разницы текущее buzz equ 13h ; Счётчик для триггера бузера buzzTime equ 14h ; Счётчик для времени бузера ; Задание значений EEPROM при прошивке org 2100h ; Запись в EEPROM при прошивке de .0 ; Нуль в первый адрес памяти .0 org 0 ; Начало программы goto start start bcf INTCON,GIE ; Глобальный запрет прерываний clrf calibrate ; Калибровка сенсора при включении: ; Зарядить (переключить на вход и в Hi-z) bsf STATUS,RP0 ; Переключение банка на первый movlw B'00001000' ; Закладка работы портов movwf TRISB ; Установка на вход третьего вывода PORTB bsf OPTIONR,RBPU ; Выключить подтягивающие резисторы bcf STATUS,RP0 ; Переключение банка на нулевой ; Посчитать время заряда CountTimeF btfsc PORTB,RB3 ; Установлен или сброшен третий бит регистра порта б goto WrTmCalibr ; Если бит =1 выполнить эту инструкцию incf calibrate,f ; Иначе (бит =0) выполнить эту goto CountTimeF ; Перейти обратно на счётчик ; Разрядить установкой на выход и нуля WrTmCalibr bsf STATUS,RP0 ; Переключение банка на первый movlw B'00000000' ; Закладка работы портов movwf TRISB ; Установка на выход третьего вывода PORTB bcf STATUS,RP0 ; Переключение банка на нулевой bcf PORTB,3 ; Разряд конденсатора на внутреннюю цепь ; Чтение и установка предыдущего состояния портов movlw .00 ; Адрес памяти movwf EEADR ; Address to read bsf STATUS,RP0 ; Bank 1 bsf EECON1,RD ; EE Read bcf STATUS,RP0 ; Bank 0 movfw EEDATA ; W = EEDATA movwf trigg ; Запись регистра trigg btfsc trigg,0 ; Проверка нулевого бита регистра trigg goto one ; If last=1 then goto "one" goto zero ; If last=0 then goto "zero" ; Калибровка завершена, время первого заряда (при заряде без доп. ёмкости тела) записано в регистр calibrate ; Теперь мы готовы вновь запускать заряд конденсатора и счётчик ; Проверка на совпадение откалиброванного значения и текущего ; Тоесть заряд: CicleCharge clrf currently ; Сбросить текущее значение счётчика bsf STATUS,RP0 ; Переключение банка на первый movlw B'00001000' ; Закладка работы портов movwf TRISB ; Установка на вход третий вывод PORTB bcf STATUS,RP0 ; Переключение банка на нулевой ; Считаем время заряда CountTimeS btfsc PORTB,RB3 ; Установлен или сброшен третий бит регистра порта б goto WrTmCurrent ; Если бит =1 выполнить эту инструкцию incf currently,f ; Иначе (бит =0) выполнить эту goto CountTimeS ; Перейти обратно на счётчик ; Запомнить время заряда, записать в память ; Разрядка установкой на выход и нуля WrTmCurrent bsf STATUS,RP0 ; Переключение банка на первый movlw B'00000000' ; Закладка работы портов movwf TRISB ; Установка на выход третьего вывода PORTB bcf STATUS,RP0 ; Переключениe банка на нулевой bcf PORTB,3 ; Разряд конденсатора на внутреннюю цепь ; Если значения совпадают или не больше counterInc - goto cicle, если не совпадают - goto switch clrw ; Очищаем Wreg movfw calibrate ; Копируем в W значение текущего времени заряда subwf currently,w ; Вычитаем текущее время из откалиброванного movwf diffValue ; Запись разницы в регистр btfss STATUS,flagZ ; Проверяем Z goto preswitch ; Переходим в ПП предпереключения goto CicleCharge ; Если clear - перейти к следующей зарядке (бит Z установится в 1) ; Как минимум это можно было оформить циклом: preswitch decf diffValue ; Если не ноль (разница есть) btfss STATUS,flagZ ; Проверяем Z goto preswitch2 ; Переходим в ПП предпереключения goto CicleCharge ; Если clear - перейти к следующей зарядке (бит Z установится в 1) preswitch2 decf diffValue ; Если не ноль (разница есть) btfss STATUS,flagZ ; Проверяем Z goto preswitch3 ; Переходим в ПП предпереключения goto CicleCharge ; Если clear - перейти к следующей зарядке (бит Z установится в 1) preswitch3 decf diffValue ; Если не ноль (разница есть) btfss STATUS,flagZ ; Проверяем Z goto switch ; Переходим в ПП предпереключения goto CicleCharge ; Если clear - перейти к следующей зарядке (бит Z установится в 1) ; Считывание из памяти предыдущего состояния switch bcf STATUS,RP0 ; Bank 0 movlw .00 ; movwf EEADR ; Address to read bsf STATUS,RP0 ; Bank 1 bsf EECON1,RD ; EE Read bcf STATUS,RP0 ; Bank 0 movfw EEDATA ; W = EEDATA ; Считали, теперь инкрементируем movwf trigg incf trigg,f ; Для установки нового значения переключения btfsc trigg,0 ; Проверка нулевого бита trigg goto one ; If last=1 then goto "one" goto zero ; If last=0 then goto "zero" one movlw b'00000100' ; Установить вход с телефона, запретить с авто movwf PORTB goto write zero movlw b'00000010' ; Установить вход с авто, запретить вход с телефона, goto after movwf PORTB goto write ; Установку произвели, теперь необходимо записать текущую константу в память. Запись: write movlw .00 ; Как по даташиту: movwf EEADR ; пишем адрес... movfw trigg ; movwf EEDATA ; и данные, которые хотим записать bsf STATUS,RP0 ; bank 1 bsf EECON1,WREN ; Разрешить запись movlw 055h ; Required Sequence (обязательная последовательность команд при записи) movwf EECON2 ; Required Sequence (обязательная последовательность команд при записи) movlw 0AAh ; Required Sequence (обязательная последовательность команд при записи) movwf EECON2 ; Required Sequence (обязательная последовательность команд при записи) bsf EECON1,WR ; Начать запись postwrite btfsc EECON1,WR ; Задержка до окончания процесса записи goto postwrite ; Сигнал об окончании цикла (переключение сработало) movlw .130 movwf buzzTime q1 decfsz buzzTime goto startBuzz goto mute startBuzz movlw .255 movwf buzz bsf PORTB,RB4 Buzz decfsz buzz,f goto Buzz movlw .255 movwf buzz bcf PORTB,RB4 Buzz2 decfsz buzz,f goto Buzz2 goto q1 mute decfsz buzzTime goto mute ; Не стал заморачиваться с циклом, скопировал :) movlw .130 movwf buzzTime q2 decfsz buzzTime goto startBuzz2 goto gocicle startBuzz2 movlw .255 movwf buzz bsf PORTB,RB4 Buzz3 decfsz buzz,f goto Buzz3 movlw .255 movwf buzz bcf PORTB,RB4 Buzz4 decfsz buzz,f goto Buzz4 goto q2 gocicle goto CicleCharge ; go to cicle end