;25/06/2013_v3.3 ;Рабочая программа вольт/амперметра ;V.3.3.Добавлена индикация перегрузки по напряжению. ;V.3.2.Возобновлена засветка индикатора в 2 приема в связи с высоким ;потреблением зеленого индикатора. ;V.3.1.Изменена коррекция значения тока 1:1. ;Добавлено ограничение значения тока до 9,9В (перегрузка -,--) ;V.1.2.Добавлена фильтрация результата измерения. ;V.1.1.Откорректирован диапазон по току ; list p=16f676 __CONFIG _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BODEN_OFF & _PWRTE_OFF & _MCLRE_OFF & _BODEN_OFF & _CP_OFF & _CPD_OFF ERRORLEVEL -302,-306 ;======================================================== ; include include ; org RESET_V ; clrf PCLATH ;select program memory page 0 goto SETUP ; ;============================================================== ; ОБРАБОТКА ПРЕРЫВАНИЙ ;============================================================== ; org ISR_V ; InterruptCode: movwf WREG_TEMP ;save WREG swapf STATUS,W ;store STATUS in WREG clrf STATUS ;select file register bank0 movwf STATUS_TEMP ;save STATUS value movf PCLATH,W ;store PCLATH in WREG movwf PCLATH_TEMP ;save PCLATH value clrf PCLATH ;select program memory page0 movf FSR,W ;store FSR in WREG movwf FSR_TEMP ;save FSR value TMR0int movlw k movwf TMR0 ;коррекция TMR0 call DISPLAY ;вызов п/п индикации bcf INTCON,T0IF EndInt: movf FSR_TEMP,W ;get saved FSR value movwf FSR ;restore FSR movf PCLATH_TEMP,W ;get saved PCLATH value movwf PCLATH ;restore PCLATH swapf STATUS_TEMP,W ;get saved STATUS value movwf STATUS ;restore STATUS swapf WREG_TEMP,F ;prepare WREG to be restored swapf WREG_TEMP,W ;restore WREG without affecting STATUS retfie ;return from interrupt ; ;============================================= ; Таблица соответствия сегментов индикаторов ;============================================= LEDTABLE_A addwf PCL,F ; W + PC -> PC retlw b'00110100' ;0 retlw b'00010100' ;1 retlw b'00110010' ;2 retlw b'00110110' ;3 retlw b'00010110' ;4 retlw b'00100110' ;5 retlw b'00100110' ;6 retlw b'00110100' ;7 retlw b'00110110' ;8 retlw b'00110110' ;9 retlw b'00000010' ;'-' LEDTABLE_C addwf PCL,F ; W + PC -> PC retlw b'00100011' ;0 retlw b'00000000' ;1 retlw b'00000011' ;2 retlw b'00000001' ;3 retlw b'00100000' ;4 retlw b'00100001' ;5 retlw b'00100011' ;6 retlw b'00000000' ;7 retlw b'00100011' ;8 retlw b'00100001' ;9 retlw b'00000000' ;'-' ;============================================================== ; И Н И Ц И А Л И З А Ц И Я ;============================================================== ; SETUP CLRF PORTA ;очистка портов CLRF PORTC movlw b'00000111' movwf CMCON ;компаратор выключен Bank1 call 3FFh movwf OSCCAL ;калибровка тактового генератора movlw b'11000011' ;подтяжки выкл.,прерыв. по фронту movwf OPTION_REG ;предделитель перед таймером 1/16 movlw b'00000001' ;вход AN0 - аналоговый movwf ANSEL movlw TRIS_A ;RA0, RA3 - input movwf TRISA ; movlw TRIS_C_dot_OFF ;RC2 - input (точка выключена) movwf TRISC ; movlw b'01010000' ;частота преобразования Fosc/16 movwf ADCON1 clrf PIE1 Bank0 movlw b'10000001' ;вход RA0-аналоговый, АЦП включен movwf ADCON0 ; clrf INTCON ;все прерывания запрещены ; movlw 0x20 ;блок очистки РОН movwf FSR ;(первых 32 байт от 0х20 до 0х3F) clr_mem: clrf INDF ; incf FSR,f ; btfss FSR,6 ; goto clr_mem ; ; clrf TMR0 bsf INTCON,T0IE ;включаем прерывания по таймеру 0 bsf INTCON,GIE ; ; ;=============================================================================== ; ================ M A I N P R O G R A M ===================== ;=============================================================================== ; MAIN: measure call AD_CONVERTION ;АЦП-преобразование. Рез. в DH/DL ;прибавляем D к ADD bcf STATUS,C movf DL,w addwf ADD_L,f btfsc STATUS,C incf DH,f movf DH,w addwf ADD_H,f ;после 8 измерений сумма результатов делится на 8 для усреднения incf CCOUNTER,f btfsc CCOUNTER,3 ;счетчик измерений = 8? goto calc_result ;да, произвести расчет ;пауза между измерениями для исключения перемигивания ;младшего разряда call PAU50 ;пауза 40мс goto measure ; calc_result ;делим сумму на 8, результат заносим в DH/DL bcf STATUS,C rrf ADD_H,f rrf ADD_L,f bcf STATUS,C rrf ADD_H,f rrf ADD_L,f bcf STATUS,C rrf ADD_H,w movwf DH rrf ADD_L,w movwf DL ;очищаем регистры clrf CCOUNTER clrf ADD_L clrf ADD_H ;переходим к пересчету результата конкретного вида измерения btfss SW_SENSE ;режим измерения напряжения? goto CURRENT ;нет ;да VOLTAGE: bsf mode ;для получения диапазона 0-51,2 делим результат на 2 bcf STATUS,C rrf DH,f rrf DL,f calc_voltage ;производим обработку значения, которое не должно быть больше 500 ;то есть DH=1, DL=244 (01F4) movf DH,f SKIP_IF_NOZERO goto do_BCD ;DH=0, не обрабатываем результат movf DL,w sublw .244 ;244-DL > 0? SKIP_IF_NEGATIVE goto do_BCD ;DL<=244, не обрабатываем результат movlw .10 ;записываем ссылку на черточки в movwf D1 movwf D2 movwf D3 goto MAIN ; CURRENT: bcf mode ;отсекаем значения тока меньше 1 единицы movf DH,f SKIP_IF_ZERO goto calc_current decfsz DL,w goto calc_current clrf DL calc_current ;производим обработку значения, которое не должно быть больше 999 ;то есть DH=3, DL=231 (03E7) movf DH,w sublw b'00000011' SKIP_IF_ZERO ;проверяем DH на равество "3" goto do_BCD ;DH<3, не обрабатываем результат movf DL,w sublw .231 ;231-DL > 0? SKIP_IF_NEGATIVE goto do_BCD ;DL<=231, не обрабатываем результат movlw .10 ;записываем ссылку на черточки в movwf D1 movwf D2 movwf D3 goto MAIN ; do_BCD call BIN2BCD movf LED0,w movwf D3 movf LED1,w movwf D2 movf LED2,w movwf D1 goto MAIN ; ;\_______ _______/ ; ************************************************* ;********** S = U = B = R = O = U = T = I = N = E = S ********** ; ______*************************************************_______ ;/ \ ;================================================================ ;ПП ДИНАМИЧЕСКОЙ ИНДИКАЦИИ ;use: INDEX ;================================================================ DISPLAY ;гасим светодиоды movlw b'00011100' movwf PORTC clrf PORTA Bank1 movlw TRIS_C_dot_OFF movwf TRISC Bank0 ;проверяем индекс индикаторов ;INDEX=0 - младший разряд, порт А ;INDEX=1 - младший разряд, порт С ;....... ;INDEX=6 - перегрузка счетчика movf INDEX,W ; LEDIndex -> W sublw .5 ;проверяем: индекс меньше 6? SKIP_IF_NEGATIVE goto sel_cathode ;индекс меньше 6 clrf INDEX ;индекс =6, сбрасываем счетчик в 0 ;----------- sel_cathode: ;выбор отображаемого разряда movlw b'00000100' andwf INDEX,w ;INDEX=5 или 4? SKIP_IF_ZERO ;нет, проверяем дальше goto sel_MSD ;да, засвечиваем старший разряд movlw b'00000010' andwf INDEX,w ;INDEX=3 или 2? SKIP_IF_ZERO ;нет, засвечиваем младший разряд goto sel_CSD ;да, засвечиваем средний разряд sel_LSD Bank1 movlw TRIS_C_dot_ON movwf TRISC Bank0 bcf DIGIT_3 goto fire_LSD ;зажечь сегменты младшего разряда sel_CSD bcf DIGIT_2 goto fire_CSD ;зажечь сегменты среднего разряда sel_MSD bcf DIGIT_1 goto fire_MSD ;зажечь сегменты старшего разряда ;----------- ;зажигание сегментов индикатора fire_LSD btfss INDEX,0 ;выбор четверки сегментов для отображения goto fire_LSD_A fire_LSD_C movf D3,w call LEDTABLE_C iorwf PORTC,f goto display_end fire_LSD_A movf D3,w call LEDTABLE_A movwf PORTA goto display_end ; fire_CSD btfss INDEX,0 ;выбор четверки сегментов для отображения goto fire_CSD_A fire_CSD_C movf D2,w call LEDTABLE_C iorwf PORTC,f btfss mode ;режим измерения напряжения? goto display_end ;нет, измерение тока Bank1 ;да, засвечиваем точку во 2-м разряде movlw TRIS_C_dot_ON movwf TRISC Bank0 bsf coma goto display_end fire_CSD_A movf D2,w call LEDTABLE_A movwf PORTA goto display_end fire_MSD btfss INDEX,0 ;выбор четверки сегментов для отображения goto fire_MSD_A fire_MSD_C movf D1,w call LEDTABLE_C iorwf PORTC,f btfsc mode ;режим измерения напряжения? goto display_end ;нет, измерение тока Bank1 ;да, засвечиваем точку во 2-м разряде movlw TRIS_C_dot_ON movwf TRISC Bank0 bsf coma goto display_end fire_MSD_A movf D1,w call LEDTABLE_A movwf PORTA goto display_end ; display_end incf INDEX,f RETLW 0 ;============================================================== ;< П/П ЗАДЕРЖКИ ВРЕМЕНИ на 100мс, 50ms ;>use: COUNT,COUNT1 PAU100 movlw .130 movwf COUNT goto loopH PAU50 ; movlw .65 ;50ms movlw .52 ;40ms ; movlw .39 ;30ms movwf COUNT ; goto loopH loopH: decfsz COUNT,F goto loopL return loopL: clrf COUNT1 loop: decfsz COUNT1,F goto loop goto loopH ;/=============================================\ ; П/П ПРЕОБРАЗОВАНИЯ ДВУХБАЙТОВОГО ЧИСЛА ; В ПЯТИ-РАЗРЯДНОЕ ДВОИЧНО-ДЕСЯТИЧНОЕ ЧИСЛО ; вход - DL, DH; выход - LED0-LED4 ;>use: COUNT,TEMP ;\=============================================/ BIN2BCD bcf STATUS,C ; clear the carry bit movlw .16 movwf COUNT clrf LED2 clrf LED1 clrf LED0 loop16 rlf DL,F rlf DH,F rlf LED0,F rlf LED1,F rlf LED2,F decfsz COUNT,F ; goto adjDEC movf LED2,W ;разнос тетрад по байтам andlw 0x0F movwf LED4 ; LED4 - MSD swapf LED1,W andlw 0x0F movwf LED3 ; LED3 movf LED1,W andlw 0x0F movwf LED2 ; LED2 swapf LED0,W andlw 0x0F movwf LED1 ; LED1 movf LED0,W andlw 0x0F movwf LED0 ; LED0 - LSD return adjDEC movlw LED0 movwf FSR call adjBCD movlw LED1 movwf FSR call adjBCD movlw LED2 movwf FSR call adjBCD movlw LED3 movwf FSR call adjBCD goto loop16 adjBCD movlw 3 addwf 0,W movwf TEMP btfsc TEMP,3 ; test if result > 7 movwf 0 movlw 30 addwf 0,W movwf TEMP btfsc TEMP,7 ; test if result > 7 movwf 0 ; save as MSD retlw 0 ;============================================================== ;============================================================== ;ПП АЦП. Результат помещается в WREG ;use: TEMP AD_CONVERTION ; clrf TEMP ;пауза на время заряда С АЦП (100us) ;p_adc: decfsz TEMP,f ; goto p_adc bsf ADCON0,GO_DONE ;запускаем АЦП loopAD btfsc ADCON0,GO_DONE ;ожидаем окончания goto loopAD ;преобразования movf ADRESH,w ;результат записываем в DH/DL movwf DH Bank1 movf ADRESL,w Bank0 movwf DL return ;============================================================== ;============================================================== ;============================================================== ;============================================================== END