PIC16F84单片机做的频率计

发布者:EnchantingEyes最新更新时间:2017-12-06 来源: eefocus关键字:PIC16F84  单片机  频率计 手机看文章 扫描二维码
随时随地手机看文章

;************************************************************************* 

;    Original header file for PIC 16F84 & AKIZUKI’s assembler. 
;    Copyright (c) 1998 by 32 Technical Laboratory (JG6DFK/QRP). 
;    All rights reserved. 

;************************************************************************* 

        .16f84 

;------------------------------------------------------------------------- 
; Register definitions of bank 0. 
;------------------------------------------------------------------------- 

indf        equ    00h    ; Data I/O port for indirect addressing. 
tmr0        equ    01h    ; 8bits real-time cLOCk/counter. 
pcl        equ    02h    ; Low order 8bits of the program counter. (PC) 
status        equ    03h    ; Status register. 
fsr        equ    04h    ; Indirect data memory address pointer 0. 
porta        equ    05h    ; I/O ports A. (= RA0 to RA4) 
portb        equ    06h    ; I/O ports B. (= RB0 to RB7) 
ra        equ    05h    ; Same as PORTA. 
rb        equ    06h    ; Same as PORTB. 
eEDAta        equ    08h    ; EEPROM data register. 
eeadr        equ    09h    ; EEPROM address register. 
pclath        equ    0Ah    ; Write buffer for upper 5 bits of the PC. 
iNTCon        equ    0Bh    ; Interrupt control register. 

;------------------------------------------------------------------------- 
; Register definitions of bank 1. 
;------------------------------------------------------------------------- 

option        equ    01h    ; (= 81h) Option register. 
trISA        equ    05h    ; (= 85h) I/O ports A data direction register. 
trisb        equ    06h    ; (= 86h) I/O ports B data direction register. 
eecon1        equ    08h    ; (= 88h) EEPROM data memory R/W status register. 
eecon2        equ    09h    ; (= 89h) I/O port for EEPROM data memory. 

;------------------------------------------------------------------------- 
; Others. 
;------------------------------------------------------------------------- 

; ----- For status register. 

irp        equ    7    ; Register bank select bit for indirect addressing. 
rp1        equ    6    ; RP1:RP0  00 = Bank 0, 01 = Bank 1. 
rp0        equ    5    ;          10 = Bank 2, 03 = Bank 3. 
to        equ    4    ; Time-out bit. 
pd        equ    3    ; Power-down bit. 
z        equ    2    ; Zero bit. 
dc        equ    1    ; Digit carry or bollow bit. 
c        equ    0    ; Carry or borrow bit. 

; ----- For interrupt control register. 

gie        equ    7    ; Global interrupt enable bit. 
eeie        equ    6    ; EEPROM write complete interrupt enable bit. 
t0ie        equ    5    ; TMR0 overflow interrupt enable bit. 
inte        equ    4    ; RB0/INT interrupt enable bit. 
rbie        equ    3    ; RB port change interrupt enable bit. 
t0if        equ    2    ; TMR0 overflow interrupt flag bit. 
intf        equ    1    ; RB0/INT interrupt flag bit. 
rbif        equ    0    ; RB port change interrupt flag bit. 

; ----- For option register. 

rbpu        equ    7    ; I/O ports B pull-up disable bit. 
intedg        equ    6    ; Interrupt edge select bit. 
t0cs        equ    5    ; TMR0 clock source select bit. 
t0se        equ    4    ; TMR0 source edge select bit. 
psa        equ    3    ; Prescaler Assignment bit. 
ps2        equ    2    ; PS2:PS0 = Prescaler rate select bits. 
ps1        equ    1    ;  For TMR0 = 1:2 to 1:256. 
ps0        equ    0    ;      WDT  = 1:1 to 1:128. 

; ----- For I/O ports A. (RA) 

ra4        equ    4    ; RA4/T0CKI. 
t0cki        equ    4    ; Same as ’ra4’. 
ra3        equ    3    ; RA3. 
ra2        equ    2    ; RA2. 
ra1        equ    1    ; RA1. 
ra0        equ    0    ; RA0. 

; ----- For I/O ports B. (RB) 

rb7        equ    7    ; RB7. 
rb6        equ    6    ; RB6. 
rb5        equ    5    ; RB5. 
rb4        equ    4    ; RB4. 
rb3        equ    3    ; RB3. 
rb2        equ    2    ; RB2. 
rb1        equ    1    ; RB1. 
rb0        equ    0    ; RB0. 
int        equ    0    ; Same as ’rb0’. 

; ----- For EEPROM control register. (EECON1) 

eeif        equ    4    ; EEPROM write operation interrupt flag bit. 
wrerr        equ    3    ; EEPROM write error flag bit. 
wren        equ    2    ; EEPROM write enable bit. 
wr        equ    1    ; EEPROM write control bit. 
rd        equ    0    ; EEPROM read control bit. 

; ----- For general 

w        equ    0    ; Destination selector. (Working register) 
f        equ    1    ; Destination selector. (Register file) 
;************************************************************************* 

;    SOFtware for Frequency Counter model PIC-FC1. 
;    Version 1.00. 

;    Copyright (c) 1999 by 32 Technical Laboratory. (JG6DFK/QRP) 
;    All rights reserved. 

;************************************************************************* 

; I/O assignment: 
;    RA4 (PIN  3) Input.                (I) 
;    RA3 (pin  2) LCD Data #3.            (O) 
;    RA2 (pin  1) LCD Data #2.            (O) 
;    RA1 (pin 18) LCD Data #1.            (O) 
;    RA0 (pin 17) LCD Data #0.            (O) 
;    RB7 (pin 13) LCD Load Enable.            (O) 
;    RB6 (pin 12) LCD Register Select.        (O) 
;    RB5 (pin 11) Display Mode.            (I) 
;    RB4 (pin 10) External prescaler mode.         (I) 
;    RB3 (pin  9) Internal prescaler mode #1.    (I) 
;    RB2 (pin  8) Internal prescaler mode.#0.    (I) 
;    RB1 (pin  7) Gate time #1.            (I) 
;    RB0 (pin  6) Gate time #0.            (I) 


        .include    16f84_32.h 

        .osc        xt        ; Clock = 10 MHz
        .wdt        off 
        .pwrt        on 
        .protect    off 

        id    0100h            ; = Version No. 

;------------------------------------------------------------------------- 
; Equations. 
;------------------------------------------------------------------------- 

; ----- I/O difinitions. 

LCD_LE        equ    rb7            ; LCD load enable. 
LCD_RS        equ    rb6            ; LCD register select. 

I_SELDSP    equ    rb5            ; Display mode       select SW. 
I_EXTPSC    equ    rb4            ; External prescaler select SW. 
I_INTPS1    equ    rb3            ; External prescaler select SW #1. 
I_INTPS0    equ    rb2            ; External prescaler select SW #0. 
I_SELRS1    equ    rb1            ; Resolution         select SW #1. 
I_SELRS0    equ    rb0            ; Resolution         select SW #0. 

; ----- Constants. 

FRES_1        equ    0            ; Resolution mode =   1 Hz. 
FRES_10        equ    1            ;                    10 Hz. 
FRES_100    equ    2            ;                   100 Hz. 
FRES_1000    equ    3            ;                     1 kHz. 

DSP_FREQ    equ    0            ; Display mode = frequency. 
DSP_LENG    equ    1            ;                wave length. (X.XXX m) 

IPSC_1        equ    0            ; Internal prescaler = 1:1. 
IPSC_4        equ    1            ;                      1:4. 
IPSC_8        equ    2            ;                      1:8. 
IPSC_16        equ    3            ;                      1:16. 

TMR0_1        equ    00101000b        ; Prescaler rate for TMR0 = 1:1. 
TMR0_4        equ    00100001b        ;                           1:4. 
TMR0_8        equ    00100010b        ;                           1:8. 
TMR0_16        equ    00100011b        ;                           1:16. 

XPSC_OFF    equ    0            ; External prescaler = disabLED
XPSC_ON        equ    1            ;                      enabled. 

XPSC_RATE    equ    64            ; External prescaler rate. 

MAXDIGIT    equ    10            ; Max digit = "XXXXXXX.XXX". 

; ----- LCD functions. 

L_SELDR        equ    0            ; LCD data register select. 

L_FNCSET    equ    00101000b        ; LCD function set. 
L_ENTSET    equ    00000110b        ; LCD entry mode set. 
L_DSPCLR    equ    00000001b        ; LCD display clear. 
L_DSPOFF    equ    00001000b        ; LCD display OFF. 
L_DSPON        equ    00001100b        ; LCD display ON. 
L_CSHOME    equ    00000010b        ; LCD cursor position reset. 
L_DDFREQ    equ    10000000b+01h        ; LCD "Frequency" DD RAM addr. 
L_DDMODE    equ    10000000b+4Ch        ; LCD "Mode"      DD RAM addr. 
L_DDINP1    equ    10000000b+40h        ; LCD "Input"     DD RAM addr1. 
L_DDINP2    equ    10000000b+46h        ; LCD "Input"     DD RAM addr2. 
L_DDGATE    equ    10000000b+4Fh        ; LCD "Gate"      DD RAM addr. 

;------------------------------------------------------------------------- 
; Register file (= Work area) definitions. 

; Notes: Lower byte is located first on long length variables. 
;                                     $  $+1 $+2 
;        (Intel format. Ex: 186A0h -> A0  86  01) 
;------------------------------------------------------------------------- 

        org    0Ch 

; ----- General. 

I        ds    4            ; General loop counter. 
X        ds    4            ; Source       register for long word calc. 
EX        ds    4            ; Extra source register for mul/div. 
Y        ds    4            ; Destination  register for long word calc. 
EY        ds    4            ; Extra dest.  register for mul/div. 

; ----- For count procedure. 

CNTMODE        ds    1            ; Temporary input buffer. 

DSPMODE        ds    1            ; Display mode. 
EXT_PSC        ds    1            ; External prescaler mode. 
INT_PSC        ds    1            ; Internal prescaler mode. 
RESMODE        ds    1            ; Resolution mode. 

GATETIME    ds    2            ; Gate time in milliseconds. 
RTC_OLD        ds    1            ; RTCC previous value. 
RTC_NEW        ds    1            ; RTCC new value. 
CNT        ds    3            ; Count value. 

; ----- For LCD procedure. 

LCD_RSEL    ds    1            ; LCD register select. 
LCD_DATA    ds    1            ; LCD command or character data. 
LCD_STRBUF    ds    MAXDIGIT        ; LCD string buffer. 
LCD_DPOINT    ds    1            ; LCD decimal point location. 
LCD_FXMPTR    ds    1            ; LCD fixed message pointer. 

; ----- For calculation procedure. 

MDLOOPCT    ds    1            ; Loop counter for mul/div. 
CALCTMP1    ds    5            ; Temporary buffer for calculation. 
CALCTMP2    ds    5            ; Temporary buffer for calculation. 

; ----- For wait procedure. 

WAIT1        ds    1            ; For large loop. 
WAIT2        ds    1            ; For small loop. 

;------------------------------------------------------------------------- 
; Program entry. 
;------------------------------------------------------------------------- 

        org    0 
        goto    main 
        nop 
        nop 
        nop 
        goto    main 

;------------------------------------------------------------------------- 
; String tables. 
;------------------------------------------------------------------------- 

s_kHz 
        retlw    ’ ’            ; "kHz". 
        retlw    ’k’            ; 
        retlw    ’H’            ; 
        retlw    ’z’            ; 
        retlw    0            ; 

s_MHz 
        retlw    ’ ’            ; "MHz". 
        retlw    ’M’            ; 
        retlw    ’H’            ; 
        retlw    ’z’            ; 
        retlw    0            ; 

s_m 
        retlw    ’ ’            ; "m  ". 
        retlw    ’m’            ; 
        retlw    ’ ’            ; 
        retlw    ’ ’            ; 
        retlw    0            ; 

s_LFMode 
        retlw    ’L’            ; "LF". 
        retlw    ’F’            ; 
        retlw    0            ; 

s_MFmode 
        retlw    ’M’            ; "MF". 
        retlw    ’F’            ; 
        retlw    0            ; 

s_MHmode 
        retlw    ’M’            ; "MH". 
        retlw    ’H’            ; 
        retlw    0            ; 

s_HFmode 
        retlw    ’H’            ; "HF". 
        retlw    ’F’            ; 
        retlw    0            ; 

s_xpsHDR 
        retlw    ’I’            ; "INPUT". 
        retlw    ’N’            ; 
        retlw    ’P’            ; 
        retlw    ’U’            ; 
        retlw    ’T’            ; 
        retlw    ’:’            ; 
        retlw    0            ; 

s_xpsOFF 
        retlw    ’A’            ; "A". 
        retlw    0            ; (External prescaler:OFF) 

s_xpsON 
        retlw    ’B’            ; "B". 
        retlw    0            ;(External prescaler:ON) 

s_over 
        retlw    ’T’            ; "Too Long !!" 
        retlw    ’o’            ; 
        retlw    ’o’            ; 
        retlw    ’ ’            ; 
        retlw    ’L’            ; 
        retlw    ’o’            ; 
        retlw    ’n’            ; 
        retlw    ’g’            ; 
        retlw    ’ ’            ; 
        retlw    ’!’            ; 
        retlw    ’!’            ; 
        retlw    0            ; 

;------------------------------------------------------------------------- 
; Data tables. 
;------------------------------------------------------------------------- 

; ----- Get Internal prescaler rate. ------------------------------------- 

get_iprate 
        addwf    pcl, f 
        retlw    1            ; 1:1. 
        retlw    4            ; 1:4. 
        retlw    8            ; 1:8. 
        retlw    16            ; 1:16. 

; ----- Get Internal prescaler rate for TMR0. ---------------------------- 

get_iprtm0 
        addwf    pcl, f 
        retlw    TMR0_1            ; 1:1. 
        retlw    TMR0_4            ; 1:4. 
        retlw    TMR0_8            ; 1:8. 
        retlw    TMR0_16            ; 1:16. 

; ----- Get message address of internal prescaler mode. ------------------ 

get_ipmptr 
        addwf    pcl, f 
        retlw    s_LFmode        ; "LF". 
        retlw    s_MFmode        ; "MF". 
        retlw    s_MHmode        ; "MH". 
        retlw    s_HFmode        ; "HF". 

; ----- Get decimal point location. -------------------------------------- 

get_dploc 
        addwf    pcl, f 
        retlw    3            ;   X.XXX kHz. 
        retlw    5            ; X.XXXXX MHz. 
        retlw    4            ;  X.XXXX MHz. 
        retlw    3            ;   X.XXX MHz. 

;------------------------------------------------------------------------- 
; Interrupt procedure. 
;------------------------------------------------------------------------- 

;        No interrupt procedure. 

;------------------------------------------------------------------------- 
; Main procedure. 
;------------------------------------------------------------------------- 

main 

;    *** Initialize registers *** 

        clrf    pclath            ; Select program memory bank #0. 

        MOV lw    00000000b        ; Disabled all interrupt 
        MOV wf    intcon            ; sources. 

        clrf    porta            ; Initialize I/O ports. 
        clrf    portb            ; 

        bsf    status, rp0        ; Select bank 1. 

        MOV lw    00101000b        ; Pull-up PORTB, T0CS = EXT & 
        MOV wf    option            ; set TMR0 rate. (1:1) 

        MOV lw    00010000b        ; Set data directions. 
        MOV wf    trisa            ;   1: as input. 
        MOV lw    00111111b        ; 
        MOV wf    trisb            ; 

        bcf    status, rp0        ; Select bank 0. (Default) 

        MOV lw    11110000b        ; Set all output ports to ’0’. 
        andwf    porta, f        ; 
        MOV lw    00111111b        ; 
        andwf    portb, f        ; 

;    *** Initialize variable *** 

        clrf    CNT+0            ; Clear counter for 
        clrf    CNT+1            ; dummy display. 
        clrf    CNT+2            ; 

;    *** Initialize LCD *** 

        call    init_LCD        ; Contains function set & clear screen. 
        call    dsp_fixmsg        ; Display fixed message. 

;    *** Main Loop *** 

mainloop 
        call    set_cntmode        ; Set count mode. (Gate time etc.) 
        call    dsp_status        ; Display status. 

        MOV f    DSPMODE, f        ; Check display mode. 
        btfss    status, z        ; 
        goto    len_mode        ; 

        call    dsp_freq        ; Display frequency. 
        goto    cntstart 
len_mode 
        call    dsp_leng        ; Display wave length. 
cntstart 
        call    dsp_goff        ; Display "Gate OFF". 
        call    dsp_gon            ; Display "Gate ON". 
        call    count            ; Count core. 

        goto    mainloop 

;------------------------------------------------------------------------- 
; Set count mode. 
;   Input : Port B   (Data input port of count mode) 
;   Output: DSPMODE  (Display mode) 
;           EXT_PSC  (External prescaler mode) 
;           INT_PSC  (Internal prescaler mode) 
;           RESMODE  (Resolution mode) 
;           GATETIME (Gate time in milliseconds) 
;           W register & variable I will be broken. 

;   Notes: All input ports are negative logic. 
;------------------------------------------------------------------------- 

set_cntmode 

;    *** Get count mode from input port *** 

        MOV f    portb, w        ; Read input port & 
        andlw    00111111b        ; negate logic. 
        xorlw    00111111b        ; 
        MOV wf    CNTMODE            ; 

        andlw    00000011b        ; Get resolution mode. 
        MOV wf    RESMODE            ; 

        rrf    CNTMODE, f        ; Get internal prescaler mode. 
        rrf    CNTMODE, f        ; 
        MOV f    CNTMODE, w        ; 
        andlw    00000011b        ; 
        MOV wf    INT_PSC            ; 

        rrf    CNTMODE, f        ; Get external prescaler mode. 
        rrf    CNTMODE, f        ; 
        MOV f    CNTMODE, w        ; 
        andlw    00000001b        ; 
        MOV wf    EXT_PSC            ; 

        rrf    CNTMODE, f        ; Get display mode. 
        MOV f    CNTMODE, w        ; 
        andlw    00000001b        ; 
        MOV wf    DSPMODE            ; 

;    *** Set gate time *** 

        MOV lw    FRES_100        ; Set gate time soon if 
        subwf    RESMODE, w        ; resolution >= 100 Hz. 
        btfsc    status, c        ; 
        goto    set_gtime        ; 

        MOV f    EXT_PSC, f        ; Check other mode 
        btfsc    status, z        ; if external prescaler is enabled & 
        goto    set_gtime        ; internal prescaler rate <> 1:1. 
                        ; 
        MOV f    INT_PSC, f        ; 
        btfsc    status, z        ; 
        goto    set_gtime        ; 

        MOV lw    IPSC_16            ; Resolution = 100 Hz if 
        subwf    INT_PSC, w        ; internal prescaler rate = 1:16, 
        MOV lw    FRES_10            ; else resolution = 10 Hz. 
        btfsc    status, c        ; 
        MOV lw    FRES_100        ; 
                        ; 
        MOV wf    RESMODE            ; 
set_gtime 
        MOV lw    1            ; X <- external prescaler rate 
        MOV f    EXT_PSC, f        ;       * internal prescaler rate 
        btfss    status, z        ;       * 1000. 
        MOV lw    XPSC_RATE        ; 
                        ; 
        MOV wf    X+0            ; 
        clrf    X+1            ; 
        clrf    X+2            ; 
        clrf    X+3            ; 
                        ; 
        MOV f    INT_PSC, w        ; 
        call    get_iprate        ; 
        MOV wf    Y+0            ; 
        clrf    Y+1            ; 
        clrf    Y+2            ; 
        clrf    Y+3            ; 
                        ; 
        call    mul_xy            ; 
                        ; 
        MOV lw    0e8h            ; 
        MOV wf    Y+0            ; 
        MOV lw    03h            ; 
        MOV wf    Y+1            ; 
        call    mul_xy            ; 

        MOV lw    10            ; X <- X / 10 while I > 0. 
        MOV wf    Y+0            ;(Skip soon if RESMODE = FRES_1) 
        clrf    Y+1            ; 
                        ; 
        MOV f    RESMODE, w        ; 
        btfsc    status, z        ; 
        goto    end_sgt            ; 
                        ; 
        MOV wf    I            ; 
sgt_loop                    ; 
        call    div_xy            ; 
                        ; 
        decfsz    I            ; 
        goto    sgt_loop        ; 
end_sgt 
        MOV f    X+0, w            ; GATETIME <- X. 
        MOV wf    GATETIME+0        ; 
        MOV f    X+1, w            ; 
        MOV wf    GATETIME+1        ; 

;    *** Set Internal prescaler rate *** 

        MOV f    INT_PSC, w        ; Get TMR0 rate. 
        call    get_iprtm0        ; 

        bsf    status, rp0        ; Select bank 1. 
        MOV wf    option            ; set new TMR0 rate. 
        bcf    status, rp0        ; Select bank 0. (Default) 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Count procedure. 
;   Input : GATETIME (Gate time in milliseconds) 
;   Output: CNT (Value) 
;           W register & variable I, X, Y will be broken. 
;------------------------------------------------------------------------- 

count 

;    *** Prologue *** 

        MOV f    GATETIME+0, w        ; I <- GATETIME * 100. 
        MOV wf    X+0            ; (Convert milliseconds to 
        MOV f    GATETIME+1, w        ;  10 microseconds) 
        MOV wf    X+1            ; 
        clrf    X+2            ; I: Count loop counter. 
        clrf    X+3            ; (Use lower 24 bits) 
                        ; 
        MOV lw    64h            ; 
        MOV wf    Y+0            ; 
        clrf    Y+1            ; 
        clrf    Y+2            ; 
        clrf    Y+3            ; 
                        ; 
        call    mul_xy            ; 
                        ; 
        MOV f    X+0, w            ; 
        MOV wf    I+0            ; 
        MOV f    X+1, w            ; 
        MOV wf    I+1            ; 
        MOV f    X+2, w            ; 
        MOV wf    I+2            ; 

        clrf    CNT+0            ; Clear pulse counter. 
        clrf    CNT+1            ; 
        clrf    CNT+2            ; 

                        ; Clear RTCC & init OLD value of RTCC. 
        clrw                ;(But you may not clear it) 
        MOV wf    tmr0            ; RTCC is disabled to increment 
        MOV wf    RTC_OLD            ; for 2 instruction cycles after 
        nop                ; it is modified. 

        MOV lw    7            ; Wait 10 microseconds. 
        MOV wf    I+3            ; 
                        ; 
        decfsz    I+3            ; 
        goto    $-1            ; 
        nop                ; 
        nop                ; 
        nop                ; 

;    *** Pulse counter (Gate time = 10 microseconds * I) *** 

pulse_cnt 
        MOV f    tmr0, w            ; Increment pulse counter. 
        MOV wf    RTC_NEW            ; 
        MOV f    RTC_OLD, w        ; 
        subwf    RTC_NEW, w        ; 
                        ; 
        addwf    CNT+0, f        ; 
        MOV lw    1            ; 
        btfsc    status, c        ; 
        addwf    CNT+1, f        ; 
        btfsc    status, c        ; 
        addwf    CNT+2, f        ; 

        MOV f    RTC_NEW, w        ; OLD <- NEW. 
        MOV wf    RTC_OLD            ; 

        MOV lw    1            ; Decrement counter for sub loop. 
        subwf    I+0, f            ; 
        btfss    status, c        ; 
        subwf    I+1, f            ; 
        btfss    status, c        ; 
        subwf    I+2, f            ; 

        nop                ; Trim. 

        MOV f    I+0, w            ; Continue if I > 0. 
        iorwf    I+1, w            ; 
        iorwf    I+2, w            ; 
        btfss    status, z        ; 
        goto    pulse_cnt        ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Init LCD. 
;   Input : None. 
;   Output: Port A, Port B (Data output port for LCD) 
;           LCD_RSEL (LCD register select which always 0) 
;           W register & variable LCD_DATA, I will be broken. 

; Notes: Waiting time is about execution time * 2.7. 
;------------------------------------------------------------------------- 

init_LCD 

;    *** Power ON wait *** 

        MOV lw    100            ; Power ON wait for LCD. 
        call    wait_ms            ; (>= 15 milliseconds) 

;    *** Function set (Dummy #1) *** 

        clrf    LCD_RSEL        ; RS = ’0’. 
        bcf    portb, LCD_RS        ; (Default) 

        MOV lw    11110000b        ; Function set. 
        andwf    porta, f        ; (Data bus = 8 bits) 
        MOV lw    00000011b        ; 
        iorwf    porta, f        ; 

        MOV lw    3            ; Repeat 3 times. 
        MOV wf    I            ; 
Li_fsloop 
        bsf    portb, LCD_LE        ; Strobe. 
        nop                ; 
        nop                ; 
        bcf    portb, LCD_LE        ; 

        MOV lw    5            ; Wait >= 4.1 milliseconds. 
        call    wait_ms            ; 

        decfsz    I            ; Continue if I > 0. 
        goto    Li_fsloop        ; 

;    *** Function set (Dummy #2) *** 

        MOV lw    11110000b        ; Function set. 
        andwf    porta, f        ; (Data bus = 4 bits) 
        MOV lw    00000010b        ; 
        iorwf    porta, f        ; 

        bsf    portb, LCD_LE        ; Strobe. 
        nop                ; 
        nop                ; 
        bcf    portb, LCD_LE        ; 

        call    wait_100us        ; Wait >= 100 microseconds. 

;    *** Function set (Real) *** 

        MOV lw    L_FNCSET        ; Set real function. 
        call    set_LCD            ; 

;    *** Others *** 

        MOV lw    L_DSPOFF        ; Display OFF. 
        call    set_LCD            ; 

        call    cls            ; Clear display. 

        MOV lw    L_ENTSET        ; Set entry mode. 
        call    set_LCD            ; 

        MOV lw    L_DSPON            ; Display ON. 
        call    set_LCD            ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Display fixed message. 
;   Input : None. 
;   Output: None. 
;           W register, variable LCD_DATA & LCD_FXMPTR will be broken. 
;------------------------------------------------------------------------- 

dsp_fixmsg 

;    *** Display message *** 

        MOV lw    L_DDINP1        ; Set cursor to "Input". 
        call    set_LCD            ; (Header message) 

        MOV lw    s_xpshdr        ; Display header message of 
        MOV wf    LCD_FXMPTR        ; input channel. 
        call    dsp_fixstr        ; (External prescaler) 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Display status. 
;   Input : INT_PSC  (Internal prescaler mode) 
;           EXT_PSC  (External prescaler mode) 
;   Output: None. 
;           W register, variable LCD_FXMPTR will be broken. 
;------------------------------------------------------------------------- 

dsp_status 

;    *** Display internal prescaler mode *** 

        MOV lw    L_DDMODE        ; Set cursor to "Mode". 
        call    set_LCD            ; 

        MOV f    INT_PSC, w        ; Get message address. 
        call    get_ipmptr        ; 

        MOV wf    LCD_FXMPTR        ; Display internal prescaler mode. 
        call    dsp_fixstr        ; 

;    *** Display Input channel (Ext. prescaler mode) *** 

        MOV lw    L_DDINP2        ; Set cursor to "Input". 
        call    set_LCD            ; (Core) 

        MOV lw    s_xpsOFF        ; Set message address. 
        MOV f    EXT_PSC, f        ; 
        btfss    status, z        ; 
        MOV lw    s_xpsON            ; 

        MOV wf    LCD_FXMPTR        ; Display input channel. 
        call    dsp_fixstr        ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Display "Gate Open". 
;   Input : None. 
;   Output: None. 
;           W register will be broken. 
;------------------------------------------------------------------------- 

dsp_gon 

;    *** Display message *** 

        MOV lw    L_DDGATE        ; Set cursor to "Gate". 
        call    set_LCD            ; 

        bsf    LCD_RSEL, L_SELDR    ; Select data register. 

        MOV lw    ’*’            ; Set gate sign. 
        call    set_LCD            ; 

        clrf    LCD_RSEL        ; Set to default. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Display "Gate Close". 
;   Input : None. 
;   Output: None. 
;           W register & variable LCD_DATA will be broken. 
;------------------------------------------------------------------------- 

dsp_goff 

;    *** Display message *** 

        MOV lw    L_DDGATE        ; Set cursor to "Gate". 
        call    set_LCD            ; 

        bsf    LCD_RSEL, L_SELDR    ; Select data register. 

        MOV lw    ’ ’            ; Clear gate sign & 
        MOV wf    LCD_DATA        ; wait. 
        call    set_LCDcmd        ; 
        MOV lw    100            ; 
        call    wait_ms            ; 

        clrf    LCD_RSEL        ; Set to default. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Display frequency. 
;   Input : CNT     (Count value) 
;           RESMODE (Resolution mode) 
;   Output: None. 
;           W register, variable X, EX, Y, EY, LCD_DPOINT & LCD_FXMPTR 
;           will be broken. 
;------------------------------------------------------------------------- 

dsp_freq 

;    *** Set cursor location of LCD & convert count data to string *** 

        MOV lw    L_DDFREQ        ; Set cursor to "frequency". 
        call    set_LCD            ; 

        MOV f    CNT+0, w        ; Change count data to 
        MOV wf    X+0            ; string. 
        MOV f    CNT+1, w        ; 
        MOV wf    X+1            ; 
        MOV f    CNT+2, w        ; 
        MOV wf    X+2            ; 
        clrf    X+3            ; 
        clrf    EX+0            ; 
        clrf    EX+1            ; 
        clrf    EX+2            ; 
        clrf    EX+3            ; 
        call    x_to_str        ; 

;    *** Display frequency *** 

        MOV f    RESMODE, w        ; Set decimal point location. 
        call    get_dploc        ; 
        MOV wf    LCD_DPOINT        ; 

        call    dsp_value        ; Display value. 

        MOV lw    s_kHz            ; Add unit. (kHz or MHz) 
        MOV f    RESMODE, f        ; 
        btfss    status, z        ; 
        MOV lw    s_MHz            ; 
                        ; 
        MOV wf    LCD_FXMPTR        ; 
        call    dsp_fixstr        ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Display wave length. 
;   Input : CNT     (Count value) 
;           RESMODE (Resolution mode) 
;   Output: None. 
;           W register, variable I, X, EX, Y, EY, LCD_DPOINT & LCD_FXMPTR 
;           will be broken. 
;------------------------------------------------------------------------- 

dsp_leng 

;    *** Set cursor location of LCD *** 

        MOV lw    L_DDFREQ        ; Set cursor to "frequency". 
        call    set_LCD            ; 

;    *** Trim count data *** 

        MOV f    CNT+0, w        ; X <- Count value. 
        MOV wf    X+0            ; Y <- 1000 / Resolution. 
        MOV f    CNT+1, w        ; X <- X / Y. 
        MOV wf    X+1            ; 
        MOV f    CNT+2, w        ; 
        MOV wf    X+2            ; 
        clrf    X+3            ; 
        clrf    EX+0            ; 
        clrf    EX+1            ; 
        clrf    EX+2            ; 
        clrf    EX+3            ; 
                        ; 
        MOV lw    10            ; 
        MOV wf    Y+0            ; 
        clrf    Y+1            ; 
        clrf    Y+2            ; 
        clrf    Y+3            ; 
                        ; 
        MOV f    RESMODE, w        ; 
        sublw    FRES_1000        ; 
        btfsc    status, z        ; 
        goto    dpln_cv0        ; 
                        ; 
        MOV wf    I            ; 
dpln_trim                    ; 
        call    div_xy            ; 
                        ; 
        decfsz    I            ; 
        goto    dpln_trim        ; 

;    *** Convert data to string *** 

dpln_cv0 
        MOV f    X+0, w            ; Y <- X. 
        MOV wf    Y+0            ; (Y: frequency in kHz) 
        MOV f    X+1, w            ; 
        MOV wf    Y+1            ; 
        MOV f    X+2, w            ; 
        MOV wf    Y+2            ; 
        MOV f    X+3, w            ; 
        MOV wf    Y+3            ; 

        iorwf    Y+2, w            ; Display "Too Long !!" 
        iorwf    Y+1, w            ; if value = 0. 
        iorwf    Y+0, w            ; (Less than 1 kHz) 
        btfss    status, z        ; 
        goto    dpln_cv1        ; 
                        ; 
        MOV lw    s_over            ; 
        MOV wf    LCD_FXMPTR        ; 
        call    dsp_fixstr        ; 
        goto    end_dpln        ; 
dpln_cv1 
        MOV lw    00h            ; X <- 300000000 / Y 
        MOV wf    X+0            ; (X: wave length in mm) 
        MOV lw    0A3h            ; & convert to string. 
        MOV wf    X+1            ; 
        MOV lw    0E1h            ; 
        MOV wf    X+2            ; 
        MOV lw    11h            ; 
        MOV wf    X+3            ; 
        call    div_xy            ; 
        call    x_to_str        ; 

;    *** Display wave length *** 

        MOV lw    3            ; Set decimal point location. 
        MOV wf    LCD_DPOINT        ; (X.XXX m) 

        call    dsp_value        ; Display value. 
end_dpln 
        MOV lw    s_m            ; Add unit. (m) 
        MOV wf    LCD_FXMPTR        ; 
        call    dsp_fixstr        ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Display value. (With 0 suppless & decimal point) 
;   Input : LCD_STRBUF (String buffer) 
;           LCD_DPOINT (Decimal point from right side) 
;   Output: None. 
;           W, Index register & variable I will be broken. 
;------------------------------------------------------------------------- 

dsp_value 

;    *** Initialize *** 

        bsf    LCD_RSEL, L_SELDR    ; Select data register. 

        MOV lw    LCD_STRBUF        ; Set pointer of string. 
        MOV wf    fsr            ; 

;    *** Display sPACe (Zero suppless) *** 

        MOV lw    MAXDIGIT-1        ; Set max space count. 
        MOV wf    I            ; (MAXDIGIT - 1) 
dspvl_l1 
        MOV f    I, w            ; Exit this loop if 
        subwf    LCD_DPOINT, w        ; this loc. = decimal point or 
        btfsc    status, z        ; not zero. 
        goto    dspvl_2s        ; 
                        ; 
        MOV f    indf, w            ; 
        sublw    ’0’            ; 
        btfss    status, z        ; 
        goto    dspvl_2s        ; 

        MOV lw    ’ ’            ; Put ’ ’. 
        call    set_LCD            ; 

        incf    fsr            ; Set location to next. 
        decfsz    I            ; 
        goto    dspvl_l1        ; 

;    *** Display number & decimal point *** 

dspvl_2s 
        incf    I            ; Increment counter. 
dspvl_l2 
        MOV f    indf, w            ; Display number. 
        call    set_LCD            ; 

        incf    fsr            ; Decrement counter & 
        decf    I            ; skip below if this loc 
        MOV f    I, w            ; is not decimal point loc. 
        subwf    LCD_DPOINT, w        ; 
        btfss    status, z        ; 
        goto    dspvl_2e        ; 

        MOV lw    ’.’            ; Display decimal point. 
        call    set_LCD            ; 
dspvl_2e 
        MOV f    I, f            ; Continue if I > 0. 
        btfss    status, z        ; 
        goto    dspvl_l2        ; 

;    *** Return from subroutine *** 

        clrf    LCD_RSEL        ; Set to default. 
        return 

;------------------------------------------------------------------------- 
; Convert value of X to string. (Fixed 10 digits) 
;   Input :  X[0]- X[3] (Value) 
;           EX[0]-EX[3] 
;   Output: LCD_STRBUF  (Buffer of string for LCD) 
;           W, Index register & variable I, Y, EY will be broken. 
;------------------------------------------------------------------------- 

x_to_str 

;    *** Initialize *** 

        MOV lw    LCD_STRBUF        ; Set pointer of string. 
        addlw    9            ; (To bottom) 
        MOV wf    fsr 

        MOV lw    10            ; Set loop counter & 
        MOV wf    I            ; Y. 
        MOV wf    Y+0            ; 
        clrf    Y+1            ; 
        clrf    Y+2            ; 
        clrf    Y+3            ; 

;    *** Conversion loop (32 bits = 10 digits max) *** 

xts_loop 
        call    div_xy            ; X <- X / 10. 
        MOV f    EY+0, w            ; EY(Lowest digit) <- X mod 10. 

        addlw    ’0’            ; Change to ASCII & 
        MOV wf    indf            ; store. 

        decf    fsr            ; Set location to next. 
        decfsz    I            ; 
        goto    xts_loop        ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Clear screen. (display) 
;   Input : None. 
;   Output: None. 
;           W register & variable LCD_DATA will be broken. 
;------------------------------------------------------------------------- 

cls 

;    *** Clear display *** 

        MOV lw    L_DSPCLR        ; Clear display. 
        MOV wf    LCD_DATA        ; 
        call    set_LCDcmd        ; 

        MOV lw    5            ; Wait. 
        call    wait_ms            ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Display fixed string. (ASCIZ string on ROM) 
;   Input : LCD_FXMPTR (Pointer of fixed ASCIZ string table) 
;   Output: None. 
;           W, Index register, variable & LCD_FXMPTR will be broken. 
;------------------------------------------------------------------------- 

dsp_fixstr 

;    *** Initialize *** 

        bsf    LCD_RSEL, L_SELDR    ; Select data register. 

;    *** Display loop *** 

dfs_loop 
        call    get_fixchr        ; Exit if character = NULL. 
        addlw    0            ; 
        btfsc    status, z        ; 
        goto    end_dfs            ; 

        call    set_LCD            ; Display character. 

        incf    LCD_FXMPTR        ; Continue. 
        goto    dfs_loop        ; 

;    *** Return from subroutine *** 

end_dfs 
        clrf    LCD_RSEL        ; Set to default. 
        return 

;------------------------------------------------------------------------- 
; Get character from fixed message table. 
;   Input : LCD_FXMPTR (Pointer of fixed ASCIZ string table) 
;   Output: None. 
;           W register will be broken. 
;------------------------------------------------------------------------- 

get_fixchr 
        MOV f    LCD_FXMPTR, w        ; Caution: Upper byte of PCL 
        MOV wf    pcl            ; is always 0. 

;------------------------------------------------------------------------- 
; Set LCD command for standard operation. 
;   Input : W register (Command) 
;   Output: None. 
;           W register & variable LCD_DATA will be broken. 
;------------------------------------------------------------------------- 

set_LCD 

;    *** Set command *** 

        MOV wf    LCD_DATA 
        call    set_LCDcmd 
        call    wait_100us 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; Set LCD command (Instruction). 
;   Input : LCD_RSEL (LCD register select) 
;           LCD_DATA (LCD data) 
;   Output: Port A, Port B (Data output port for LCD) 
;           W register will be broken. 
;------------------------------------------------------------------------- 

set_LCDcmd 

;    *** Select register *** 

        bcf    portb, LCD_RS        ; Select register. 
        btfsc    LCD_RSEL, L_SELDR    ; 
        bsf    portb, LCD_RS        ; 

;    *** Send upper nibbles *** 

        MOV lw    11110000b        ; Set upper nibbles. 
        andwf    porta, f        ; 
        swapf    LCD_DATA, w        ; 
        andlw    00001111b        ; 
        iorwf    porta, f        ; 

        bsf    portb, LCD_LE        ; Strobe. 
        nop                ; 
        nop                ; 
        bcf    portb, LCD_LE        ; 
        nop                ; 
        nop                ; 

;    *** Send lower nibbles *** 

        MOV lw    11110000b        ; Set lower nibbles. 
        andwf    porta, f        ; 
        MOV f    LCD_DATA, w        ; 
        andlw    00001111b        ; 
        iorwf    porta, f        ; 

        bsf    portb, LCD_LE        ; Strobe. 
        nop                ; 
        nop                ; 
        bcf    portb, LCD_LE        ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Add. (32 bits source + 32 bits destination) 
;   Input : X[0]-X[3] (Source     : 32 bits) 
;           Y[0]-Y[3] (Destination: 32 bits) 
;   Output: X[0]-X[3] (Answer     : 32 bits) 
;           W register will be broken. 

; Allocations (MSB <-> LSB): 
;     X[3] X[2] X[1] X[0] 
;     Y[3] Y[2] Y[1] Y[0] 
;------------------------------------------------------------------------- 

add_xy 

;    *** Add Y to X *** 

        MOV f    Y+0, w            ; Lower. 
        addwf    X+0, f            ; 
        MOV lw    1            ; 
        btfsc    status, c        ; 
        addwf    X+1, f            ; 
        btfsc    status, c        ; 
        addwf    X+2, f            ; 
        btfsc    status, c        ; 
        addwf    X+3, f            ; 

        MOV f    Y+1, w            ; Middle lower. 
        addwf    X+1, f            ; 
        MOV lw    1            ; 
        btfsc    status, c        ; 
        addwf    X+2, f            ; 
        btfsc    status, c        ; 
        addwf    X+3, f            ; 

        MOV f    Y+2, w            ; Middle upper. 
        addwf    X+2, f            ; 
        MOV lw    1            ; 
        btfsc    status, c        ; 
        addwf    X+3, f            ; 

        MOV f    Y+3, w            ; Upper. 
        addwf    X+3, f            ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Subtract. (32 bits source - 32 bits destination) 
;   Input : X[0]-X[3] (Source     : 32 bits) 
;           Y[0]-Y[3] (Destination: 32 bits) 
;   Output: X[0]-X[3] (Answer     : 32 bits) 
;           W register will be broken. 

; Allocations (MSB <-> LSB): 
;     X[3] X[2] X[1] X[0] 
;     Y[3] Y[2] Y[1] Y[0] 
;------------------------------------------------------------------------- 

sub_xy 

;    *** Subtract Y from X *** 

        MOV f    Y+0, w            ; Lower. 
        subwf    X+0, f            ; 
        MOV lw    1            ; 
        btfss    status, c        ; <- Positive if CF = 1. 
        subwf    X+1, f            ; 
        btfss    status, c        ; 
        subwf    X+2, f            ; 
        btfss    status, c        ; 
        subwf    X+3, f            ; 

        MOV f    Y+1, w            ; Middle lower. 
        subwf    X+1, f            ; 
        MOV lw    1            ; 
        btfss    status, c        ; 
        subwf    X+2, f            ; 
        btfss    status, c        ; 
        subwf    X+3, f            ; 

        MOV f    Y+2, w            ; Middle upper. 
        subwf    X+2, f            ; 
        MOV lw    1            ; 
        btfss    status, c        ; 
        subwf    X+3, f            ; 

        MOV f    Y+3, w            ; Upper. 
        subwf    X+3, f            ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Multiply. (32 by 32 bits) 
;   Input :  X[0]- X[3] (Source     : 32 bits) 
;            Y[0]- Y[3] (Destination: 32 bits) 
;   Output: EX[0]-EX[3] (Answer     : 64 bits) 
;            X[0]- X[3] 
;           EY[0]-EY[3] (As same as X[0]-X[3]) 

;           W register will be broken. 

; Notes: Referred to AKIZUKI’s PIC sample software. 
;        This routine uses the same technic of manual-calculation. 

; Example:     00010010 (12h) 
;        x00110100 (34h) 
;        ---------- 
;         00000000 
;        00000000 
;           00010010 
;          00000000 
;         00010010 
;        00010010 
;       00000000 
;      00000000 
;    ------------------ 
;     0000001110101000 (03A8h) 

; Allocations (MSB <-> LSB): 
;    EX[3] EX[2] EX[1] EX[0] X[3] X[2] X[1] X[0] 
;    EY[3] EY[2] EY[1] EY[0] Y[3] Y[2] Y[1] Y[0] 
;------------------------------------------------------------------------- 

mul_xy 

;    *** Initialize *** 

        MOV f    X+0, w            ; EY <- X. 
        MOV wf    EY+0            ; 
        MOV f    X+1, w            ; 
        MOV wf    EY+1            ; 
        MOV f    X+2, w            ; 
        MOV wf    EY+2            ; 
        MOV f    X+3, w            ; 
        MOV wf    EY+3            ; 

        MOV f    Y+0, w            ; X <- Y. 
        MOV wf    X+0            ; 
        MOV f    Y+1, w            ; 
        MOV wf    X+1            ; 
        MOV f    Y+2, w            ; 
        MOV wf    X+2            ; 
        MOV f    Y+3, w            ; 
        MOV wf    X+3            ; 

        clrf    EX+0            ; Clear EX. 
        clrf    EX+1            ; 
        clrf    EX+2            ; 
        clrf    EX+3            ; 

        MOV lw    32            ; Set data length. 
        MOV wf    MDLOOPCT        ; 

;    *** Multiply loop (32 times) *** 

mul_loop 
        btfss    X+0, 0            ; Skip below if LSB of XL = ’0’. 
        goto    mul_next        ; (EY * ’0’ = 0) 

        bcf    X+0, 0            ; Clear always LSB of X. 

        MOV f    EY+0, w            ; EX <- EX + EY. 
        addwf    EX+0, f            ; 
        MOV lw    1            ; Set LSB of X to ’1’ 
        btfsc    status, c        ; if overflow. (Set carry) 
        addwf    EX+1, f            ; 
        btfsc    status, c        ; 
        addwf    EX+2, f            ; 
        btfsc    status, c        ; 
        addwf    EX+3, f            ; 
        btfsc    status, c        ; 
        bsf    X+0, 0            ; 
                        ; 
        MOV f    EY+1, w            ; 
        addwf    EX+1, f            ; 
        MOV lw    1            ; 
        btfsc    status, c        ; 
        addwf    EX+2, f            ; 
        btfsc    status, c        ; 
        addwf    EX+3, f            ; 
        btfsc    status, c        ; 
        bsf    X+0, 0            ; 
                        ; 
        MOV f    EY+2, w            ; 
        addwf    EX+2, f            ; 
        MOV lw    1            ; 
        btfsc    status, c        ; 
        addwf    EX+3, f            ; 
        btfsc    status, c        ; 
        bsf    X+0, 0            ; 
                        ; 
        MOV f    EY+3, w            ; 
        addwf    EX+3, f            ; 
        btfsc    status, c        ; 
        bsf    X+0, 0            ; 
mul_next 
        bcf    status, c        ; Rotate EX + X to right. 
        rrf    EX+3            ; (LSB of X -> MSB of EX) 
        rrf    EX+2            ; 
        rrf    EX+1            ; 
        rrf    EX+0            ; 
        rrf    X+3            ; 
        rrf    X+2            ; 
        rrf    X+1            ; 
        rrf    X+0            ; 
        btfsc    status, c        ; 
        bsf    EX+3, 7            ; 

        decfsz    MDLOOPCT, f        ; Continue if loop > 0. 
        goto    mul_loop        ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Divide. (64 bits source by 32 bits destination) 
;   Input : EX[0]-EX[3] (Source     : 64 bits) 
;            X[0]- X[3] 
;            Y[0]- Y[3] (Destination: 32 bits) 
;   Output: EX[0]-EX[3] (Answer     : 64 bits) 
;            X[0]- X[3] 
;            Y[0]- Y[3] (Mod        : 32 bits) 

;           W register will be broken. 

; Notes: Referred to AKIZUKI’s PIC sample software. 
;        This routine uses the same technic of manual-calculation. 

; Example:      0000000001100100 (64h) 
;           +------------------ 
;    (10h) 1010| 0000001111101000 (03E8h) 
;               1010 
;           ------------------- 
;            1011 
;            1010 
;           ------------------- 
;               1010 
;               1010 
;           ------------------- 
;                  0 

; Allocations (MSB <-> LSB): 
;    EX[3] EX[2] EX[1] EX[0] X[3] X[2] X[1] X[0] 
;    EY[3] EY[2] EY[1] EY[0] Y[3] Y[2] Y[1] Y[0] 
;------------------------------------------------------------------------- 

div_xy 

;    *** Initialize *** 

        clrf    CALCTMP1+0        ; Clear temporary buffer. 
        clrf    CALCTMP1+1        ; 
        clrf    CALCTMP1+2        ; 
        clrf    CALCTMP1+3        ; 
        clrf    CALCTMP1+4        ; 

        MOV lw    64            ; Set data length. 
        MOV wf    MDLOOPCT        ; 

;    *** Divide loop (64 times) *** 

div_loop 
        bcf    status, c        ; Shift CALCTMP1(Mod) + EX + X 
        rlf    X+0            ; to left. 
        rlf    X+1            ; 
        rlf    X+2            ; 
        rlf    X+3            ; 
        rlf    EX+0            ; 
        rlf    EX+1            ; 
        rlf    EX+2            ; 
        rlf    EX+3            ; 
        rlf    CALCTMP1+0        ; 
        rlf    CALCTMP1+1        ; 
        rlf    CALCTMP1+2        ; 
        rlf    CALCTMP1+3        ; 
        rlf    CALCTMP1+4        ; 

        MOV f    CALCTMP1+0, w        ; CALCTMP2(Work) <- CALCTMP1. 
        MOV wf    CALCTMP2+0        ; 
        MOV f    CALCTMP1+1, w        ; 
        MOV wf    CALCTMP2+1        ; 
        MOV f    CALCTMP1+2, w        ; 
        MOV wf    CALCTMP2+2        ; 
        MOV f    CALCTMP1+3, w        ; 
        MOV wf    CALCTMP2+3        ; 
        MOV f    CALCTMP1+4, w        ; 
        MOV wf    CALCTMP2+4        ; 

        MOV f    Y+0, w            ; CALCTMP2 <- CALCTMP2 - Y. 
        subwf    CALCTMP2+0, f        ; (Signed operation) 
        MOV lw    1            ; 
        btfss    status, c        ; <- Positive if CF=1. 
        subwf    CALCTMP2+1, f        ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+2, f        ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+3, f        ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+4, f        ; 
                        ; 
        MOV f    Y+1, w            ; 
        subwf    CALCTMP2+1, f        ; 
        MOV lw    1            ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+2, f        ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+3, f        ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+4, f        ; 
                        ; 
        MOV f    Y+2, w            ; 
        subwf    CALCTMP2+2, f        ; 
        MOV lw    1            ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+3, f        ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+4, f        ; 
                        ; 
        MOV f    Y+3, w            ; 
        subwf    CALCTMP2+3, f        ; 
        MOV lw    1            ; 
        btfss    status, c        ; 
        subwf    CALCTMP2+4, f        ; 

        btfsc    CALCTMP2+4, 7        ; Skip below if CALCTMP2 < 0. 
        goto    div_next        ; (MSB of CALCTMP2 is ’1’) 

        MOV f    CALCTMP2+0, w        ; CALCTMP1(Mod) <- CALCTMP2 & 
        MOV wf    CALCTMP1+0        ; LSB of X <- ’1’. 
        MOV f    CALCTMP2+1, w        ; 
        MOV wf    CALCTMP1+1        ; 
        MOV f    CALCTMP2+2, w        ; 
        MOV wf    CALCTMP1+2        ; 
        MOV f    CALCTMP2+3, w        ; 
        MOV wf    CALCTMP1+3        ; 
        MOV f    CALCTMP2+4, w        ; 
        MOV wf    CALCTMP1+4        ; 
                        ; 
        bsf    X+0, 0            ; 
div_next 
        decfsz    MDLOOPCT, f        ; Continue if loop > 0. 
        goto    div_loop        ; 

;    *** Return from subroutine *** 

        MOV f    CALCTMP1+0, w        ; EY(Mod) <- CALCTMP1. 
        MOV wf    EY+0            ; 
        MOV f    CALCTMP1+1, w        ; 
        MOV wf    EY+1            ; 
        MOV f    CALCTMP1+2, w        ; 
        MOV wf    EY+2            ; 
        MOV f    CALCTMP1+3, w        ; 
        MOV wf    EY+3            ; 

        return 

;------------------------------------------------------------------------- 
; General: Rotate left. (16 bits length) 
;   Input : W (Pointer of entry) 
;------------------------------------------------------------------------- 

rl16 

;    *** Rotate left *** 

        MOV wf    fsr 

        bcf    status, c        ; Set ’0’ on LSB. 
        rlf    indf, f            ; Lower. 
        incf    fsr, f 
        rlf    indf, f            ; Upper. 

        decf    fsr, f 
        btfsc    status, c 
        bsf    indf, 0            ; Set ’1’ on LSB if CF = ’1’. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Rotate right. (16 bits length) 
;   Input : W (Pointer of entry) 
;------------------------------------------------------------------------- 

rr16 

;    *** Rotate right *** 

        MOV wf    fsr 

        incf    fsr, f 

        bcf    status, c        ; Set ’0’ on MSB. 
        rrf    indf, f            ; Upper. 
        decf    fsr, f 
        rrf    indf, f            ; Lower. 

        incf    fsr, f 
        btfsc    status, c 
        bsf    indf, 7            ; Set ’1’ on MSB if CF = ’1’. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Rotate left. (32 bits length) 
;   Input : W (Pointer of entry) 
;------------------------------------------------------------------------- 

rl32 

;    *** Rotate left *** 

        MOV wf    fsr 

        bcf    status, c        ; Set ’0’ on LSB. 
        rlf    indf, f            ; Lower. 
        incf    fsr, f 
        rlf    indf, f            ; Middle lower. 
        incf    fsr, f 
        rlf    indf, f            ; Middle upper. 
        incf    fsr, f 
        rlf    indf, f            ; Upper. 

        decf    fsr, f 
        decf    fsr, f 
        decf    fsr, f 
        btfsc    status, c 
        bsf    indf, 0            ; Set ’1’ on LSB if CF = ’1’. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Rotate right. (32 bits length) 
;   Input : W (Pointer of entry) 
;------------------------------------------------------------------------- 

rr32 

;    *** Rotate right *** 

        MOV wf    fsr 

        incf    fsr, f 
        incf    fsr, f 
        incf    fsr, f 

        bcf    status, c        ; Set ’0’ on MSB. 
        rrf    indf, f            ; Upper. 
        decf    fsr, f 
        rrf    indf, f            ; Middle upper. 
        decf    fsr, f 
        rrf    indf, f            ; Middle lower. 
        decf    fsr, f 
        rrf    indf, f            ; Lower. 

        incf    fsr, f 
        incf    fsr, f 
        incf    fsr, f 
        btfsc    status, c 
        bsf    indf, 7            ; Set ’1’ on MSB if CF = ’1’. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: shift left. (16 bits length) 
;   Input : W (Pointer of entry) 
;------------------------------------------------------------------------- 

sl16 

;    *** Shift left *** 

        MOV wf    fsr 

        bcf    status, c        ; Set ’0’ on LSB. 
        rlf    indf, f            ; Lower. 
        incf    fsr, f 
        rlf    indf, f            ; Upper. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Shift right. (16 bits length) 
;   Input : W (Pointer of entry) 
;------------------------------------------------------------------------- 

sr16 

;    *** Shift right *** 

        MOV wf    fsr 

        incf    fsr, f 

        bcf    status, c        ; Set ’0’ on MSB. 
        rrf    indf, f            ; Upper. 
        decf    fsr, f 
        rrf    indf, f            ; Lower. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Shift left. (32 bits length) 
;   Input : W (Pointer of entry) 
;------------------------------------------------------------------------- 

sl32 

;    *** Shift left *** 

        MOV wf    fsr 

        bcf    status, c        ; Set ’0’ on LSB. 
        rlf    indf, f            ; Lower. 
        incf    fsr, f 
        rlf    indf, f            ; Middle lower. 
        incf    fsr, f 
        rlf    indf, f            ; Middle upper. 
        incf    fsr, f 
        rlf    indf, f            ; Upper. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Shift right. (32 bits length) 
;   Input : W (Pointer of entry) 
;------------------------------------------------------------------------- 

sr32 

;    *** Shift right *** 

        MOV wf    fsr 

        incf    fsr, f 
        incf    fsr, f 
        incf    fsr, f 

        bcf    status, c        ; Set ’0’ on MSB. 
        rrf    indf, f            ; Upper. 
        decf    fsr, f 
        rrf    indf, f            ; Middle upper. 
        decf    fsr, f 
        rrf    indf, f            ; Middle lower. 
        decf    fsr, f 
        rrf    indf, f            ; Lower. 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Wait procedure. 
;   Input : W (Time in milliseconds) 
;   Output: None. 
;           W register & variable WAIT1, WAIT2 will be broken. 
;------------------------------------------------------------------------- 

wait_ms 

;    *** Wait loop *** 

        MOV wf    WAIT1            ; Set milliseconds loop counter. 
wm_loop1 
        MOV lw    249            ; Set microseconds loop counter. 
        MOV wf    WAIT2            ; (996 microseconds / 4) 
wm_loop2 
        nop 
        nop 
        nop 
        nop 
        nop 
        nop 
        nop 
        decfsz    WAIT2            ; Continue if loop2 > 0. 
        goto    wm_loop2        ; 

        nop 
        nop 
        nop 
        nop 
        nop 
        nop 
        decfsz    WAIT1            ; Continue if loop1 > 0. 
        goto    wm_loop1        ; 

;    *** Return from subroutine *** 

        return 

;------------------------------------------------------------------------- 
; General: Wait procedure. (Fixed 100 microseconds) 
;   Input : None. 
;   Output: None. 
;           W register & variable WAIT1 will be broken. 
;------------------------------------------------------------------------- 

wait_100us 

;    *** Wait loop *** 

        MOV lw    48            ; Set 100 microseconds loop counter. 
        MOV wf    WAIT1            ; (96 microseconds) 
wu_loop 
        nop 
        nop 
        decfsz    WAIT1            ; Continue if loop > 0. 
        goto    wu_loop            ; 

;    *** Return from subroutine *** 

        nop 
        nop 
        nop 
        nop 
        nop 
        return 

; End of COUNTER.ASM 


 

16f84_32.H


关键字:PIC16F84  单片机  频率计 引用地址:PIC16F84单片机做的频率计

上一篇:485通讯PIC源程序
下一篇:p18f458单片机通讯程序

推荐阅读最新更新时间:2024-03-16 15:48

ARM7单片机(学习ing)—(一)、输入/输出端口GPIO编程—01
一、输入/输出端口GPIO编程 一—(01)、一位数码管静态显示(通过74HC595实现) 1、管脚连接模块 首先介绍一下LPC2106的相关的管脚~~ 特性:可以实现独立的管脚配置 应用:管脚连接模块的用途是将管脚配置为需要的功能(这一章节主要就是介绍GPIO功能~~别的会在接下来的章节中分别予以介绍~~) 描述:管脚连接模块可以使所选管脚具有一个以上的功能。配置寄存器控制多路开关来连接管脚与片内外设。外设在激活和任何相关只读使能之前必须连接到适当的管脚。任何使能的外设功能如果没有映射到相应的管脚,则被认为是无效的。 寄存器的描述: 管脚连接模块包括两个寄存器: 管脚功能寄存器0:(PINSEL0) PINSEL0寄存器按
[单片机]
ARM7<font color='red'>单片机</font>(学习ing)—(一)、输入/输出端口GPIO编程—01
Precision32芯片方案介绍 延续8位MCU优势
ARM Cortex内核改变了MCU产品的传统形态,毕竟通用的标准有助于减少整体系统成本、降低设计复杂度并缩短开发时间。开发人员在为特定设计选择MCU时需考虑诸多因素,如存储大小、输入输出引脚数量、通信接口等。然而,在多种基于ARM标准内核的MCU产品都满足基本需求的情况下,SILICon Labs认为开发人员可从下列因素中进一步缩小选择范围,例如:混合信号集成度、可配置性、功耗和开发难度等。Silicon Labs期望通过Precision32系列产品,重塑32位MCU产品领域的多功能、一体化、高能效和易用特性。 集成多种外设降低系统成本 Precision32结合了Cortex-M3 CPU和多种模拟组件,主要包括:两个12位
[单片机]
Precision32芯片方案介绍 延续8位<font color='red'>MCU</font>优势
ST推出STM32无线微控制器模块,提升物联网产品开发效率
半导体供应商意法半导体推出一个新的加快物联网产品上市的解决方案,该方案可利用现成的微型STM32无线微控制器(MCU)模块加快基于Bluetooth® LE和802.15.4新物联网设备的开发周期。 这个7mm x 11.3mm的 STM32WB5MMG模块让缺少无线设计能力的产品研发团队也能开发物联网产品。为开发层数最少的低成本PCB电路板而设计,新模块集成了直到天线的整个射频子系统。用户还可以免费使用意法半导体的STM32Cube MCU开发生态系统工具、设计向导、射频协议栈和完整软件库,快速高效地完成开发项目。 意法半导体部门副总裁兼微控制器产品总经理Ricardo de Sa Earp表示:“我们的首个基于S
[单片机]
ST推出STM32无线<font color='red'>微控制器</font>模块,提升物联网产品开发效率
8051单片机教程第二课:单片机的内部、外部结构(一)
一、单片机的外部结构 拿到一块芯片,想要使用它,首先必须要知道怎样连线,我们用的一块称之为89C51的芯片,下面我们就看一下如何给它连线。1、电源:这当然是必不可少的了。单片机使用的是5V电源,其中正极接40引脚,负极(地)接20引脚。2、振蒎电路:单片机是一种时序电路,必须提供脉冲信号才能正常工作,在单片机内部已集成了振荡器,使用晶体振荡器,接18、19脚。只要买来晶振,电容,连上就可以了,按图1接上即可。3、复位引脚:按图1中画法连好,至于复位是何含义及为何需要复要复位,在单片机功能中介绍。4、EA引脚:EA引脚接到正电源端。至此,一个单片机就接好,通上电,单片机就开始工作了。 我们的第一个任务是要用单片机点亮一只发光二极
[单片机]
8051<font color='red'>单片机</font>教程第二课:<font color='red'>单片机</font>的内部、外部结构(一)
单片机常用数字滤波函数
/////////////////////////////////限副滤波/////////////////// #define A 10 //A值可根据实际情况调整 char value; //value为有效值 char filter() { char new_value; //new value为当前采样值 new value= get _ad(); if ((new_value-value A)‖(value-new_value A) return value; return new_value; } /////////////////////////中位值滤波//////////////////
[单片机]
单片机C语言的知识汇总
一、概述 1、结合8051介绍单片机C语言的优越性: ·无须懂得 单片机 的具体硬件,也能够编出符合硬件实际的专业水平的程序;    ·不懂得单片机的指令集,也能够编写完美的单片机程序;    ·不同函数的数据实行覆盖,有效利用片上有限的RAM空间;    ·提供auto、 static 、const等存储类型和专门针对8051单片机的data、idata、pdata、xdata、code等存储类型,自动为变量合理地分配地址;    ·C语言提供复杂的数据类型( 数组 、结构、联合、枚举、指针等),极大地增强了程序处理能力和灵活性;    ·提供small、compact、large等编译模式,以适应片上存储器的大小;
[单片机]
51单片机片内数据存储器分为哪几个性质和用途不同的区域?
8051内部128B的数据RAM区,包括有工作寄存器组区、可直接位寻址区和数据缓冲区。各区域的特性如下: (1)00H~1FH为工作寄存器组区,共分4组,每组占用8个RAM字节单元,每个单元作为一个工作寄存器,每组的8个单元分别定义为8个工作寄存器R0~R7。当前工作寄存器组的选择是由程序状态字PSW的RS1、RS0两位来确定。如果实际应用中并不需要使用工作寄存器或不需要使用4组工作寄存器,不使用的工作寄存器组的区域仍然可作为一般数据缓冲区使用,用直接寻址或用Ri的寄存器间接寻址来访问。 (2)20H~2FH为可位寻址区域,这16个字节的每一位都有一个地址,编址为00H~7FH。 当然,位寻址区也可以用作字节寻址的一般
[单片机]
基于单片机的温湿度监控系统设计
0 引言 在日常生活中温湿度监控系统应用很广泛,例如:粮库、机房、档案馆、特殊材料加工工场等场所,都必须严格控制环境的温度及相对湿度,使其保持在一定的范围内。硝基软片生产线对于温湿度有着特殊的要求,需要装有温湿度在线监控系统,由用户根据环境要求设定系统的温湿度阈值;系统实时地测量显示环境的温湿度值,实现温湿度自动控制,使其在较宽的温度范围内具有较高的测试精度,同时还可以根据用户设定报警阈值报警,一旦发现环境温湿度超限,立即报警。为此,我们设计了一款测量精度高、结构简单使用、工作稳定可靠的基于单片机的温湿度监控与自动控制升降系统,并受到了硝基软片生产客户的好评。 1 设计方案 温湿度监控系统满足以下要求: 1)按照国家
[单片机]
基于<font color='red'>单片机</font>的温湿度监控系统设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved