LIST p=12F629 #include __CONFIG (_MCLRE_OFF & _CP_OFF & _CPD_OFF & _PWRTE_OFF & _WDT_ON & _INTRC_OSC_NOCLKOUT & _BODEN_ON) #define COLD 1 ; лампа холодного света #define HOT 2 ; лампа теплого света #define UP 3 ; увеличение яркости #define DOWN 4 ; уменьшение яркости #define POWER 5 ; вкл\выкл #define MODE 0 ; выбор холодного\теплого света Reg_1 EQU 0x21 Reg_2 EQU 0x22 Reg_3 EQU 0x23 ; в данном регистре храним значение яркости светодиода во время работы Reg_4 EQU 0x24 Reg_5 EQU 0x25 ; в данном регистре храним значение яркости светодиода после выключения устройства org 2100h ; На стадии "прошивки", записываем в EEPROM-ячейку, de .254 ; с адресом 00h, число 254 (FE) константу определяющую яркость светодиода при первом включении устройства (.1 min - .254 max) ;;;;;;;;;;;;;;;;;;; ; старт программы ; ;;;;;;;;;;;;;;;;;;; org 0 goto START ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; подготовительные операции ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; START call 0x3FF ; копируем калибровочную константу bsf STATUS,5 ; переход в банк 1 movwf OSCCAL ; записываем калибровочную константу banksel TRISIO ; переходим в регистр TRISIO movlw b'00111001' ; настраиваем GP0-3-4-5 на вход movwf TRISIO ; -//- banksel WPU ; переходим в регистр WPU movlw b'00111001' ; включаем подтягивающие резисторы movwf WPU ; -//- banksel OPTION_REG ; переходим в регистр OPTION_REG movlw b'00001110' ; включаем предделитель перед WDT 1:16 movwf OPTION_REG ; -//- banksel INTCON ; переходим в регистр INTCON movlw b'00000000' ; глобальный запрет прерываний movwf INTCON ; -//- banksel VRCON ; переходим в регистр VRCON movlw .0 ; отключаем источник опорного напряжения movwf VRCON ; -//- banksel IOC ; переходим в регистр IOCB movlw b'00000000' ; запрет прерываний по изменению уровня сигнала на входах movwf IOC ; -//- bcf STATUS,5 ; переход в банк 0 ;читаем данные значения яркости светодиода из EEPROM READ bsf STATUS,5 ; переход в банк 1 movlw 0 ; Считывается содержимое movwf EEADR ; EEPROM-ячейки с адресом 00h. bsf EECON1,RD ; Разрешение чтения. movf EEDATA,W ; Считанный байт записывается в W. movwf Reg_5 ; W -> Reg_5. bcf STATUS,5 ; переход в банк 0 call Pause call Pause call Pause loop clrwdt ; сброс сторожевого таймера btfsc GPIO,POWER ; если на входе 1, то переход на "loop" (ждем поступления команды на включение) goto loop ; если 0 то данная команда пропускается bsf GPIO,COLD ; включаем холодный свет ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Зажигаем светодиод до заданной яркости ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; bcf STATUS,Z ; сбрасываем флаг Z movlw .1 ; начинаем разжигание светодиода с минимальной яркости movwf Reg_3 ; -//- call pwm inc incf Reg_3 ; увеличиваем на 1 содержимое 3 регистра call pwm q btfss GPIO,UP ; если на входе 0, то переход в подпрограмму увеличения яркости светодиода call UPS ; пропускаем если 1 btfss GPIO,DOWN ; если на входе 0, то переход в подпрограмму уменьшения яркости светодиода call DOWNS ; пропускаем если 1 movf Reg_5,W ; копируем в W содержимое 5 регистра xorwf Reg_3,W ; проверяем равно ли значение 3 регистра содержимому регистра W btfss STATUS,Z ; проверяем значение флага Z, если =0 то значение W и Reg_3 не равны и исполняется следующая команда, goto inc ; если =1 то значение W и Reg_3 равны и следующая команда пропускается bcf STATUS,Z ; сбрасываем флаг Z call pwm btfsc GPIO,POWER ; если на входе 1, то переход на "q" => закольцовка goto q ; пропускаем если поступила команда отключения ;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Гасим светодиод до нуля ; ;;;;;;;;;;;;;;;;;;;;;;;;;;; dec decf Reg_3 ; вычитаем 1 из 3 регистра call pwm movlw .1 ; гасим светодиод до этого значения, т.е. минимальной яркости xorwf Reg_3,W ; сравниваем значение W и регистра 3 btfss STATUS,Z ; проверяем значение флага Z, если =0 то значение W и Reg_3 не равны и исполняется следующая команда, ;если =1 то значение W и Reg_3 равны и следующая команда пропускается goto dec ; -//- call pwm call Pause call Pause call Pause call Pause ;записываем в EEPROM значение яркости светодиода, которое будет храниться после отключения устройства WRITE bsf STATUS,5 ; переход в банк 1 movlw 0 ; Выбор адреса той EEPROM-ячейки, в которую movwf EEADR ; будет произведена запись. В данном случае, это ячейка с адресом 00h, но можно назначить и другой адрес. movf Reg_5,W ; Копирование данных, из регистра Reg_5, movwf EEDATA ; в регистр EEDATA (то, что в нём "лежит", в дальнейшем будет записано в выбранную EEPROM-ячейку). bsf EECON1,WREN ; "Глобальное" разрешение записи. movlw 55h ; Обязательная последователь команд movwf EECON2 ; -//- movlw 0AAh ; -//- movwf EECON2 ; -//- bsf EECON1,WR ; "Запуск в работу" аппаратной процедуры записи. ;Пояснение: по окончании записи, бит WR аппаратно сбрасывается в 0 (блокировка "запуска в работу" аппаратной процедуры записи). btfsc EECON1,WR ; Запись завершена или нет? goto $-1 ; Если не завершена, то проверка производится снова. ; Если завершена, то выход из "плавающей" задержки. bcf EECON1,WREN ; "Глобальный" запрет записи. bcf STATUS,5 ; переход в банк 0 goto loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Подпрограмма увеличения яркости светодиода если нажата кнопка UP ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; UPS bcf STATUS,Z ; сбрасываем флаг Z movlw .254 ; константа максимальной яркости светодиода, копируем в регистр W xorwf Reg_5,W ; сверяем содержание регистров W и Reg_5 btfss STATUS,Z ; результат 1, если содержимое регистров равно -> пропускаем следующую команду incf Reg_5 ; увеличиваем на 1 содержимое 5 регистра, если содержание регистров W и Reg_5 не равно bcf STATUS,Z ; сбрасываем флаг Z return ; возвращаемcя по стеку обратно ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; Подпрограмма уменьшения яркости светодиода если нажата кнопка DOWN ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DOWNS bcf STATUS,Z ; сбрасываем флаг Z movlw .2 ; константа минимальной яркости светодиода, копируем в регистр W xorwf Reg_5,W ; сверяем содержание регистров W и Reg_5 btfss STATUS,Z ; результат 1, если содержимое регистров равно -> пропускаем следующую команду decf Reg_5 ; уменьшаем на 1 содержимое 5 регистра, если содержание регистров W и Reg_5 не равно bcf STATUS,Z ; сбрасываем флаг Z movf Reg_5,W ; копируем в W содержимое 5 регистра xorwf Reg_3,W ; проверяем равно ли значение 3 регистра содержимому регистра W btfss STATUS,Z ; результат 1, если содержимое регистров равно -> пропускаем следующую команду decf Reg_3 ; уменьшаем на 1 содержимое 3 регистра, если содержание регистров W и Reg_5 не равно bcf STATUS,Z ; сбрасываем флаг Z return ; возвращаемcя по стеку обратно ;;;;;;;;;;;;;;;;;;;;; ; Подпрограмма ШИМа ; ;;;;;;;;;;;;;;;;;;;;; pwm movlw .3 ; константа определяющая время нарастания(гашения) яркости светодиода(чем больше, тем продолжительней инерционность) movwf Reg_4 ; копируем константу в 4 регистр wr clrwdt ; сброс сторожевого таймера movf Reg_3,W ; копируем в W содержимое 3 регистра movwf Reg_2 ; копируем содержимое регистра W в 2 регистр movwf Reg_1 ; копируем содержимое регистра W в 1 регистр comf Reg_1,F ; инвертируем содержимое 1 регистра wrr decfsz Reg_1,F ; вычитаем 1 из 1 регистра, если результат не = 0, то исполняется следующая команда goto wrr ; если результат = 0, то данная команда пропускается и программа исполняется далее bsf GPIO,COLD ; зажигаем холодный светодиод wrrr decfsz Reg_2,F ; вычитаем 1 из 2 регистра, если результат не = 0, то исполняется следующая команда goto wrrr ; если результат = 0, то данная команда пропускается и программа исполняется далее bcf GPIO,COLD ; гасим светодиод next5 decfsz Reg_4,F ; вычитаем 1 из 4 регистра, если результат не = 0, то исполняется следующая команда goto wr ; если результат = 0, то данная команда пропускается и программа исполняется далее return ; возвращаемcя по стеку обратно :-) ;delay = 150'000 machine cycles Pause movlw .140 movwf Reg_1 movlw .195 movwf Reg_2 wr1 decfsz Reg_1,F goto wr1 clrwdt decfsz Reg_2,F goto wr1 return end