📄 pmeter.asm
字号:
LIST P=16C71, F=INHX8M, R=HEX, C=132, N=804, T=OFF
TITLE "AC Power Meter - Rick May"
;******************************************************************************
;* D E C L A R A T I O N S *
;******************************************************************************
include "16cXX.h"
; Register Assignments for MATH routines
; --------------------------------------
count equ 0X13
temp equ 0X14
ACCaLO equ 0X15
ACCaHI equ 0x16
ACCbLO equ 0x17
ACCbHI equ 0x18
ACCcLO equ 0x19
ACCcHI equ 0x1A
ACCdLO equ 0x1B
ACCdHI equ 0x1C
; Register Assignments
; --------------------
AY_DP EQU 0X1D ; Decimal point Array used by AYDISP1, AYDISP2
AY_TEMP EQU 0X1E ; temp reg used by AYDIGIT
AY_CNT EQU 0X1F ; shift count used by AYDIGIT
TIC EQU 0x20 ; Number of 10ms intervals/sec 0-99.
SEC EQU 0x21 ; Number of seconds 0-59.
MIN EQU 0x22 ; Number of minutes.
SAV_W EQU 0x23 ; PLACE TO SAVE W DURING INT
SAV_ST EQU 0x24 ; PLACE TO SAVE STAT DURING INT
CNTR1 EQU 0X25 ; DELAY COUNT used by DELAY
CNTR2 EQU 0X26 ; DELAY COUNT used by DELAY
sHI EQU 0X27 ; 1 second energy accumulator, updated in ISR
sLO EQU 0X28
eHI EQU 0X29 ; Master energy accumulator, e, updated in bkgrnd
eMED EQU 0X2A
eLO EQU 0X2B
PWR EQU 0X2C
ADcnt EQU 0X2D ; Count used in A/D converter operations, used by ISR
MODE EQU 0X2F
;
; Bit Definitions
; ---------------
#define mode_sw _portb,0 ; SWITCH DEFINITIONS
#define res_sw _portb,1
#define ad_cs _portb,2 ; NATIONAL ADC0831 A/D Converter DEFINITIONS
#define ad_clk _portb,3
#define ad_dat _portb,4
#define ay_dat _portb,5 ; MICROCHIP AY0438 LCD Driver DEFINITIONS
#define ay_clk _portb,6
#define ay_ld _portb,7
#define ay_arr_out _porta,2 ; Direct PIC Drive of LCD backplane
#define ay_bp _porta,3 ; and LCD Arrow segment
;
; BIT DEFINITONS OF decimal point control reg used by AYDISP1, AYDISP2
;
; +--7--+--6--+--5--+--4--+--3--+--2--+--1--+--0--+
; AY_DP | arr | l | arr | arr | l | dp2 | dp3 | dp4 |
; | | slow| fast| slow| | | | |
; +-----+-----+-----+-----+-----+-----+-----+-----+
#define ay_dp4 AY_DP,0
#define ay_dp3 AY_DP,1
#define ay_dp2 AY_DP,2
#define ay_l AY_DP,3
#define ay_arr_flash_slow AY_DP,4
#define ay_arr_flash_fast AY_DP,5
#define ay_l_flash_slow AY_DP,6
#define ay_arr AY_DP,7
;
; BIT DEFINITONS OF mode reg
;
; +--7--+--6--+--5--+--4--+--3--+--2--+--1--+--0--+
; MODE |no_d1|no_d2| 1s_ |500ms|1s | X | MODE |
; | | | flag|_flag|flag2| | |
; +-----+-----+-----+-----+-----+-----+-----+-----+
#define no_d1 MODE,7
#define no_d2 MODE,6
#define 1s_flag MODE,5
#define 500ms_flag MODE,4
#define 1s_flag2 MODE,3
;******************************************************************************
;* R E S E T A N D I N T E R R U P T V E C T O R S *
;******************************************************************************
ORG 0x00 ; RESET VECTOR
GOTO MAIN_INIT
ORG 0x04 ; INTERRUPT VECTOR
GOTO INT_SERVICE
;******************************************************************************
;* I N C L U D E M A T H L I B R A R Y R O U T I N E S *
;******************************************************************************
include "pm_math.asm"
MAIN_INIT
;******************************************************************************
;* P O R T _ I N I T I A L I Z A T I O N *
;******************************************************************************
bcf _gie ; DISABLE GLOBAL INTERRUPTS
bsf _rp0 ; SET PAGE 1 for _trisa, TRISB, OPTION
movlw b'10' ; PORTA RA0-1 ANALOG, RA2-3 DIG INPUTS
movwf _adcon1
movlw b'00011' ; RA4-RA2 = OUT RA1,RA0 = IN
movwf _trisa
movlw b'00010011' ; RB7-5=OUT,RB4=IN,RB3-2=OUT,RB1-RB0=IN
movwf _trisb
movlw b'00000111' ; PortB pullups = on; RTCC=int; Prescale=256
movwf _option
bcf _rp0 ; Reset Back to Page 0
movlw b'10000101' ; OSC/32 CLK, CH=0, GO,NOINT,AD=ON
movwf _adcon0
clrf AY_DP ; Initialize AY LCD stuff to defaults
bsf ay_clk
bsf ay_dat
bcf ay_ld
bcf ay_arr
bcf ad_clk
bsf ad_cs
movlw .32 ; Clear all segments
movwf AY_CNT ; STORE
AYINIT bsf ay_clk ; Raise clk
bcf ay_dat ; Lower data - all zero data
bcf ay_clk ; Lower clk
decfsz AY_CNT ; MOVE TO NEXT BIT
goto AYINIT
bsf ay_ld ; Done. Raise ay_ld to latch data to AY
nop
bcf ay_ld
clrf TIC
clrf SEC
clrf MIN
clrf sHI
clrf sLO
clrf eHI
clrf eMED
clrf eLO
clrf PWR
clrf MODE
movlw .217 ; 256-39=217 = 10ms timeout
movwf _rtcc ; preload timer.
bsf _rtie ; enable timer interrupts
bsf _gie ; global interrupt enable
goto main_loop
org 0x100
;******************************************************************************
;* M A I N P R O G R A M L O O P *
;******************************************************************************
main_loop
;------------------------------------------------------
; Scan Switches
;------------------------------------------------------
btfsc res_sw ; Using internal pullups 0=down
goto reset_sw_done
movlw .65 ; Wait 50ms
call DELAY
btfsc res_sw ; Using internal pullups 0=down
goto reset_sw_done
clrf TIC
clrf SEC
clrf MIN
clrf eLO
clrf eMED
clrf eHI
bcf no_d1
bcf no_d2
reset_sw_done
btfsc mode_sw ; Using internal pullups 0=down
goto mode_sw_done
movlw .65 ; Wait 50ms
call DELAY
btfsc mode_sw ; Using internal pullups 0=down
goto mode_sw_done
movf MODE,w ; put mode in W reg
addlw .1 ; Increment to next mode (2bit cntr)
andlw 0x03 ; mask off any carry that may have happened
;
; Now, new MODE is in W reg
;
rrf MODE ; this shifting wipes out existing 2bit
bcf _carry ; counter.
rrf MODE
bcf _carry
rlf MODE
rlf MODE
;
; Now restore other bits in MODE, recall new counter is in W
;
iorwf MODE ; 'or-in' other bits in MODE reg.
movwf MODE
movlw .130 ; wait 100ms since we changed modes
call DELAY ; don't want to slide through a mode
mode_sw_done
;
; Check for 1s if expired, Update Accumulator e
;
btfss 1s_flag2 ; if 1s up, then do block below
goto not_1s_exp
bcf 1s_flag2 ; background clears, isr sets.
movf sLO,W ; ACCb is numerator
movwf ACCbLO
movf sHI,W
movwf ACCbHI
clrf sLO ; these accumulators can be reset now
clrf sHI
CLRF ACCaHI ; ACCa is denominator
movlw .36
movwf ACCaLO
call D_divS ; result in ACCb e=s/36
;
; ;do triple precision accumulate of e, energy
;
movf ACCbLO,w ; Addition ( ACCb + e -> e )
addwf eLO ; add lsb
btfsc _carry ; add in carry
goto lo_carry ; yep, we had carry out of Lo byte
goto med_add ; No carry out of lo byte
lo_carry
incf eMED ; adjust for carry
btfsc _z
incf eHI
med_add
movf ACCbHI,w ; Now do the MED byte
addwf eMED ; add msb
btfsc _carry
incf eHI
not_1s_exp
;------------------------------------------------------
; Dispatcher
;------------------------------------------------------
movlw HIGH Mode0
movwf _pclath
movf MODE,w
andlw 0x03
addwf _pcl
goto Mode0
goto Mode1
goto Mode2
goto Mode3
Mode0
;------------------------------------------------------
; Mode0 = Instantenous Power Measurement
;------------------------------------------------------
movlw .13 ; wait 10ms as to not over-display
call DELAY
clrf AY_DP ; no flashing colons or arrow
btfss 500ms_flag ; if 500ms up, then do block below
goto mode0_done
bcf 500ms_flag ; background clears, isr sets.
btfss 1s_flag
goto half_sec_accum
goto full_sec_accum
half_sec_accum
movf sLO,W ; ACCb is numerator
movwf ACCbLO
movf sHI,W
movwf ACCbHI
clrf ACCaHI ; ACCa is denominator
movlw .5 ; 50 samples in 500 ms
movwf ACCaLO
call D_divS ; result in ACCb pwr=(s/50)*10 simple avg.
call B2_BCD ; ACCd,ACCa = B2_BCD(ACCb)
call AYDISP2 ; display low 4bytes
goto mode0_done
full_sec_accum
bcf 1s_flag ; clear flag that is set by isr
movf sLO,W ; ACCb is numerator
movwf ACCbLO
movf sHI,W
movwf ACCbHI
clrf sLO ; clear these accumulators used by isr
clrf sHI ; clear these accumulators used by isr
clrf ACCaHI ; ACCa is denominator
movlw .10 ; 100 samples in 1 s
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -