如何使用 PIC 16 制作倒数计时器

How to make a countdown timer using PIC 16

我的倒数计时器从 30 分钟开始(分钟的十位为 3,分钟的个位为 0,秒的十位和个位为 0)。我关注了这个 youtube 视频 https://www.youtube.com/watch?v=mIG8N5sbXUY&t=1782s 但我没有增加秒数,而是减少了秒数。我对 PIC 汇编还很陌生,所以我不知道为什么视频中的代码不起作用,但它不起作用。下面是我的代码

      LIST P=16F84A, F=INHX8M        
      INCLUDE<P16F84A.INC>                                   
      __CONFIG _CP_OFF & _WDT_ON & _XT_OSC    

MINUTE_TENS     EQU     0x20
MINUTE_UNITS    EQU     0x21
SECOND_TENS EQU     0x22
SECOND_UNITS    EQU     0x23
COUNT           EQU     0x24

    ORG     0X00
    GOTO        START 
    ORG     0X04
    GOTO        ISR

LOOKUP  ADDWF   PCL,F
        RETLW   0X00
        RETLW   0X01
        RETLW   0X02
        RETLW   0X03
        RETLW   0X04
        RETLW   0X05
        RETLW   0X06
        RETLW   0X07
        RETLW   0X08
        RETLW   0X09

ISR     MOVLW   0x0C
        MOVWF   TMR0
        BCF     INTCON,TMR0IF
        DECFSZ  COUNT,F
        RETFIE
        MOVLW   .122
        MOVWF   COUNT
        
        DECF    SECOND_UNITS,F
        MOVF    SECOND_UNITS,W
        SUBLW   0x00
        BTFSS   STATUS,C
        RETFIE
        CLRF    SECOND_UNITS
        
        DECF    SECOND_TENS,F
        MOVF    SECOND_TENS,W
        SUBLW   0x00
        BTFSS   STATUS,C
        RETFIE
        CLRF    SECOND_TENS
        
        DECF    MINUTE_UNITS,F
        MOVF    MINUTE_UNITS,W
        SUBLW   0x00
        BTFSS   STATUS,C
        RETFIE
        CLRF    MINUTE_UNITS
        
        DECF    MINUTE_TENS,F
        MOVF    MINUTE_TENS,W
        SUBLW   0x00
        BTFSS   STATUS,C
        RETFIE
        CLRF    MINUTE_TENS
        RETFIE

DELAY   NOP
        RETURN
    
START   BSF     STATUS, RP0
        CLRF    TRISA
        MOVLW   0x70
        MOVWF   TRISB
        MOVLW   0x44
        MOVWF   OPTION_REG
        BCF     STATUS, RP0
        MOVLW   0x0C
        MOVWF   TMR0
        MOVLW   .122
        MOVWF   COUNT
        MOVLW   0xA0
        MOVWF   INTCON              ;enable tmr0 interrupt

        MOVLW   3                   ;start at 30:00
        MOVWF   MINUTE_TENS
        CLRF    MINUTE_UNITS
        CLRF    SECOND_TENS
        CLRF    SECOND_UNITS
        CLRF    PORTA

MAIN    MOVF    MINUTE_TENS,W
        CALL    LOOKUP
        MOVWF   PORTB
        BSF     PORTA,RA0
        CALL    DELAY               ;1 ms
        BCF     PORTA,RA0

        MOVF    MINUTE_UNITS,W
        CALL    LOOKUP
        MOVWF   PORTB
        BSF     PORTA,RA1
        CALL    DELAY               ;1 ms
        BCF     PORTA,RA1

        MOVF    SECOND_TENS,W
        CALL    LOOKUP
        MOVWF   PORTB
        BSF     PORTA,RA2
        CALL    DELAY               ;1 ms
        BCF     PORTA,RA2

        MOVF    SECOND_UNITS,W
        CALL    LOOKUP
        MOVWF   PORTB
        BSF     PORTA,RA3
        CALL    DELAY               ;1 ms
        BCF     PORTA,RA3

        GOTO    MAIN
        
        END

LED 的多路复用工作但不倒计时。我怎样才能让这个倒计时每秒?看来我的 tmr0 不工作了。

您发布的代码与您声明的不符。

这段代码似乎模拟正确:

MPASM  5.22                          MAIN.ASM   3-3-2022  0:58:20         PAGE  1


LOC  OBJECT CODE     LINE SOURCE TEXT
  VALUE

                      00001     list        c=132,n=0   ; Make .LST look nice
                      00002     list        p=16F84A    ; Tell assembler the controller we are using
                      00003     list        r=dec       ; Use desciaml as default radix for expressions
                      00004     errorlevel  -224        ; Suppress Use of this instruction is not recommended warning
                      00005 ;
                      00006 ; File:     main.asm
                      00007 ; Target:   PIC16F84A
                      00008 ; Author:   dan1138
                      00009 ; Date:     2022-MAR-02
                      00010 ; Compiler: MPASMWIN(v5.22) absolute mode
                      00011 ; IDE:      none
                      00012 ;
                      00013 ; Description:
                      00014 ;
                      00015 ;   Example project for the PIC16F84 controller using the MPASMWIN(v5.22) from the command line.
                      00016 ;
                      00017 ;
                      00018 ;                           PIC16F84A
                      00019 ;                   +----------:_:----------+
                      00020 ;     DIGIT_3 <>  1 : RA2               RA1 : 18 <> DIGIT_2
                      00021 ;     DIGIT_4 <>  2 : RA3               RA0 : 17 <> DIGIT_1
                      00022 ;             <>  3 : RA4/T0CKI        OSC1 : 16 <- 4MHz crystal
                      00023 ;    ICSP_VPP ->  4 : MCLR             OSC2 : 15 -> 4MHz crystal
                      00024 ;         GND ->  5 : GND               VDD : 14 <- 5v0
                      00025 ;   LED_SEG_g <>  6 : RB0/INT       PGD/RB7 : 13 <> LED_SEG_dp/ICSP_PGD
                      00026 ;   LED_SEG_f <>  7 : RB1           PGC/RB6 : 12 <> LED_SEG_a /ICSP_PGC
                      00027 ;   LED_SEG_e <>  8 : RB2               RB5 : 11 <> LED_SEG_b
                      00028 ;   LED_SEG_d <>  9 : RB3               RB4 : 10 <> LED_SEG_c
                      00029 ;                   +-----------------------:
                      00030 ;                            DIP-18
                      00031 ;
                      00032 ;
                      00033 ; Include target specific definitions for special function registers
                      00034 ;
                      00035 #include "p16f84A.inc"
                      00001         LIST
                      00002 
                      00003 ;==========================================================================
                      00004 ;  MPASM PIC16F84A processor include
                      00005 ; 
                      00006 ;  (c) Copyright 1999-2013 Microchip Technology, All rights reserved
                      00007 ;==========================================================================
                      00008 
                      00208         LIST
                      00036 ;
                      00037 ; Set the configuration word
                      00038 ;
2007   3FF1           00039   __CONFIG _XT_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
                      00040 ;
                      00041 ;
                      00042 ;
                      00043 ;
                      00044 ; Declare RAM for application
                      00045 ;
                      00046   CBLOCK 0x0C
  0000000C            00047     TMR0_Sample      :1     ; Sample of TIMER0 use for system tick
  0000000D            00048     TicksInOneSec    :1     ; Count Ticks in one second
  0000000E            00049     Seconds          :2     ; Seconds: units, tens
  00000010            00050     Minutes          :2     ; Minutes: units, tens
  00000012            00051     LED_Segments     :4     ; Segment refresh buffer
  00000016            00052     LED_DigitOn      :1     ; Mask of which one digit is on
                      00053   ENDC
                      00054 
                      00055 
                      00056 ;
                      00057 ; Define how much real time is in a system tick.
                      00058 ;   This application uses a system tick of 4 milliseconds.
                      00059 ;
                      00060 ;   This is:
                      00061 ;       FOSC / 4 / TMR0_prescale = (TIMER0 clock frequency)
                      00062 ;       4000000/4/32 = 31250 Hz
                      00063 ;
                      00064 ;       (TIMER0 clock frequency) / TMR0_8_MS = System tick frequency
                      00065 ;       31250/125 = 250 Hz
                      00066 ;
                      00067 ;       250 Hz has a period of 0.004 seconds.
                      00068 ;
                      00069 #define TMR0_4_MS d'125'          ; TIMER0 counts in 4 milliseconds
                      00070 #define TICKS_PER_SECOND d'250'   ; System ticks in one second
                      00071 ;
                      00072 ; ==============================================================
                      00073 ; Power on reset
                      00074 ;
0000                  00075     org 0x0000
0000                  00076 Start:
0000   2854           00077     goto    main
0001                  00078 LookupSegments:
0001   018A           00079     clrf    PCLATH
0002   390F           00080     andlw   h'0F'
0003   0782           00081     addwf   PCL,F
                      00082 ;            abcdefg       _   
0004   347E           00083     dt    b'01111110'  ;  | |  
                      00084                        ;  |_|  
                      00085                        ;       
0005   3430           00086     dt    b'00110000'  ;    |  
                      00087                        ;    |  
                      00088                        ;   _   
0006   346D           00089     dt    b'01101101'  ;   _|  
                      00090                        ;  |_   
                      00091                        ;   _   
0007   3479           00092     dt    b'01111001'  ;   _|  
                      00093                        ;   _|  
                      00094                        ;       
0008   3433           00095     dt    b'00110011'  ;  |_|  
                      00096                        ;    |  
                      00097                        ;   _   
0009   345B           00098     dt    b'01011011'  ;  |_   
                      00099                        ;   _|  
                      00100                        ;   _   
000A   345F           00101     dt    b'01011111'  ;  |_   
                      00102                        ;  |_|  
                      00103                        ;   _   
000B   3470           00104     dt    b'01110000'  ;    |  
                      00105                        ;    |  
                      00106                        ;   _   
000C   347F           00107     dt    b'01111111'  ;  |_|  
                      00108                        ;  |_|  
                      00109                        ;   _   
000D   3473           00110     dt    b'01110011'  ;  |_|  
                      00111                        ;    |  
                      00112                        ;   _   
000E   3477           00113     dt    b'01110111'  ;  |_|  
                      00114                        ;  | |  
                      00115                        ;       
000F   341F           00116     dt    b'00011111'  ;  |_   
                      00117                        ;  |_|  
                      00118                        ;   _   
0010   344E           00119     dt    b'01001110'  ;  |    
                      00120                        ;  |_   
                      00121                        ;       
0011   343D           00122     dt    b'00111101'  ;   _|  
                      00123                        ;  |_|  
                      00124                        ;   _   
0012   344F           00125     dt    b'01001111'  ;  |_   
                      00126                        ;  |_   
                      00127                        ;   _   
0013   3447           00128     dt    b'01000111'  ;  |_   
                      00129                        ;  |    
                      00130 ;
                      00131 ; ==============================================================
                      00132 ; The LED task is called every system tick (4 milliseconds)
                      00133 ;
                      00134 ; It refreshes one of the four LED digits from the segment buffer.
                      00135 ;
0014                  00136 LED_Task:
0014   0816           00137     movf    LED_DigitOn,W
0015   0716           00138     addwf   LED_DigitOn,W
0016   390F           00139     andlw   h'0F'
0017   1903           00140     skpnz
0018   3801           00141     iorlw   1
0019   0096           00142     movwf   LED_DigitOn
001A   1816           00143     btfsc   LED_DigitOn,0
001B   0812           00144     movf    LED_Segments+0,W
001C   1896           00145     btfsc   LED_DigitOn,1
001D   0813           00146     movf    LED_Segments+1,W
001E   1996           00147     btfsc   LED_DigitOn,3
001F   0814           00148     movf    LED_Segments+2,W
0020   1996           00149     btfsc   LED_DigitOn,3
0021   0815           00150     movf    LED_Segments+3,W
0022   0185           00151     clrf    PORTA
0023   0086           00152     movwf   PORTB
0024   0816           00153     movf    LED_DigitOn,W
0025   0085           00154     movwf   PORTA
0026   0008           00155     return
                      00156 ;
                      00157 ; ==============================================================
                      00158 ; The Count Down task is called every system tick (4 milliseconds)
                      00159 ;
                      00160 ; This task count system ticks until one second has elapsed (250 counts)
                      00161 ; Decrements the 30 minute time to zero
                      00162 ; Converts the minutes and seconds to segments
                      00163 ; Updates the segment buffer
                      00164 ;
0027                  00165 CountDown_Task:
0027   0B8D           00166     decfsz  TicksInOneSec,F
0028   0008           00167     return
0029   30FA           00168     movlw   TICKS_PER_SECOND
002A   008D           00169     movwf   TicksInOneSec
                      00170 
002B   038E           00171     decf    Seconds,F
002C   1E0E           00172     btfss   Seconds,4
002D   283F           00173     goto    UpdateSegments
002E   3009           00174     movlw   d'9'
002F   008E           00175     movwf   Seconds
                      00176 
0030   038F           00177     decf    Seconds+1,F
0031   1E0F           00178     btfss   Seconds+1,4
0032   283F           00179     goto    UpdateSegments
0033   3005           00180     movlw   d'5'
0034   008F           00181     movwf   Seconds+1
                      00182 
0035   0390           00183     decf    Minutes,F
0036   1E10           00184     btfss   Minutes,4
0037   283F           00185     goto    UpdateSegments
0038   3009           00186     movlw   d'9'
0039   0090           00187     movwf   Minutes
                      00188 
003A   0391           00189     decf    Minutes+1,F
003B   1E11           00190     btfss   Minutes+1,4
003C   283F           00191     goto    UpdateSegments
003D   3003           00192     movlw   d'3'
003E   0091           00193     movwf   Minutes+1
                      00194 
003F                  00195 UpdateSegments:
003F   0811           00196     movf    Minutes+1,W
0040   2001           00197     call    LookupSegments
0041   0612           00198     xorwf   LED_Segments+0,W
0042   397F           00199     andlw   h'7F'
0043   0692           00200     xorwf   LED_Segments+0,F
0044   0810           00201     movf    Minutes+0,W
0045   2001           00202     call    LookupSegments
0046   0613           00203     xorwf   LED_Segments+1,W
0047   397F           00204     andlw   h'7F'
0048   0693           00205     xorwf   LED_Segments+1,F
0049   080F           00206     movf    Seconds+1,W
004A   2001           00207     call    LookupSegments
004B   0614           00208     xorwf   LED_Segments+2,W
004C   397F           00209     andlw   h'7F'
004D   0694           00210     xorwf   LED_Segments+2,F
004E   080E           00211     movf    Seconds+0,W
004F   2001           00212     call    LookupSegments
0050   0615           00213     xorwf   LED_Segments+3,W
0051   397F           00214     andlw   h'7F'
0052   0695           00215     xorwf   LED_Segments+3,F
0053   0008           00216     return
                      00217 ;
                      00218 ; ==============================================================
                      00219 ; Main application starts here
                      00220 ;
0054                  00221 main:
0054   30D5           00222     movlw   b'11010101'     ; Select TIMER0 clock source as FOSC/4, prescale TMR0 a 1:64
0055   0062           00223     option
                      00224 ;
                      00225 ; Wait for about 800 milliseconds before making PGC/PGD outputs.
                      00226 ;
                      00227 ; This will give the In-Circuit-Serial-Programmer a chance
                      00228 ; to connect to the PIC16F84A
                      00229 ;
0056   3032           00230     movlw   d'50'
0057   008C           00231     movwf   TMR0_Sample
0058   0181           00232     clrf    TMR0
0059   018B           00233     clrf    INTCON
005A                  00234 POR_Wait:
005A   1D0B           00235     btfss   INTCON,TMR0IF
005B   285A           00236     goto    POR_Wait
005C   110B           00237     bcf     INTCON,TMR0IF
005D   0B8C           00238     decfsz  TMR0_Sample,F
005E   285A           00239     goto    POR_Wait
                      00240 
005F   30D4           00241     movlw   b'11010100'     ; Select TIMER0 clock source as FOSC/4, prescale TMR0 at 1:32
0060   0062           00242     option
0061   30F0           00243     movlw   b'11110000'     ; RA3,RA2,RA1,RA0 as outputs
0062   0065           00244     tris    PORTA
0063   3000           00245     movlw   b'00000000'     ; All PORTB as outputs
0064   0066           00246     tris    PORTB
                      00247 ;
                      00248 ; Initialize application states
                      00249 ;
0065   0181           00250     clrf    TMR0
0066   018C           00251     clrf    TMR0_Sample
0067   30FA           00252     movlw   TICKS_PER_SECOND
0068   008D           00253     movwf   TicksInOneSec
0069   0196           00254     clrf    LED_DigitOn
006A   0192           00255     clrf    LED_Segments+0
006B   0193           00256     clrf    LED_Segments+1
006C   0194           00257     clrf    LED_Segments+2
006D   0195           00258     clrf    LED_Segments+3
006E   018E           00259     clrf    Seconds+0           ; Seconds units
006F   018F           00260     clrf    Seconds+1           ; Seconds tens
0070   0190           00261     clrf    Minutes+0           ; Minutes units
0071   3003           00262     movlw   d'3'
0072   0091           00263     movwf   Minutes+1           ; Minutes tens
0073   203F           00264     call    UpdateSegments
                      00265 ;
                      00266 ; ==============================================================
                      00267 ; Application loop
                      00268 ;
                      00269 ;   The application does this:
                      00270 ;       Creates the system tick
                      00271 ;       Counts timer down from 30 minutes
                      00272 ;       Updates the LED digits
                      00273 ;
0074                  00274 AppLoop:
                      00275 ;
                      00276 ; Loop to wait for system tick
0074                  00277 WaitForSystemTick:
0074   080C           00278     movf    TMR0_Sample,W   ; Get previous TIMER0 count state
0075   0201           00279     subwf   TMR0,W          ; Difference of current minus previous sample
0076   3C7D           00280     sublw   TMR0_4_MS
0077   1C03           00281     btfss   STATUS,C        ; Skip if period longer than 0.8 milliseconds
0078   2874           00282     goto    WaitForSystemTick
0079   307D           00283     movlw   TMR0_4_MS
007A   078C           00284     addwf   TMR0_Sample,F   ; Update tick period count
007B                  00285 SystemTickTime:
                      00286 ;
                      00287 ; Do LED task
007B   2014           00288     call    LED_Task
                      00289 ;
                      00290 ; Do Count down task
007C   2027           00291     call    CountDown_Task
007D   2874           00292     goto    AppLoop
                      00293 
                      00294     end