⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 counter.asm

📁 PIC16F628A芯片制作的频率计
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;--------------------------------------------------------------------------

neg32  macro op                      ; op1 := 0 - op2
       local neg_done
           comf  op,   f             ; invert all 8 bits in high byte  
           comf  op+1, f             ; invert all 8 bits in middle high byte  
           comf  op+2, f             ; invert all 8 bits in middle low byte  
           comf  op+3, f             ; invert all 8 bits in low byte  
           ; Note at this point 0x000000 would have turned into 0xFFFFFFF .
           ; Must add ONE to complete the TWO's COMPLIMENT calculation ( -0  = 0 ).
           ; Note that "incf" affects only the Z flag but not the C flag .
           incfsz op+3, f            ; increment low byte        (bits 7...0)
           goto   neg_done           ; if incremented result NOT zero, we're through !
           incfsz op+2, f            ; increment middle low byte (bits 15...8)
           goto   neg_done           ; if incremented result NOT zero, ...
           incfsz op+1, f            ; increment middle high byte (bits 23...16)
           goto   neg_done           ; if ...
           incfsz op+0, f            ; increment high byte       (bits 31...24)
           goto   neg_done           ;
neg_done
       endm




;**********************************************************************
  ORG     0x000             ; processor reset vector
       goto MainInit        ; go to beginning of program
; (begin of ROM is too precious to waste for ordinary code, see below...)



;**************************************************************************
;                                                                         *
; Lookup tables                                                           *
;    Must be at the start of the code memory to avoid crossing pages !!   *
;                                                                         *
;**************************************************************************

;--------------------------------------------------------------------------
; 7-segment LED data table
;--------------------------------------------------------------------------

    ; Index 0..9 used for decimal numbers, all other indices defined below :
CHAR_A    equ  .10                 ; Letters A..F = HEX digits, index 10..15
CHAR_b    equ  .11                 ;
CHAR_c    equ  .12                 ;
CHAR_d    equ  .13                 ;
CHAR_E    equ  .14                 ; 
CHAR_F    equ  .15                 ; 
CHAR_G    equ  .16                 ; Other letters used in "programming" mode 
CHAR_H    equ  .17                 ; 
CHAR_i    equ  .18                 ; 

BLANK     equ  .19                 ; blank display
TEST      equ  .20                 ; power-on display test

CHAR_P    equ  .21                 ; A few other letters for programming mode...
CHAR_r    equ  .22                 ;
CHAR_o    equ  .23                 ;   "Prog"
CHAR_Q    equ  .24                 ;   "Quit"
CHAR_u    equ  .25                 ;
CHAR_t    equ  .26                 ;
CHAR_S    equ  .27                 ;   "Sub"   
CHAR_Z    equ  .28                 ;   "ZEro"
CHAR_I    equ  .29                 ;   large "I" (left aligned!) for "IF"
CHAR_J    equ  .30                 ;
CHAR_k    equ  .31                 ;
CHAR_L    equ  .32                 ;
CHAR_N    equ  .33                 ;
CHAR_V    equ  .34                 ;
CHAR_EQ   equ  .35                 ;   "="


#if (DISP_VARIANT==1) 
DPPOINT_BIT equ  4   ; decimal point bit (same for all digits)
#define _A  0x01     ; bitmask for segment A , etc ..
#define _B  0x02
#define _C  0x20
#define _D  0x08
#define _E  0x04
#define _F  0x40
#define _G  0x80
#define _DP 0x10
#endif   ; DISPLAY VARIANT #1
#if (DISP_VARIANT==2) || (DISP_VARIANT==3)
DPPOINT_BIT equ  1   ; decimal point bit (same for all digits)
#define _A  0x40     ; bitmask for segment A , etc ..
#define _B  0x80
#define _C  0x04
#define _D  0x01
#define _E  0x08
#define _F  0x10
#define _G  0x20
#define _DP 0x02
#endif   ; DISPLAY VARIANT #2 + #3


BLANK_PATTERN equ b'00000000'      ; blank display pattern (7-segment code)


;-----------------------------------------------------------------------------
;  Table to convert a decimal digit or a special character into 7-segment-code
;   Note: In DL4YHF's PIC counter, all digits have the same segment connections,
;         so we do not need individual conversion tables for all segments.
;        
;  AAAA
; F    B
; F    B
;  GGGG
; E    C
; E    C
;  DDDD   DP
;
;-----------------------------------------------------------------------------
Digit2SevenSeg:
          addwf PCL,f  ; caution: this is 'PCL' only, not 'PC'. Beware of page borders.
          ; A = 0, B = 1, C = 5, D = 3, E = 2, F = 6, G = 7, DP = 4
#if (COMMON_ANODE)
 #define SSEG_XORMASK 0xFF  ; since 2005-03-21 ... never tested by the author !
#else
 #define SSEG_XORMASK 0x00  ; for COMMON CATHODE: No bitwise EXOR to the pattern
#endif
          retlw (_A+_B+_C+_D+_E+_F   )^SSEG_XORMASK ; ABCDEF. = '0'    ( # 0  )
          retlw (   _B+_C            )^SSEG_XORMASK ; .BC.... = '1'    ( # 1  )
          retlw (_A+_B   +_D+_E   +_G)^SSEG_XORMASK ; AB.DE.G = '2'    ( # 2  )
          retlw (_A+_B+_C+_D      +_G)^SSEG_XORMASK ; ABCD..G = '3'    ( # 3  )
          retlw (   _B+_C      +_F+_G)^SSEG_XORMASK ; .BC..FG = '4'    ( # 4  )
          retlw (_A   +_C+_D   +_F+_G)^SSEG_XORMASK ; A.CD.FG = '5'    ( # 5  )
          retlw (_A   +_C+_D+_E+_F+_G)^SSEG_XORMASK ; A.CDEFG = '6'    ( # 6  )
          retlw (_A+_B+_C            )^SSEG_XORMASK ; ABC.... = '7'    ( # 7  )
          retlw (_A+_B+_C+_D+_E+_F+_G)^SSEG_XORMASK ; ABCDEFG = '8'    ( # 8  )
          retlw (_A+_B+_C+_D   +_F+_G)^SSEG_XORMASK ; ABCD.FG = '9'    ( # 9  )
          retlw (_A+_B+_C   +_E+_F+_G)^SSEG_XORMASK ; ABC.EFG = 'A'    ( # 10 )
          retlw (      _C+_D+_E+_F+_G)^SSEG_XORMASK ; ..CDEFG = 'b'    ( # 11 )
          retlw (         _D+_E   +_G)^SSEG_XORMASK ; ...DE.G = 'c'    ( # 12 )
          retlw (   _B+_C+_D+_E   +_G)^SSEG_XORMASK ; .BCDE.G = 'd'    ( # 13 )
          retlw (_A      +_D+_E+_F+_G)^SSEG_XORMASK ; A..DEFG = 'E'    ( # 14 )
          retlw (_A         +_E+_F+_G)^SSEG_XORMASK ; A...EFG = 'F'    ( # 15 )
          retlw (_A   +_C+_D+_E+_F   )^SSEG_XORMASK ; A.CDEF. = 'G'    ( # 16 )
          retlw (   _B+_C   +_E+_F+_G)^SSEG_XORMASK ; .BC.EFG = 'H'    ( # 17 )
          retlw (            _E      )^SSEG_XORMASK ; ....E.. = 'i'    ( # 18 )

          retlw (BLANK_PATTERN       )^SSEG_XORMASK ; ....... = ' '    ( # 19 )
          retlw (b'11111111'         )^SSEG_XORMASK ; all segments on  ( # 20 )

          ; A few more letters for programming mode :
          retlw (_A+_B      +_E+_F+_G)^SSEG_XORMASK ; AB..EFG = 'P'    ( # 21 )
          retlw (            _E   +_G)^SSEG_XORMASK ; ....E.G = 'r'    ( # 22 )
          retlw (      _C+_D+_E   +_G)^SSEG_XORMASK ; ..CDE.G = 'o'    ( # 23 )
          retlw (_A+_B+_C      +_F+_G)^SSEG_XORMASK ; ABC..FG = 'Q'    ( # 24 )
          retlw (      _C+_D+_E      )^SSEG_XORMASK ; ..CDE.. = 'u'    ( # 25 )
          retlw (         _D+_E+_F+_G)^SSEG_XORMASK ; ...DEFG = 't'    ( # 26 )
          retlw (_A   +_C+_D   +_F+_G)^SSEG_XORMASK ; A.CD.FG = 'S'    ( # 27 )
          retlw (_A+_B   +_D+_E   +_G)^SSEG_XORMASK ; AB.DE.G = 'Z'    ( # 28 )
          retlw (            _E+_F   )^SSEG_XORMASK ; ....EF. = 'I'    ( # 29 )
          retlw (   _B+_C+_D         )^SSEG_XORMASK ; .BCD..  = 'J'    ( # 30 )
          retlw (         _D+_E+_F+_G)^SSEG_XORMASK ; ...DEFG = 'k'    ( # 31 )
          retlw (         _D+_E+_F   )^SSEG_XORMASK ; ...DEF. = 'L'    ( # 32 )
          retlw (_A+_B+_C   +_E+_F   )^SSEG_XORMASK ; ABC.EF. = 'N'    ( # 33 )
          retlw (      _C+_D+_E+_F   )^SSEG_XORMASK ; ..CDEF. = 'V'    ( # 34 )
          retlw (         _D      +_G)^SSEG_XORMASK ; ...D..G = '='    ( # 35 )



;--------------------------------------------------------------------------
; Table to control which 7-segment display is enabled. Displays are usually
; COMMON CATHODE (variants 1+2) so pulled low to enable.
; For DISP_VARIANT=3 (COMMON ANODE), the digit-driving pattern is inverted.
; Input:   W = 0 means the MOST SIGNIFICANT DIGIT (the leftmost one), etc.
; Result:  VALUE to be written to ENABLE_PORT to activate the digit
;--------------------------------------------------------------------------
Digit2MuxValue:     ; 
          addwf PCL,f  ; caution: this is 'PCL' only, not 'PC'
          ; Note: If the program counter is affected, a command requires to instruction cycles (=8 osc cycles)
#if (DISP_VARIANT==1)  ; muliplexer values for DISPLAY VARIANT #1 :
          retlw b'11110111'        ; most significant digit is on   PA3 (!)
          retlw b'11111110'        ; next less significant dig. on  PA0 (!)
          retlw b'11111011'        ; next less significant dig. on  PA2 (!)
          retlw b'11111101'        ; 4th (sometimes the last) digit PA1 (!)
          retlw b'11111111'        ; 5th (OPTIONAL) least significant digit = NOT (PA3+PA2+PA1+PA0)
#endif   ; DISPLAY VARIANT #1
#if (DISP_VARIANT==2)  ; muliplexer values for DISPLAY VARIANT #2 (5 digits, COMMON CATHODE) :
          retlw b'11110111'        ; most significant digit is on   PA3 (!)
          retlw b'11111011'        ; next less significant dig. on  PA2 (!!)
          retlw b'11111110'        ; next less significant dig. on  PA0 (!!)
          retlw b'11111101'        ; 4th (sometimes the last) digit PA1 (!)
          retlw b'11111111'        ; 5th (OPTIONAL) least significant digit = NOT (PA3+PA2+PA1+PA0)
#endif   ; DISPLAY VARIANT #2
#if (DISP_VARIANT==3)  ; muliplexer values for DISPLAY VARIANT #3 (5 digits, COMMON ANODE) :
                       ; Unused bits (b7..b4) are left HIGH as above .
          retlw b'11111000'        ; most significant digit is on   PA3 (!)
          retlw b'11110100'        ; next less significant dig. on  PA2 (!!)
          retlw b'11110001'        ; next less significant dig. on  PA0 (!!)
          retlw b'11110010'        ; 4th (sometimes the last) digit PA1 (!)
          retlw b'11110000'        ; 5th (OPTIONAL) least significant digit = NOT (PA3+PA2+PA1+PA0)
#endif   ; DISPLAY VARIANT #2



;--------------------------------------------------------------------------
; Powers-of-ten table (32 bits, most significant byte first)
;   Based on an idea by James Hutchby (MadLab, 1996) .
;   Modified for 32-bit arithmetic by Wolfgang Buescher (2004).
;--------------------------------------------------------------------------
TensTable  addwf PCL,f  
           cquad   .10000000  ; 10 million is sufficient for the counter itself
           cquad   .1000000
           cquad   .100000
           cquad   .10000
           cquad   .1000
           cquad   .100
           cquad   .10
           cquad   .1


;--------------------------------------------------------------------------
; DISPLAY jump table for programming mode .
;   Loads the display-strings like "quit" etc into the display latches.
; Input parameter:  menu_index (0 .. MI_INDEX_MAX)
; Output placed in  display0..display3
;
;--------------------------------------------------------------------------
PMDisplay:
          movfw  menu_index  ; load menu index into W register
          addwf  PCL, f      ; add W to lower part of program counter (computed jump)
          goto   PmDisp_Quit ; show "quit" (quit programming mode)
          goto   PmDisp_PSave; show "PSave"(power-saving mode on/off)
          goto   PmDisp_Add  ; show "add " (add frequency offset)
          goto   PmDisp_Sub  ; show "sub " (subtract frequency offset)
          goto   PmDisp_Zero ; show "Zero" (set frequency offset to zero)
          goto   PmDisp_StIF ; show "StdIF" (select standard IF from table)
          goto   PmDisp_IF_1 ; show 1st standard IF from table
          goto   PmDisp_IF_2 ; show 2nd standard IF from table
          goto   PmDisp_IF_3 ; show 3rd standard IF from table
          goto   PmDisp_IF_4 ; show 4th standard IF from table
          goto   PmDisp_IF_5 ; show 5th standard IF from table
          goto   PmDisp_Quit ; show "quit" (quit STANDARD IF menu)
          ; Add more display strings here if needed !

;--------------------------------------------------------------------------
; EXECUTION jump table for programming mode .
;   Executes the commands "quit", "psave", "add", "sub", "zero", etc.
; Input parameter:  menu_index (0 .. MI_INDEX_MAX)
;--------------------------------------------------------------------------
PMExecute:   ; Execute the function belonging to menu_index
          movfw  menu_index  ; load menu index into W register
          addwf  PCL, f      ; add W to lower part of program counter (computed jump)
          goto   PmExec_Quit ; quit programming mode
          goto   PmExec_PSave; turn power-saving mode on/off
          goto   PmExec_Add  ; add frequency offset from now on
          goto   PmExec_Sub  ; subtract frequency offset from now on
          goto   PmExec_Zero ; set frequency offset to zero

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -