📄 sample.asm.bak
字号:
;OSC 20MHZ
;CX1-V1.SCH\PCB
;PIC16F877A
;050729程序框架示例
;050802输入口去抖后存入keyh\keyl
;050919modbus通信协议的CRC16校验
include <p16F877A.inc>;标准头文件,这样所有的特殊寄存器都定义好了
__config (_LVP_OFF&_BODEN_ON&_PWRTE_ON&_WDT_ON&_HS_OSC);烧写设置,可参考伪指令手册
;低电压烧写关、掉电保护、上电延时、看门狗、高速晶振
;*******************************BANK0
status_temp equ 20H ;中断 status暂存
PCLATH_TMP equ 21H ;中断 PCLATH暂存
FSR_TMP equ 22H ;中断 FSR暂存
flag equ 23H ;中断 标记寄存器
t10ms equ 24H ;中断 10ms发生寄存器 20000000/4/256=195
t1ms EQU 26H ;输入口扫描1MS
timeout equ 28H ;超时倒计时
sec equ 29h ;时基秒发生寄存器
keyh EQU 40H ;输入口扫描
key_ah EQU 41H
key_bh EQU 42H
keyl EQU 43H
key_al EQU 44H
key_bl EQU 45H
key_tim EQU 46H ;延时计数
key_set EQU 47H ;延时设定0-255MS
Crc00 EQU 60H
Crc0 EQU 61H
Crc1 EQU 62H
Crc2 EQU 63H
Crc3 EQU 64H
Crc4 EQU 65H
Crc5 EQU 66H
Crc6 EQU 67H ;|
CrcL EQU 67H ;|
Crc7 EQU 68H ; |
CrcH EQU 68H ; |
Crc8 EQU 69H ;
Crc9 EQU 6AH ;
Crc10 EQU 6BH ;
Crc11 EQU 6CH ;
Crc12 EQU 6DH ;
CrcL1 EQU 6EH
CrcH1 EQU 6FH
;*******************************BANK0\1\2\3共用
; EQU 70h ;ICD2仿真占用
w_temp EQU 71h ;w暂存
tempy EQU 78h
;*******************************BANK1
;*******************************BANK2
;*******************************BANK3
; EQU 1E5H ;ICD2仿真占用
; EQU 1EFh ;ICD2仿真占用
;flag ;标记寄存器每位的定义
time1_f equ 0 ;=1 10ms到
; EQU 1
; equ 2
; equ 4
; equ 5
; equ 6
; equ 7
; equ 8
;*********************************************************************************
org 0
nop ;ICD2仿真占用
goto start
org 0x04
service ;中断入口
movwf w_temp ;保护W\STATUS\PCLATH\FSR,和你认为要保护的寄存器
swapf STATUS,W
clrf STATUS ;Bank0
movwf status_temp
MOVFW PCLATH
MOVWF PCLATH_TMP
MOVFW FSR
MOVWF FSR_TMP
BCF PCLATH,3 ;in column 0
BCF PCLATH,4 ;in column 0
service_time0
BTFSS INTCON,T0IF ;T0IF=1 是TIMER0中断?
goto service_r ;N
bcf INTCON,T0IF ;Y CLR int flag
decfsz t10ms,F ;
goto $+4
movlw .195 ;10ms 20000000/4/256=195
MOVWF t10ms
BSF flag,time1_f ;10ms标记,给时基子程序用
decfsz t1ms,F
goto service_time0_r
movlw .19 ;1ms
MOVWF t1ms
CALL scan_input ;(34Tcyc) ;输入扫描
goto service_r
service_time0_r
service_r
MOVFW FSR_TMP ;恢复被保护的寄存器
MOVWF FSR
MOVFW PCLATH_TMP
MOVWF PCLATH ;column X
swapf status_temp,W
movwf STATUS ;bank X
swapf w_temp,F
swapf w_temp,W
retfie ;exit interrupt
;**********************************************
start
clrf STATUS
CLRF PCLATH
BSF STATUS,RP0 ;Bank1
BTFSC PCON,NOT_POR ;上电复位?
GOTO LOOP ;N
;*********************************************上电复位
start2
clrf STATUS ;上电时需初始化的变量
clrf flag
movlw .100 ;1000ms
MOVWF sec ;
movlw 0xff ;输入口初始化
MOVWF keyh
MOVWF keyl
CLRF key_tim
MOVLW .30
MOVWF key_set ;延时设定0-255MS
GOTO LOOP
;**********************************************其它复位
LOOP
clrf STATUS
CLRWDT ;清狗
BSF STATUS, RP0 ;Bank1
BSF PCON,NOT_POR ;RESET NOT_POR
MOVLW B'11111111' ;PORTA\B\C\D\E方向设定1:IN 0:OUT
MOVWF TRISA
MOVLW B'11111111' ;
MOVWF TRISB
MOVLW B'11111111' ;
MOVWF TRISC ;
MOVLW B'11111111' ;
MOVWF TRISD
MOVLW B'00001111' ;
MOVWF TRISE
movlw B'00000111' ;select DDDDDDDD,ADC不用
movwf ADCON1 ;analog inputs
movlw B'10001000'
MOVWF OPTION_REG ;1:1 for WDT(18ms)预分频给看门狗
MOVLW B'00000000' ;Off OTHER IE 关了不用的中断
MOVWF PIE1
BCF INTCON,6 ;Off OTHER IE 关了不用的中断
BSF INTCON,7 ;ON GIE 开总中断
BSF INTCON,5 ;ON TIMER0 开TIMER0开总中断
clrf STATUS
CALL time1 ;CALL 时基1
MOVLW Crc8
CALL ACrcJs ;计算Crc0--Crc8的CRC检验码,用于MODBUS 结果CrcH1 CrcL1
GOTO LOOP ;不断循环运行
time1 ;时基1
btfsc flag,time1_f ;10ms到?
goto time1_1 ;y
goto time1_r ;n
time1_1
bcf flag,time1_f ;CLR time1_f 10ms到了
;TSTF timeout ; ;超时倒计时==0?
;btfss 3,2
;decf timeout,F ;n -1
decfsz sec,F ;sec-1==0?
goto time1_r ;n
movlw .100 ;y 1000ms
MOVWF sec ;1s到了
time1_r
return
;输入口扫描(中断服务)
;读portd\portb每位的值,去抖后存入keyh\keyl
;key_set延时设定0-255MS,调整它可以调整防抖时间
scan_input
INCF key_tim,F ;延时到?
MOVFW key_set
SUBWF key_tim,W
BTFSS 3,0
GOTO scan_input_r ;n
clrf key_tim ;y
movfw PORTD ;存入备用
MOVWF key_bh
MOVFW PORTB
MOVWF key_bl
movfw key_bh ;处理keyh
xorwf key_ah,F
comf key_ah,W
IORWF keyh,F
MOVFW key_ah
IORWF key_bh,W
ANDWF keyh,F ;去抖后的位状态
MOVFW key_bh
movwf key_ah
CLRF key_bh
movfw key_bl ;处理keyl
xorwf key_al,F
comf key_al,W
IORWF keyl,F
MOVFW key_al
IORWF key_bl,W
ANDWF keyl,F ;去抖后的位状态
MOVFW key_bl
movwf key_al
CLRF key_bl
scan_input_r
return
ACrcJs
;计算Crc0--CrcN的CRC检验码,用于MODBUS 结果CrcH1 CrcL1
MOVWF tempy ;最后一个byte 地址
movlw (Crc0-.1) ;从Crc0开始计算
movwf FSR
goto ACrcJs1
ACrcJs1
movlw 0FFH
movwf CrcL1
movwf CrcH1
ACrcJs2
incf FSR,F
incf tempy,W ;
subwf FSR,W
btfsc 3,0 ;FSR>=(最后一个byte 地址+1)?
goto ACrcJsR ;y
ACrcJs3
movlw (.1+.8) ;n设可移8次
movwf temp
movfw INDF ;CrcL oxr Crc(FSR)
xorwf CrcL1,F
ACrcJs4
decfsz temp,F ;temp-1=0?
goto $+2
goto ACrcJs2 ;y
bcf 3,0 ;右移
rrf CrcH1,F
rrf CrcL1,F
btfss 3,0 ;c=1?
goto ACrcJs4 ;n
movlw 0A0H ;y
xorwf CrcH1,F
movlw 01H
xorwf CrcL1,F
goto ACrcJs4
ACrcJsR
return
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -