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

📄 counter.asm

📁 PIC16F628A芯片制作的频率计
💻 ASM
📖 第 1 页 / 共 5 页
字号:
          goto   PmExec_StIF ; switch to  "Standard IF selection mode"
          goto   PmExec_SelIF ; select 1st standard IF from table
          goto   PmExec_SelIF ; select 2nd standard IF from table
          goto   PmExec_SelIF ; select 3rd standard IF from table
          goto   PmExec_SelIF ; select 4th standard IF from table
          goto   PmExec_Quit ; quit STANDARD IF menu
          ; Add more jumps here if needed !



;**************************************************************************
;                                                                         *
; Procedures                                                              *
;                                                                         *
;**************************************************************************


;--------------------------------------------------------------------------
;  Configure the prescaler for TIMER 0 in the PIC's OPTION register .
;--------------------------------------------------------------------------

; Description of the OPTION register, from the PIC16F628 data sheet:
; bit 7: RBPU: PORTB Pull-up Enable bit
;        1 = PORTB pull-ups are disabled
;        0 = PORTB pull-ups are enabled by individual port latch values
; bit 6: INTEDG: Interrupt Edge Select bit
;        1 = Interrupt on rising edge of RB0/INT pin
;        0 = Interrupt on falling edge of RB0/INT pin
; bit 5: T0CS: TMR0 Clock Source Select bit
;        1 = Transition on RA4/T0CKI pin
;        0 = Internal instruction cycle clock (CLKOUT)
; bit 4: T0SE: TMR0 Source Edge Select bit
;        1 = Increment on high-to-low transition on RA4/T0CKI pin
;        0 = Increment on low-to-high transition on RA4/T0CKI pin
; bit 3: PSA: Prescaler Assignment bit
;        1 = Prescaler is assigned to the WDT
;        0 = Prescaler is assigned to the Timer0 module
; bit 2-0: PS2:PS0: Prescaler Rate Select bits, here shown for TMR0 :
;     000  = 1 : 2
; ... 111  = 1 : 256
;        Note: to count EVERY pulse (1 : 1) with TMR0, the prescaler
;              must be assigned to the WATCHDOG TIMER (WDT) !
; Some examples (for the OPTION register, parameter in W for SetPrescaler):
PSC_DIV_BY_2   equ  b'00100000'   ; let prescaler divide TMR0 by two
PSC_DIV_BY_4   equ  b'00100001'   ; let prescaler divide TMR0 by   4
PSC_DIV_BY_8   equ  b'00100010'   ; let prescaler divide TMR0 by   8
PSC_DIV_BY_16  equ  b'00100011'   ; let prescaler divide TMR0 by  16
PSC_DIV_BY_32  equ  b'00100100'   ; let prescaler divide TMR0 by  32
PSC_DIV_BY_64  equ  b'00100101'   ; let prescaler divide TMR0 by  64
PSC_DIV_BY_128 equ  b'00100110'   ; let prescaler divide TMR0 by 128
PSC_DIV_BY_256 equ  b'00100111'   ; let prescaler divide TMR0 by 256

SetPrescaler:  ; copy W into OPTION register, avoid watchdog trouble
          clrwdt     ; recommended by Microchip ("switching prescaler assignment") 
          errorlevel -302 ; Turn off banking message for the next few instructions..
          bsf   STATUS, RP0            ;! setting RP0 enables access to OPTION reg
               ; option register is in bank1. i know. thanks for the warning.
          movwf OPTION_REG             ;! ex: "option" command (yucc)
          bcf   STATUS, RP0            ;! clearing RP0 for normal register access
          errorlevel +302 ; Enable banking message again
          retlw 0


PrescalerOff:  ; turn the prescaler for TMR0 "off" 
               ; (actually done by assigning the prescaler to the watchdog timer)
          clrwdt                        ; clear watchdog timer
          clrf  TMR0                    ; clear timer 0 AND PRESCALER(!)
          errorlevel -302 ; Turn off banking message for the next few instructions..
          bsf   STATUS, RP0            ;! setting RP0 enables access to OPTION reg
               ; option register is in bank1. i know. thanks for the warning.
          movlw b'00100111'            ;! recommended by Microchip when
                                       ;! changing prescaler assignment from TMR0 to WDT
          movwf OPTION_REG             ;! ex: "option" command (yucc)
          clrwdt                       ;! clear watchdog again
          movlw b'00101111'            ;! bit 3 set means PS assigned to WDT now
          movwf OPTION_REG             ;! ex: "option" command (yucc)
          bcf   STATUS, RP0            ;! clearing RP0 for normal register access
          errorlevel +302 ; Enable banking message again
          retlw 0


;--------------------------------------------------------------------------
; Power-saving subroutine: Puts the PIC to sleep for ROUGHLY 100 milliseconds .
;  - crystal oscillator turned OFF during this phase
;  - only the internal RC-oscillator for the watchdog keeps running
;  - expiration of watchdog during sleep does NOT reset the PIC, 
;    only wakes it up again so normal operation may resume 
;  - LED display will be off during this time 
;--------------------------------------------------------------------------
Sleep150ms:  ; go to sleep for approx. 150 milliseconds, and then RETURN (no reset)
   ; Details on the PIC's watchdog timer (from PIC16F628 datasheet) :
   ; > The WDT has a nominal timeout period of 18 ms (with
   ; > no prescaler). The timeout periods vary with temperature,
   ; > VDD and process variations from part to part (see
   ; > DC specs).
   ; > The Watchdog Timer is a free running on-chip RC oscillator which does 
   ; > not require any external components. This RC oscillator is separate 
   ; > from the ER oscillator of the CLKIN pin. That means that the WDT will run, 
   ; > even if the clock on the OSC1 and OSC2 pins of the device has been stopped, 
   ; > for example, by execution of a SLEEP instruction. 
   ; > During normal operation, a WDT timeout generates a device RESET.
   ; > If the device is in SLEEP mode, a WDT timeout causes the device to wake-up 
   ; > and continue with normal operation.
   ; > The WDT can be permanently disabled by programming the configuration bit 
   ; > WDTE as clear .
   ; In other words, to use the watchdog-timer for "temporary sleep" here ,
   ; it must be ENABLED in the configuration word when programming the PIC.
   ;  (because its not possible to turn it on via software if it's not on).
   ; But once the watchdog timer is ON, it must be FED periodically otherwise
   ; it will reset the PIC during normal operation !
   ; Here (in the frequency counter), the prescaler remains assigned to timer0
   ; so the watchdog interval is ~ 18 milliseconds (+/-, RC-oscillator) .
   ; > The CLRWDT and SLEEP instructions clear the WDT and the postscaler, 
   ; > if assigned to the WDT, and prevent it from timing out and generating
   ; >  a device RESET. The TO bit in the STATUS register will be cleared upon
   ; > a Watchdog Timer timeout.
#if(COMMON_CATHODE)  ; display with COMMON CATHODE : 
          movlw 0x00                    ; segment drivers LOW to turn off
#else  ; not COMMON CATHODE but COMMON ANODE:
          movlw 0xFF                    ; segment drivers HIGH to turn off
#endif
          movwf LEDS_PORT               ; turn LED segments off
          ; Note: The global interrupt-enable flag (GIE) is off in this application !
          ; To avoid unintended wake-up on 'interrupt' (port level change),
          ; disable all interrupt-SOURCES: Clear T0IE,INTE,RBIE,PEIE too :
          clrf  INTCON                  ; disable all interrupts during SLEEP mode
          clrwdt                        ; clear watchdog timer
          clrf  TMR0                    ; clear timer 0 AND PRESCALER(!)
          errorlevel -302 ; Turn off banking message for the next few instructions..
          bsf   STATUS, RP0            ;! setting RP0 enables access to OPTION reg
               ; option register is in bank1. i know. thanks for the warning.
          movlw b'00101011'            ;! assign PS to WDT; divide by 8 FOR WDT(!)
          movwf OPTION_REG             ;! ex: "option" command (yucc)
          bcf   STATUS, RP0            ;! clearing RP0 for normal register access
          errorlevel +302 ; Enable banking message again
          sleep                         ; sleep for approx 18 ms (one watchdog interval)
          ; The SLEEP command clears the Watchdog Timer and stops the main oscillator.
          ; Only the internal watchdog timer keeps running.
          ; The WDT is is also cleared when the device wakes-up from SLEEP, 
          ; regardless of the source of wake-up, so no need for 'clrwdt' here !
          nop    ; arrived here, slept for ~ 8 times 18 milliseconds
          return ; end  Sleep150ms
              



;--------------------------------------------------------------------------
; Convert a character into LEDs data for the 7-segment displays, fed with
; the character in w.  Bit 7 set means 'decimal point AFTER this digit' .
;--------------------------------------------------------------------------

conv      macro display                 ; macro for duplicate code
          movwf display                 ; save decimal point bit (msb)
          andlw 7fh                     ; mask bit
          call  Digit2SevenSeg          ; convert digit into 7-segment-code via table
          btfsc display,7               ; check bit 7 = decimal point ?
#if(COMMON_CATHODE)
          iorlw 1<<DPPOINT_BIT          ; include decimal point if bit 7 set (bitwise OR)
#else  ; not COMMON CATHODE but COMMON ANODE: decimal point must be 'AND'ed to pattern:
          andlw (1<<DPPOINT_BIT)^0xFF   ; include decimal point if bit 7 set (bitwise AND)
#endif
          movwf display                 ; set display data register
          endm

conv_char0:   ; display digit #0  (leftmost, or MOST SIGNIFICANT digit)
          conv  display0
          retlw 0

conv_char1:   ; display #1
          conv  display1
          retlw 0

conv_char2:   ; display #2
          conv  display2
          retlw 0

conv_char3:   ; display #3
          conv  display3
          retlw 0

conv_char4:   ; display #4  (rightmost, or LEAST SIGNIFICANT digit, "ones")
          conv  display4
          retlw 0


;--------------------------------------------------------------------------
; Fill the 5-digit display latch with blank characters
;--------------------------------------------------------------------------
ClearDisplay:
          movlw BLANK_PATTERN
          movwf display0
          movwf display1
          movwf display2
          movwf display3
          movwf display4
          retlw 0



;--------------------------------------------------------------------------
; Save a single Byte in the PIC's Data-EEPROM.
;  Input parameters:
;    INDF = *FSR    contains byte to be written (was once EEDATA)
;    w              contains EEPROM address offset (i.e. "destination index")
;
;--------------------------------------------------------------------------
        ; write to EEPROM data memory as explained in the 16F628 data sheet.
        ; EEDATA and EEADR must have been set before calling this subroutine
        ; (optimized for the keyer-state-machine).
        ; CAUTION : What the lousy datasheet DS40300B wont tell you:
        ;           The example given there for the 16F628 is WRONG ! 
        ;           All EEPROM regs are in BANK1 for the 16F628. 
        ;           In the PIC16F84, some were in BANK0 others in BANK1..
        ; In the PIC16F628, things are much different... all EEPROM regs are in BANK1 !
SaveInEEPROM:    ; save "INDF" = *FSR   in EEPROM[<w>]
         bcf     INTCON, GIE           ; disable INTs
         errorlevel -302 ; Turn off banking message for the next few instructions..
         bsf     STATUS, RP0         ;!; Bank1 for "EEADR" access, PIC16F628 ONLY (not F84)
         movwf   EEADR               ;!; write into EEPROM address register (BANK1 !!)
         bcf     STATUS, RP0         ;!; Bank0 to read "bStorageData"
         movfw   INDF                ; ; w := *FSR (read source data from BANK 0)
         bsf     STATUS, RP0         ;!; Bank1 for "EEDATA" access, PIC16F628 ONLY (not F84)
         movwf   EEDATA              ;!; EEDATA(in BANK1) := w  (BANK1; F628 only, NOT F84 !!!)
         bsf     EECON1, WREN        ;!; set WRite ENable
         bcf     INTCON, GIE         ;!; Is this REALLY required as in DS40300B Example 13-2 ?
         movlw   055h                ;!;
         movwf   EECON2              ;!; write 55h
         movlw   0AAh                ;!;
         movwf   EECON2              ;!; write AAh
         bsf     EECON1, WR          ;!; set WR bit, begin write
         ; wait until write access to the EEPROM is complete.
SaveEW:  btfsc   EECON1, WR          ;!; WR is cleared after completion of write
         goto    SaveEW              ;!; WR=1, write access not finished yet
         ; Arrived here: the EEPROM write is ready
         bcf     EECON1, WREN        ;!; disable further WRites
         bcf     STATUS, RP0         ;!; Bank0 for normal access
         errorlevel +302 ; Enable banking message again
   ;     bsf     INTCON, GIE           ; enable INTs ? NOT IN THIS APPLICATION !
         retlw   0  ; end SaveInEEPROM


;--------------------------------------------------------------------------
; Read a single Byte from the PIC's Data-EEPROM.
;  Input parameters:
;    w    contains EEPROM address offset (i.e. "source index")
;         will *NOT* be modified to simplify block-read .
;    FSR  points to the memory location where the byte shall be placed.
;
;  Result:
;     INDF = *FSR  returns the read byte
;--------------------------------------------------------------------------
        ; Caution: EEDATA and EEADR have been moved from Bank0(16F84) to Bank1(16F628)
        ;          and the example from the datasheet telling you to switch to 

⌨️ 快捷键说明

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