winnie 发表于 2009-3-7 22:20:44

一个16F877实现计时秒表功能

一个16F877实现计时秒表功能
简介:

该源程序已在实验板上调试通过,读者可直接引用,并可以利用软件编程的灵活性,加以拓展,实现更为复杂的功能。
;****************************************
;*   一个16F877实现计时秒表功能         *
;****************************************

;16F877秒表源程序,带注解
;该源程序已在实验板上调试通过,读者可直接引用,并可以利用软件编程的灵活性,加以拓展,实现更为复杂的功能。
LIST         P=16F877
      INCLUDE      "P16F877,INC"
;************此程序实现计时秒表功能******************
;时钟显示范围:00.00秒-99.99秒,分辨度:0.01秒;所用的寄存器如下
S0         EQU      0X20         ;0.01 秒计时器
S1         EQU      S0+1         ;0.1 秒计时器
S2         EQU      S0+2         ;1 秒计时器
S3         EQU      S0+3         ;10秒计时器
SREG      EQU      S0+4         ;软计数器
LEDF      EQU      S0+5         ;显示的LED的位置指示寄存器
XW_TEMP   EQU      S0+6         ;用于中断中保护W的值
XHOSTS      EQU      S0+7         ;用于中断中保护STATUS的值
DEYH      EQU      S0+8
DEYL      EQU      S0+9         ;以上两个寄存器用于软件延时
HOSTF      EQU      S0+0A      ;用于中断中保护FSR的值
   ORG         0X00
   GOTO      MAIN
   ORG         0X04
   GOTO      CLKINT            ;转向中断服务程序
   ORG         0X10
;****************************************
;数字到段码的转换子程序(最好放在程序开头,避免超过2 KB的空间发生跨页读表)
CONVERT                           ;不带小数点的共阳极码表   
……                        ;详细的程序语句见A/D应用章节的程序清单
CONVERT2                        ;带小数点的共阳极码表
……                        ;详细的程序语句见A/D应用章节的程序清单
TRANSMIT                         ;SPI发送显示子模块
   CLRF      PORTA            ;LACK送低电平,为锁存做准备
   MOVWF      SSPBUF             ;启动发送   
WAIT   BANKSEL      PIR1
   BTFSS      PIR1,SSPIF
   GOTO      WAIT            ;等待发送结束
   BCF         PIR1,SSPIF      ;清除中断标志
   NOP
   RETURN
;***********显示子程序模块************
DISPLAY   MOVLW      0X01
   MOVWF      LEDF
   MOVLW      0XA0
   MOVWF      FSR
AGAINXIAN   MOVF   LEDF,W
   SUBLW      0X02
   BTFSS      STATUS,Z
   GOTO      XIANB
   MOVF      INDF,W
   CALL      CONVERT2         ;若是第二位,则查带小数点的码表
   GOTO      TRAN
XIANB   MOVF      INDF,W
   CALL      CONVERT
TRAN   CALL      TRANSMIT         ;发送一个显示数据
   INCF         FSR
   INCF         LEDF
   MOVF      LEDF,W
   SUBLW      0X05
   BTFSS      STATUS,Z
   GOTO      AGAINXIAN
   MOVLW      0X01
   MOVWF      LEDF
XIANDARK   MOVLW   0X13
   CALL      CONVERT
   CALL      TRANSMIT
   INCF         LEDF
   MOVF      LEDF,W
   SUBLW      0X05
   BTFSS      STATUS,Z
   GOTO      XIANDARK         ;显示4个"DARK"
   BSF         PORTA,5            ;最后给一个锁存信号,代表一次显示任务完成
   RETURN
;********** S0计数溢出处理子程序***************
CS0      CLRF      S0
   INCF         S1
   RETURN
;********** S1计数溢出处理子程序***************
CS1      CLRF      S1
      INCF         S2
      RETURN
;********** S2计数溢出处理子程序***************
CS2      CLRF      S2
      INCF         S3
      RETURN
;********** S3计数溢出处理子程序***************
CS3      CLRF      S3
      RETURN
;***********时钟中断服务程序*******************
CLKINT   MOVWF      XW_TEMP            ;保存W的值
   SWAPF      STATUS,W
   MOVWF      XHOSTS            ;暂存STATUS的值
   MOVF      FSR,W
   MOVWF      HOSTF            ;保存FSR的值。以上程序为中断现场保护
   MOVLW      0X14
   MOVWF      TMR0            ;对TMR0写入一个调整值,因为写入
;TMR0后接着的两个周期不能增量
   BCF         INTCON,T0IF         ;清除中断标志
   INCF         SREG
   MOVF      SREG,W
   SUBLW      0X28               ;TMR0 每250 μs中断一次
   BTFSS      STATUS,Z         ;其中断40次后才执行对S0、 S1、 S2、 S3 的
                      ;操作
   GOTO      TIFAN
   CLRF      SREG
   INCF         S0
   MOVF      S0,W
   SUBLW      0X0A
   BTFSC      STATUS,Z
   CALL      CS0   
   MOVF      S1,W
   SUBLW      0X0A
   BTFSC      STATUS,Z
   CALL      CS1
   MOVF      S2,W
   SUBLW      0X0A
   BTFSC      STATUS,Z
   CALL      CS2
   MOVF      S3,W
   SUBLW      0X0A
   BTFSC      STATUS,Z
   CALL      CS3
TIFAN   MOVF      HOSTF,W         ;以下为中断现场恢复
   MOVWF      FSR               ;恢复间接寻址指针FSR的值
   SWAPF      XHOSTS,W
   MOVWF      STATUS            ;恢复STATUS的值
   SWAPF      XW_TEMP,1
   SWAPF      XW_TEMP,W         ;恢复W的值
   RETFIE   
;*********** TMR0初始化子程序***************
CLKINSUB   BANKSEL      OPTION_REG
   BCF         OPTION_REG,T0CS       ;TMR0工作于定时器方式
   BSF         OPTION_REG,PSA      ;TMR0不用分频
   BANKSEL      INTCON
   BCF         INTCON,T0IF         ;清除TMR0的中断标志
   BCF         INTCON,GIE         ;总中断禁止
   BSF         INTCON,T0IE         ;TMR0中断允许
   RETURN
;***************系统初始化子程序*****************
MAINSUB      BANKSEL      TRISA
   BCF         TRISA,5         ;置RA5为输出方式,以输出锁存信号
   BCF         TRISB,1
   BCF         TRISB,2
   BSF         TRISB,4
   BSF         TRISB,5            ;设置与键盘有关的各口的输入输出方式
   BCF         TRISC,5
   BCF         TRISC,3            ;设置SCK与SDO为输出方式
   BCF         INTCON,GIE          ;关闭所有中断
   MOVLW      0XC0
   MOVWF      SSPSTAT         ;设置SSPSTAT寄存器
   BANKSEL      SSPCON
   MOVLW      0X30
MOVWF      SSPCON            ;设置SPI的控制方式,允许SSP方式,
;并且时钟下降沿发送,与“74HC595,当
;其SCLK从低到高电平跳变时,串行输入数据
;(DI)移入寄存器”的特点相对应
   BCF         STATUS,IRP         ;间接寻址选中BANK0、BANK1
RETURN                   ;返回   
;***********键扫描子程序********************
KEYSCAN      CLRF   PORTB      ;B1和B2两条线上送0
   NOP         
NOP                  ;经过一段时间的延时,避开引脚电平的过渡过程
   MOVF      PORTB,W
   ANDLW      0X30         ;只检查B4和B5两位,屏蔽其它各位
   SUBLW      0X30
   RETURN      
;****************************************
KEYDELAY                        ;键盘去抖子程序(约8ms的软件延时)
……                        ;详细的程序语句请参考相关章节
   RETURN   
;*************显示缓冲区处理子程序****************
XIANHUAN   MOVLW      0XA0
   MOVWF      FSR
   MOVF      S3,W
   MOVWF      INDF
   INCF         FSR
   MOVF      S2,W
   MOVWF      INDF
   INCF         FSR
   MOVF      S1,W
   MOVWF      INDF
   INCF         FSR
   MOVF      S0,W
   MOVWF      INDF
   RETURN
;****************************************
MAIN      NOP
      CALL      MAINSUB            ;系统初始化
      CALL      CLKINSUB         ;调用时钟初始化子程序
DENJIAN   BCF         INTCON,GIE
   BANKSEL      S0
   CLRF      S0
   CLRF      S1
   CLRF      S2
   CLRF      S3
   CLRF      SREG
   CLRF      LEDF            ;S0=S1=S2=S3=0
   CALL      XIANHUAN         ;把S3、S2、S1、S0的值装入显示缓冲区
      CALL      DISPLAY            ;显示
DENAN      BCF      INTCON,GIE         ;关中断
   CALL      KEYSCAN            ;进行键扫描
   BTFSS      STATUS,Z
   GOTO      XIAODOU1         ;如起始键按下,则消抖动
   GOTO      DENAN            ;如起始键没按下,则继续等待
XIAODOU1   CALL   KEYDELAY         ;延时消抖动
   CALL      KEYSCAN            ;再次进行键扫描
   BTFSC      STATUS,Z
   GOTO      DENAN            ;若为干扰,则再次等待键按下
   BANKSEL      S0
   CLRF      S0
   CLRF      S1
   CLRF      S2
   CLRF      S3
      CLRF      SREG            ;设置新一次计时的初始条件      
WAITS   CALL      KEYSCAN      
   BTFSS      STATUS,Z
   GOTO      WAITS            ;为了防止按键过于灵敏,等键松开后再进行
;下面的操作   
   MOVLW      0X08
   MOVWF      TMR0
   BSF         INTCON,GIE         ;开总中断
HERE   CALL      XIANHUAN         ;显示缓冲区处理   
   CALL      DISPLAY            ;即时更新显示内容
   CALL      KEYSCAN   
   BTFSS      STATUS,Z
   GOTO      XIAODOU            ;若停止计时键按下,则消抖
   GOTO      HERE            ;若停止计时键没按下,则继续等待中断计时
XIAODOU      CALL   DISPLAY            ;利用消抖动时间调用显示程序
   CALL      DISPLAY   
   CALL      DISPLAY   
   CALL      DISPLAY
   CALL      DISPLAY
   CALL      DISPLAY   
   CALL      DISPLAY   
   CALL      DISPLAY   
   CALL      DISPLAY
   CALL      KEYSCAN
   BTFSC      STATUS,Z
   GOTO      HERE            ;若为干扰,则继续等待停止键按下      
   BCF         INTCON,GIE         ;若停止键按下,则禁止中断
      CALL      DISPLAY            ;若不为干扰,则禁止中断,更新显示内容   
WAITR   CALL      KEYSCAN      
      BTFSS      STATUS,Z
      GOTO      WAITR            ;为了防止按键过于灵敏,等键松开后再进行
;下面的操作      
DENDAI   CALL      KEYSCAN
   BTFSC      STATUS,Z
   GOTO      DENDAI            ;循环进行键扫描,等待清0键按下
   CALL      KEYDELAY
   CALL      KEYSCAN
   BTFSC      STATUS,Z
   GOTO      DENDAI            ;延时消抖
WAIT19   CALL      KEYSCAN
   BTFSS      STATUS,Z
   GOTO      WAIT19            ;等键松开   
   GOTO      DENJIAN            ;新一次计时开始
   END





一个16F877应用的典型程序结构
;****************************************
;*   一个16F877应用的典型程序结构       *
;****************************************
;***************程序说明区*******************
   LIST   p=16f877   ;指定微控制器型号和文件输出格式
   INCLUDE   p16f877.inc   ;读入MPLAB提供的定义文件P16F877.INC
;***片内RAM常用资源、变量定义和相应的说明*********
   ACCALO   EQU 20   ;存放加数或减数低8位
   ACCAHI    EQU 21   ;存放加数或减数高8位
   ACCBLO    EQU    23   ;存放被加数或被减数低8位
   ACCBHI    EQU    24   ;存放被加数或被减数高8位
   S_W   EQU    25   ;栈存W寄存器值
   S_STATUS   EQU   26   ;栈存STATUS寄存器值
;****************芯片复位矢量*******************
   ORG   0X0000   ;由于PIC16F877芯片复位矢量在0000h单
      ;元,所以常在0000h单元处放置一条跳转
      ;指令,使单片机复位后能跳过中断矢量,
               ;直接执行主程序
START   GOTO      MAIN      
;******************中断矢量**********************
   ORG   0X0004   ;由于PIC16F877的中断矢量为0004h,所以
      ;当中断开放时, 需在此处加入中断程序,
      ;使单片机能在中断到来时及时进入相应的
      ;中断服务程序。为了可靠起见,如果单片
      ;机不使用中断,则常常在该中断矢量处放
      ;置RETFIE指令,可以使单片机不会因
      ;干扰产生误中断而导致程序跑飞
   CALL   PUSH   ;调用保护现场子程序
   BTFSS   PIR1,ADIF
   CALL   AD   ;若AD中断到,则执行中断服务程序
   ……..      ;此处可放多个中断子程序,并以软件安排
         ;中断优先级
   CALL   POP   ;恢复中断现场
   RETFIE   ;中断返回
;****************主程序区*****************
   ORG   0X0100   ;将主程序、子程序和中断服务程序等存放
      ;在0100h单元之后,在中断矢量和主程序
      ;区之间预留一些存储单元,以便写入判
      ;跳指令和一些必要的现场保护程序。此外
      ;用户也可以根据实际需要,使主程序从其
      ;它地址开始存放
MAIN   BSF   STATUS,RP0   ;选择存储体1
   MOVLW   0XFF   ;定义RA口为输入端口
   MOVWF   TRISA
   BCF   STATUS,RP0   ;选择存储体0
   MOVLW   0X04   ;初值化ACCALO
   MOVWF   ACCALO   
   CALL   DX   ;调用DX子程序
LOOP1   ……   ;任务1
   ……   ;任务2
   :
   :
   :
   GOTO   LOOP1   ;反复执行任务一和任务二等
;***************子程序区*********************
DX   MOVF    ACCALO,0   ;ACCB和ACCA低半字节相加
   ADDWF    ACCBLO
   RETURN      ;子程序返回
;****************************************
PUSH   MOVWF   S_W   ;保护W寄存器
   MOVF   STATUS,0   ;保护STATUS寄存器
   MOVWF   S_STATUS
   RETURN      ;子程序返回
;****************************************
POP   MOVF    S_STATUS,0   ;恢复STATUS寄存器
   MOVWF   STATUS
   MOVF   S_W,0   ;恢复W寄存器
   RETURN   ;子程序返回
;****************中断服务子程序区************************
AD      BCF         PIR1,ADIF   ;清AD中断标志
   ……                  ;中断服务主体程序
   RETURN               ;子程序返回
       END
页: [1]
查看完整版本: 一个16F877实现计时秒表功能