Advertisement
jack96013

StopWatch

Dec 14th, 2020
2,563
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
MPASM 12.33 KB | None | 0 0
  1. ;##############################################
  2. ;Title  : 時鐘 (按鈕控制)
  3. ;Description : S1 開始 S2 暫停 S3 清除 S4 繼續
  4. ;Author : TZU-CHIEG ,HSU
  5. ;##############################################
  6. list p=16F877A
  7. #include <p16f877A.inc> ; Include file locate at defult directory
  8. ; CONFIG
  9. ; __config 0xFF7A
  10.  __CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CP_OFF
  11.  
  12. ;
  13. VAL_US equ .40 ; 1ms delay valum
  14. VAL_MS equ .100
  15. count equ 0x20 ; Defined temp reg. for 1ms delay
  16. count_ms equ 0x21            ; Defined delay reg.
  17.  
  18. VAL_500u equ .80 ; 1ms delay valum
  19. count_500u equ 0x37 ; Defined temp reg. for 1ms delay
  20.  
  21. ADDR_POLL equ 0x25 ;掃描顯示
  22.  
  23. ADDR_DISP equ 0x26 ;轉 7 Segment
  24.  
  25. ADDR_SOU equ 0x27 ;轉BCD (個位)
  26. ADDR_TEN equ 0x28 ;轉BCD 十位
  27.  
  28. ADDR_CLOCK_EN equ 0x40
  29. ADDR_CLOCK_DIV_1 equ 0x29;
  30. VAL_CLOCK_DIV_1 equ .121     ;83*3=249 125*2=250
  31. ADDR_CLOCK_DIV_2 equ 0x30
  32. VAL_CLOCK_DIV_2 equ .8
  33. ADDR_CLOCK_SEC equ 0x22  ;秒
  34. ADDR_CLOCK_MIN equ 0x23  ;分
  35. ADDR_CLOCK_HUR equ 0x24  ;小時
  36.  
  37. ADDR_SEG_DIG0 equ 0x31 ;第一位顯示
  38. ADDR_SEG_DIG1 equ 0x32 ;第二位顯示
  39. ADDR_SEG_DIG2 equ 0x33 ;第三位顯示
  40. ADDR_SEG_DIG3 equ 0x34 ;第四位顯示
  41. ADDR_SEG_DIG4 equ 0x35 ;第五位顯示
  42. ADDR_SEG_DIG5 equ 0x36 ;第六位顯示
  43. ADDR_SEG_DIG6 equ 0x37 ;第七位顯示
  44. ADDR_SEG_DIG7 equ 0x38 ;第八位顯示
  45.  
  46.  
  47. ;### 按鈕處理 ###
  48. ADDR_BUTTON_SCAN_DIV equ 0x39 ;按鈕掃描週期
  49. NUM_BUTTON_SCAN_DIV equ .20 ;按鈕掃描週期
  50.  
  51. ADDR_BUTTON_STATUS equ 0x3A ;按鈕狀態(輸入/出)
  52. ADDR_BUTTON_COUNT equ 0x3B ;按住計數
  53. ADDR_BUTTON_S1_PRESSED_COUNT equ 0x50
  54. ADDR_BUTTON_S2_PRESSED_COUNT equ 0x51
  55. ADDR_BUTTON_S3_PRESSED_COUNT equ 0x52
  56. ADDR_BUTTON_S4_PRESSED_COUNT equ 0x53
  57. VAL_BUTTON_SHORT_PRESSED equ .25
  58. VAL_BUTTON_LONG_PRESSED equ .25
  59. ;##################
  60. ;### 指示燈 ###
  61. ADDR_RUNNING_DIV equ 0x41
  62. VAL_RUNNING_DIV equ .166
  63.  
  64.  ;
  65. ;***************************************
  66. ;           Program start              *
  67. ;***************************************
  68. org 0x00 ; reset vector
  69. nop ; Reserve for MPLAB-ICD
  70. Initial:
  71.     ;Port Configure
  72.     clrw ; W =0
  73.     clrf PCLATH
  74.     banksel TRISA ; Select to bank1
  75.     movlw 0x06
  76.     movwf ADCON1
  77.     clrf TRISA
  78.     clrf TRISD
  79.     clrf TRISE;TEST
  80.     movlw b'11111111'
  81.     movwf TRISB
  82.    
  83.     banksel PORTA
  84.     bsf PORTE,0
  85.     bsf PORTE,1
  86.     movlw .0
  87.     movwf ADDR_POLL
  88.    
  89.     clrf ADDR_CLOCK_SEC
  90.     clrf ADDR_CLOCK_MIN
  91.     clrf ADDR_CLOCK_HUR
  92.  
  93.     ;clrf PORTD
  94.     movlw VAL_CLOCK_DIV_1
  95.     movwf ADDR_CLOCK_DIV_1 ;
  96.     movlw VAL_CLOCK_DIV_2
  97.     movwf ADDR_CLOCK_DIV_2
  98.  
  99.     movlw NUM_BUTTON_SCAN_DIV
  100.     movwf ADDR_BUTTON_SCAN_DIV
  101.    
  102.     clrf ADDR_CLOCK_EN
  103.     bsf ADDR_CLOCK_EN,1 ;第一次執行
  104.     bcf ADDR_CLOCK_EN,0
  105.  
  106.     movlw VAL_RUNNING_DIV
  107.     movwf ADDR_RUNNING_DIV
  108.    
  109.     movlw b'10111111'
  110.     ;movwf ADDR_DISP
  111.     ;call bcd_to_segment
  112.     ;movf ADDR_DISP,0
  113.     movwf ADDR_SEG_DIG0
  114.     movwf ADDR_SEG_DIG1
  115.     movwf ADDR_SEG_DIG2
  116.     movwf ADDR_SEG_DIG3
  117.     movwf ADDR_SEG_DIG4
  118.     movwf ADDR_SEG_DIG5
  119.     ;movlw b'10110011'
  120.     movwf ADDR_SEG_DIG6
  121.     movwf ADDR_SEG_DIG7
  122.     movwf ADDR_SEG_DIG5
  123.     movwf ADDR_SEG_DIG4
  124.     movwf ADDR_SEG_DIG3
  125.     movwf ADDR_SEG_DIG2
  126.  
  127.  
  128. ;
  129. ;************ Main *********************
  130. ;
  131. start:
  132.     ;call test
  133.     call task_button ;按鈕工作
  134.     call task_clock ;計數工作
  135.     call task_running_indcator
  136.     call digi_polling ;掃描顯示工作
  137.  
  138.     call delay_1ms ; Call delay routine
  139.     goto start
  140.  
  141.    
  142. task_clock: ;達目標次數(1秒),計數一次
  143.     btfss ADDR_CLOCK_EN,0
  144.         return
  145.     decfsz ADDR_CLOCK_DIV_1,f
  146.         return
  147.     movlw VAL_CLOCK_DIV_1
  148.     movwf ADDR_CLOCK_DIV_1
  149.  
  150.     decfsz ADDR_CLOCK_DIV_2,f
  151.         return
  152.     movlw VAL_CLOCK_DIV_2
  153.     movwf ADDR_CLOCK_DIV_2
  154.     call clock
  155.     return
  156.    
  157. ;test:
  158. ;    btfss PORTE,0
  159. ;   goto on
  160. ;    goto off
  161. ;    on:
  162. ;   bsf PORTE,0
  163. ;   return
  164. ;    off:
  165. ;   bcf PORTE,0
  166. ;   return
  167.  
  168. digi_clear:
  169.     movlw .0
  170.     movwf ADDR_DISP
  171.     call bcd_to_segment
  172.     movwf ADDR_SEG_DIG0
  173.     movwf ADDR_SEG_DIG1
  174.     movwf ADDR_SEG_DIG2
  175.     bcf ADDR_SEG_DIG2,7
  176.     movwf ADDR_SEG_DIG3
  177.     movwf ADDR_SEG_DIG4
  178.     bcf ADDR_SEG_DIG4,7
  179.     movwf ADDR_SEG_DIG5
  180.     return
  181.  
  182. clock: ;時鐘
  183.     ;call test
  184.     ;=====SEC======
  185.     incf ADDR_CLOCK_SEC,1
  186.    
  187.     movlw .60
  188.     subwf ADDR_CLOCK_SEC,0
  189.     btfss STATUS,2
  190.     goto clock_sec_fin
  191.     clrf ADDR_CLOCK_SEC
  192.     call clock_sec_fin
  193.     ;=====MIN======
  194.     min:
  195.     incf ADDR_CLOCK_MIN,1
  196.     movlw .60
  197.     subwf ADDR_CLOCK_MIN,0
  198.     btfss STATUS,2
  199.     goto clock_min_fin
  200.     clrf ADDR_CLOCK_MIN
  201.     call clock_min_fin
  202.     ;=====HOUR======
  203.     hour:
  204.     incf ADDR_CLOCK_HUR,1
  205.     movlw .24
  206.     subwf ADDR_CLOCK_HUR,0
  207.     btfss STATUS,2
  208.     goto clock_hour_fin
  209.     clrf ADDR_CLOCK_HUR
  210.     call clock_hour_fin
  211.     return
  212.     clock_sec_fin:
  213.     movf ADDR_CLOCK_SEC,0
  214.  
  215.     call val_to_segment
  216.     movf ADDR_SOU,0
  217.     movwf ADDR_SEG_DIG0
  218.     movf ADDR_TEN,0
  219.     movwf ADDR_SEG_DIG1
  220.     return
  221.     clock_min_fin:
  222.     movf ADDR_CLOCK_MIN,0
  223.  
  224.     call val_to_segment
  225.     movf ADDR_SOU,0
  226.     movwf ADDR_SEG_DIG2
  227.     bcf ADDR_SEG_DIG2,7
  228.     movf ADDR_TEN,0
  229.     movwf ADDR_SEG_DIG3
  230.     return
  231.     clock_hour_fin:
  232.     movf ADDR_CLOCK_HUR,0
  233.    
  234.     call val_to_segment
  235.     movf ADDR_SOU,0
  236.     movwf ADDR_SEG_DIG4
  237.     bcf ADDR_SEG_DIG4,7
  238.     movf ADDR_TEN,0
  239.     movwf ADDR_SEG_DIG5
  240.     return
  241.    
  242. val_to_segment: ;原值轉 7 段顯示碼
  243.     movwf ADDR_SOU
  244.     call BCD
  245.    
  246.     movf ADDR_SOU,0 ;個位轉SEG
  247.     movwf ADDR_DISP
  248.     call bcd_to_segment
  249.     movwf ADDR_SOU
  250.    
  251.     movf ADDR_TEN,0 ;十位轉SEG
  252.     movwf ADDR_DISP
  253.     call bcd_to_segment
  254.     movwf ADDR_TEN
  255.     return
  256.  
  257. digi_polling: ;掃描顯示
  258.     ;Polling the digits pin
  259.     incf ADDR_POLL
  260.     btfss ADDR_POLL,3
  261.     goto digi_polling_fin
  262.     clrf ADDR_POLL
  263.    
  264.     digi_polling_fin:
  265.     movlw b'00111111'
  266.     movwf PORTA
  267.     movlw b'00000011'
  268.     movwf PORTE
  269.    
  270.     movf ADDR_POLL,0
  271.     addwf ADDR_POLL,0
  272.     addwf ADDR_POLL,0
  273.    
  274.     addwf PCL
  275.  
  276.     movf ADDR_SEG_DIG7,0
  277.     bcf PORTA,0
  278.     goto seg_out
  279.  
  280.     movf ADDR_SEG_DIG6,0
  281.     bcf PORTA,1
  282.     goto seg_out
  283.  
  284.     movf ADDR_SEG_DIG5,0
  285.     bcf PORTA,2
  286.     goto seg_out
  287.  
  288.     movf ADDR_SEG_DIG4,0
  289.     bcf PORTA,3
  290.     goto seg_out
  291.  
  292.     movf ADDR_SEG_DIG3,0
  293.     bcf PORTA,4
  294.     goto seg_out
  295.  
  296.     movf ADDR_SEG_DIG2,0
  297.     bcf PORTA,5
  298.     goto seg_out
  299.  
  300.     movf ADDR_SEG_DIG1,0
  301.     bcf PORTE,0
  302.     goto seg_out
  303.    
  304.     movf ADDR_SEG_DIG0,0
  305.     bcf PORTE,1
  306.     goto seg_out
  307.    
  308.     seg_out:
  309.     movwf PORTD
  310.    
  311.     return
  312.    
  313. bcd_to_segment: ;BCD 轉 7 段碼
  314.     ;Edge Check
  315.     movlw ADDR_DISP
  316.     sublw .9
  317.     btfsc STATUS,0
  318.     return
  319.     movf ADDR_DISP,0
  320.     addwf PCL
  321.     retlw b'11000000' ;0
  322.     retlw b'11111001' ;1
  323.     retlw b'10100100' ;2
  324.     retlw b'10110000' ;3
  325.     retlw b'10011001' ;4
  326.     retlw b'10010010' ;5
  327.     retlw b'10000010' ;6
  328.     retlw b'11111000' ;7
  329.     retlw b'10000000' ;8
  330.     retlw b'10010000' ;9
  331.    
  332. BCD: ;轉 BCD 碼
  333.     clrf ADDR_TEN
  334.     BCD_TEN:
  335.     movlw .10
  336.     subwf ADDR_SOU,0
  337.     btfss STATUS,0
  338.     return
  339.     movwf ADDR_SOU
  340.     incf ADDR_TEN,1
  341.     goto BCD_TEN
  342.    
  343. task_running_indcator:
  344.     decfsz ADDR_RUNNING_DIV
  345.     return
  346.     movlw VAL_RUNNING_DIV
  347.     movwf ADDR_RUNNING_DIV
  348.     btfss ADDR_CLOCK_EN,0
  349.     return
  350.     comf ADDR_SEG_DIG7,0
  351.     btfsc STATUS,Z
  352.     bcf ADDR_SEG_DIG7,0
  353.     btfsc ADDR_SEG_DIG7,5
  354.     goto rr_1
  355.     movlw b'11111111'
  356.     movwf ADDR_SEG_DIG7
  357.     bcf ADDR_SEG_DIG7,0
  358.     return
  359.     rr_1:
  360.     bsf STATUS,C
  361.     rlf ADDR_SEG_DIG7
  362.     return
  363.    
  364. task_button:
  365.     decfsz ADDR_BUTTON_SCAN_DIV,f
  366.         return
  367.     movlw NUM_BUTTON_SCAN_DIV
  368.     movwf ADDR_BUTTON_SCAN_DIV
  369.     button_s1:
  370.         movlw b'00000001'
  371.         andwf PORTB,W
  372.         movwf ADDR_BUTTON_STATUS
  373.         movf ADDR_BUTTON_S1_PRESSED_COUNT,W
  374.         movwf ADDR_BUTTON_COUNT
  375.         call button_general
  376.    
  377.         movwf ADDR_BUTTON_S1_PRESSED_COUNT
  378.         btfss ADDR_BUTTON_STATUS,3 ;長按檢測
  379.            goto button_s1_fin
  380.         ;### EXECUTE ###
  381.         btfss ADDR_CLOCK_EN,1
  382.             goto Initial
  383.         bcf ADDR_CLOCK_EN,1
  384.         bsf ADDR_CLOCK_EN,0
  385.         call digi_clear
  386.         ;##### END #####
  387.     button_s1_fin:
  388.     btfsc ADDR_CLOCK_EN,1
  389.         goto button_fin
  390.     button_s2:
  391.         movlw b'00000010'
  392.         andwf PORTB,W
  393.         movwf ADDR_BUTTON_STATUS
  394.         movf ADDR_BUTTON_S2_PRESSED_COUNT,W
  395.         movwf ADDR_BUTTON_COUNT
  396.         call button_general
  397.  
  398.         movwf ADDR_BUTTON_S2_PRESSED_COUNT
  399.         btfss ADDR_BUTTON_STATUS,2 ;短按檢測
  400.             goto button_s3
  401.         ;### EXECUTE ###
  402.         bcf ADDR_CLOCK_EN,0
  403.         ;##### END #####
  404.     button_s3:
  405.         movlw b'00000100'
  406.         andwf PORTB,W
  407.         movwf ADDR_BUTTON_STATUS
  408.         movf ADDR_BUTTON_S3_PRESSED_COUNT,W
  409.         movwf ADDR_BUTTON_COUNT
  410.         call button_general
  411.    
  412.         movwf ADDR_BUTTON_S3_PRESSED_COUNT
  413.         btfss ADDR_BUTTON_STATUS,2 ;短按檢測
  414.             goto button_s4
  415.         ;### EXECUTE ###
  416.         call digi_clear
  417.         bcf ADDR_CLOCK_EN,0
  418.         clrf ADDR_CLOCK_SEC
  419.         clrf ADDR_CLOCK_MIN
  420.         clrf ADDR_CLOCK_HUR
  421.         ;##### END #####
  422.     button_s4:
  423.         movlw b'00001000'
  424.         andwf PORTB,W
  425.         movwf ADDR_BUTTON_STATUS
  426.         movf ADDR_BUTTON_S4_PRESSED_COUNT,W
  427.         movwf ADDR_BUTTON_COUNT
  428.         call button_general
  429.    
  430.         movwf ADDR_BUTTON_S4_PRESSED_COUNT
  431.         btfss ADDR_BUTTON_STATUS,2 ;短按檢測
  432.             goto button_fin
  433.         ;### EXECUTE ###
  434.         btfsc ADDR_CLOCK_EN,0
  435.             goto button_fin
  436.         bsf ADDR_CLOCK_EN,0
  437.         movlw VAL_CLOCK_DIV_1
  438.         movwf ADDR_CLOCK_DIV_1
  439.  
  440.         movlw VAL_CLOCK_DIV_2
  441.         movwf ADDR_CLOCK_DIV_2
  442.         ;##### END #####    
  443.     button_fin:
  444.         return
  445.  
  446. ;用法port & mask 後帶入 ADDR_BUTTON_STATUS,按住計數器帶入ADDR_BUTTON_COUNT
  447. ;結束後 ADDR_BUTTON_STATUS ,W為COUNT
  448. ;...<3> <2> <1> <0>
  449. ;    0   0   0   1 ;為鬆開狀態
  450. ;    0   0   1   0 ;為按住狀態
  451. ;    0   1   0   0 ;為短按
  452. ;    1   0   0   0 ;為長按
  453. button_general:
  454.     movf ADDR_BUTTON_STATUS,w
  455.     btfss STATUS,Z
  456.         goto button_off
  457.     button_on:
  458.     clrf ADDR_BUTTON_STATUS
  459.         bsf ADDR_BUTTON_STATUS,1 ;表示按住
  460.         comf ADDR_BUTTON_COUNT,w ;溢位檢查
  461.         btfsc STATUS,Z
  462.             goto button_general_finish
  463.         incf ADDR_BUTTON_COUNT
  464.         movlw VAL_BUTTON_LONG_PRESSED
  465.         subwf ADDR_BUTTON_COUNT,w
  466.         btfss STATUS,C
  467.             goto button_general_finish
  468.         ;差值 > 0 表示長按,利用移入255達到死鎖
  469.         movlw .255
  470.         movwf ADDR_BUTTON_COUNT
  471.         ;### Long Pressed ###
  472.         bsf ADDR_BUTTON_STATUS,3 ;表長按
  473.         bcf ADDR_BUTTON_STATUS,1 ;
  474.         ;####################
  475.         goto button_general_finish
  476.     button_off:
  477.     clrf ADDR_BUTTON_STATUS
  478.         bsf ADDR_BUTTON_STATUS,0 ;表示鬆開
  479.         movf ADDR_BUTTON_COUNT,w
  480.         btfsc STATUS,Z
  481.         goto button_general_finish
  482.         ;Non Zero means the button has been pressed
  483.         movlw VAL_BUTTON_SHORT_PRESSED
  484.         subwf ADDR_BUTTON_COUNT,w
  485.         clrf ADDR_BUTTON_COUNT
  486.         btfsc STATUS,C
  487.             goto button_general_finish
  488.         ;### Long Pressed ###
  489.         bsf ADDR_BUTTON_STATUS,2 ;表短按
  490.         bcf ADDR_BUTTON_STATUS,1
  491.         ;####################
  492.         goto button_general_finish
  493.         ;===== End ======
  494.     button_general_finish:
  495.     movf ADDR_BUTTON_COUNT,w
  496.        return
  497.  
  498.  
  499. ;-------- 100 ms delay routine ----------
  500. delay_100ms:
  501. movlw VAL_MS
  502. movwf count_ms
  503.     loop_ms
  504.     call delay_1ms
  505.     decfsz count_ms,f
  506.     goto loop_ms
  507.     return
  508.    
  509. ;-------- 1 ms delay routine -----------
  510. delay_500us:
  511.     movlw VAL_500u
  512.     movwf count_500u
  513.     dec_loop_500u
  514.     call D_short
  515.     decfsz count_500u,f
  516.     goto dec_loop_500u
  517.     return
  518.    
  519. ;-------- 1 ms delay routine -----------
  520. delay_1ms:
  521.     movlw VAL_US
  522.     movwf count
  523.     dec_loop
  524.     call D_short
  525.     decfsz count,f
  526.     goto dec_loop
  527.     return
  528. ;
  529. ;--------     Delay 5uS    ------------- 25ms
  530. D_short
  531.     call D_ret ; 1uS * 4 + 1uS = 10uS
  532.     call D_ret
  533.     call D_ret
  534.     call D_ret
  535.     nop
  536.     nop
  537.     D_ret return
  538. ;
  539. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement