📄 counter.asm
字号:
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 + -