论坛风格切换切换到宽版
  • 5140阅读
  • 3回复

PIC 中断的响应与复位 [复制链接]

上一主题 下一主题
离线XLDZZ
 
发帖
443
只看楼主 倒序阅读 0楼 发表于: 2009-08-26
最近想做个测速的设备
但是碰到一些问题,是关于中断的,在关掉中断的情况下led能正常动态显示。但开中断后
一旦中断响应,就出不了中断。
不知道为什么,我已经清楚标志位并保护了现场。以下是问题程序。
附件为开发板原理图
list   p=16f877
#include "p16f877a.inc"
__config b�'0x3b31

cunt     equ 30h;ccp中断计数暂存
cunt_pro   equ 31h;用于计算中间寄存器
temp_cunt   equ 32h;用于显示代码暂存
ge       equ 33h;个位
shi       equ 34h;十位
bai       equ 35h;百位
mpy_h     equ 36h;乘积高8位
mpy_l     equ 37h;乘积低8位
mpy_temp1   equ 38h;乘法暂存器1
mpy_temp2   equ 39h;乘法暂存器2
mpy_temp3   equ 4ah;乘法暂存器3
time_cunt   equ 4bh;时间寄存器
flg       equ 4ch;标志寄存器(bit0为2s时间到,bit1表示ccp1中断,bit3表示允许tmr1中断)
temp     equ 4dh;中间寄存器
status_temp equ 4eh;状态位暂存
w_temp     equ 4fh;w暂存
pcl_temp   equ 50h;pcl暂存


org 000h
nop
movlw 0ah
movwf time_cunt
goto main
org 004h
nop
goto int


main
call io_reset;io初始化
call int_reset;中断初始化
clrf flg
banksel portc
loop_check
btfss portc,5
goto loop_check
call delay750us
btfss portc,5
goto loop_check;按键程序
movlw b񟝘'
movwf portd
call sc;按键后点亮灯
banksel pie1
bsf pie1,2;允许ccp中断
banksel pir1
goto loop_dsp
;----------主程序--------
loop_dsp
movf ge,0
movwf temp_cunt
call table
movwf portb
call sc_ge;374锁存
movf shi,0
movwf temp_cunt
call table
movwf portb
call sc_shi;374锁存
movf bai,0
movwf temp_cunt
call table
movwf portb
call sc_bai;374锁存
goto loop_dsp
;-----------动态显示----------------


;------------主程序--------------
io_reset
banksel trisc
movlw 0ffh
movwf trisc
movlw 00h
movwf trise
movwf trisd
movwf trisb
banksel portc
clrf portc
clrf portd
clrf portb
clrf porte
clrf ge
clrf shi
clrf bai
clrf flg
clrf time_cunt
call sc
return
;-----------io初始化---------------
int_reset
banksel intcon
movlw b�'开总中断,开第二梯队中断
movwf intcon
banksel pie1
movlw   b�'
movwf pie1;只允许tmr1,ccp未开中断
banksel pir1
movlw b�'
movwf t1con;分频比1:8,不同步,关tmr1
movlw b�'
movwf ccp1con
clrf pir1;清第二中断标志
clrf tmr1l
clrf tmr1h
return
;----------中断初始化--------------
int
banksel pie1
clrf pie1
banksel portc
movwf w_temp;保护w内容
movf status,0
movwf status_temp;保护状态位
movf pcl,0
movwf pcl_temp;保护pcl

btfss pir1,2;ccp中断否
goto int_retfie;goto int_next
goto int_retfie;goto ccp_int
int_next
btfss flg,3;是否允许tmr1中断
goto int_retfie
btfss pir1,0;tmr1中断否
goto int_retfie
bcf pir1,0
decfsz time_cunt,1;减一为0则转移
goto int_retfie
bsf flg,0;2s时间到,flg bit0置位
movlw 0ah
movwf time_cunt;时间计数器重置
goto int_retfie
;-----------中断服务----------------
ccp_int
movlw 0ah
movwf temp
incf cunt,1;ccp中断计数器加1
incf ge,1 ;个位加1
movf temp,0
subwf ge,0
btfss status,2
goto int_retfie
incf shi,1
clrf ge
movf temp,0
subwf shi,0
btfss status,2
goto int_retfie
incf bai,1
clrf shi
movf temp,0
subwf bai,0
btfss status,2
goto int_retfie
clrf ge
clrf shi
clrf bai
goto int_next
int_retfie
banksel pie1
bsf pie1,0
bsf pie1,2
banksel portd
movf pcl_temp,0
movwf pcl
movf status_temp,0
movwf status
movf w_temp,0
retfie
;---------ccp中断服务---------
pro_2s
banksel pie1
movlw 00h
movwf pie1;关所ccp,tmr1中断
banksel pir1
bcf t1con,0;关闭定时器1
clrf tmr1l
clrf tmr1h
movf cunt
movwf cunt_pro;把cunt(ccp中断次数计数器)值送往cunt_pro计数器
clrf cunt;清ccp中断计数器
clrf ge
clrf shi
clrf bai
banksel pie1
movlw 05h   ;b�',允许tmr1,ccp中断
movwf pie1
bankpir1
bsf t1con,0;开定时器1
bsf flg,3 ;开定时器软件中断标志
bcf flg,0 ;清时2s间到标记
pro2s_check
btfss flg,0
goto pro2s_check
banksel pie1
movlw 00h
movwf pie1
banksel pir1
bsf portd,6
call sc
goto loop_dsp



;---------------计算转速-------------

delay1ms:   movlw 09fh
        movwf 20h
lp01:     movlw 0ffh
        movwf 21h
lp11:     movlw 02ch
        movwf 22h
lp21:     decfsz 22h
        goto   lp21
        decfsz 21h
        goto   lp11
        decfsz 20h
        goto   lp01
        return
;----------1ms延时程序---------------


delay750us:
        movlw 0ffh
        movwf 26h
        loop750
        nop
        nop
        nop
        nop
        decfsz 26h,1
        goto loop750
        return
;----------750us延时程序----------------
delayn
nop
nop
nop
nop
nop
return





sc
movlw 06h
movwf porte
call delay750us
clrf porte
return
;--------374锁存程序--------------------

sc_ge
movlw 01h
movwf portd
movlw 06h
movwf porte
call delayn
clrf porte
return
;-------动态个位显示锁存----------------
sc_shi
movlw 02h
movwf portd
movlw 06h
movwf porte
call delayn
clrf porte
return
;-------动态十位显示锁存----------------
sc_bai
movlw 04h
movwf portd
movlw 06h
movwf porte
call delayn
clrf porte
return
;-------动态百位显示锁存----------------
table
movf temp_cunt,0
addwf pcl,1
retlw 0d7h
retlw 012h
retlw 0cbh
retlw 05bh
retlw 01eh
retlw 05dh
retlw 0ddh
retlw 013h
retlw 0dfh
retlw 05fh
;-----------显示解码程序-----------------
end
附件: MAIN.pdf (0 K) 下载次数:65
离线bellstudio
发帖
2820
只看该作者 1楼 发表于: 2009-08-27
int
banksel pie1
clrf pie1
banksel portc
movwf w_temp;保护w内容
movf status,0
movwf status_temp;保护状态位
movf pcl,0
movwf pcl_temp;保护pcl

暂时看出两个地方
1、顺序上有问题,你都先做bank切换了,你存status还有啥意义?你这样返回时的bank很可能是错误的
2、pcl不需要存的,通常是在有跨页调用的时候存pclath
在线BG2WAH
发帖
606
只看该作者 2楼 发表于: 2009-08-27
补充一点……

; 现场保寄存器必需定为0x70--0x7f单元

            list     p=16f877a, st=off
                errorlevel -302, -306
                include <p16f877a.inc>

status_temp equ 0x71         ; 状态位暂存
w_temp     equ 0x72         ; w暂存
;---------------------------------
      org   0x0000
      goto   picstart     ; 到主程序
      org   0x0004       ; 中断入口地址
      movwf   w_temp       ; 保护w
      movf   status,w
      clrf   status       ; 无论在哪个体都恢复到休0
      movwf   status_temp   ; 保护status
;       movf   pclath,w     ; 如果跨页加上这条
;       clrf   pclath
;       movwf   pclath_temp   ; 保护pclath
;       movf   fsr,w       ; 如果用了间接寻址加上这条
;       movwf   fsr_temp
      goto   intermit     ; 到服务中断子程序
;---------------------------------
picstart clrwdt             ; (如果启用看门狗加上这条)
      call   initial       ; 调用系统初始化子程序
      ; .............

mainpic   ;..............       ; 主程序
      goto   mainpic
;---------------------------------
; 服务中断子程序

intermit btfss   pir1,ccp1if   ; ccp中断否?
      goto   comeback     ; 否,到恢复
      bcf   pir1,ccp1if   ; 是,清标志位
      ;...............
      ;...............
      goto   comeback
     
; (清pie1可能会丢失计数值)
;---------------------------------
; 恢复现场

comeback ; movf   pclath_temp,w
      ; movwf   pclath       ; 恢复pclath数据
      ; movf   fsr_temp,w
      ; movwf   fsr
      movf   status_temp,w
      movwf   status       ; 恢复status数据
      swapf   w_temp,f
      swapf   w_temp,w     ; 恢复w数据
      retfie             ; 返回断点
;----------------------------------
; 初始化子程序

initial   bsf   status,rp0     ; 体1
      movlw   0xc
      movwf   adcon1       ; re为i/o端口
      clrf   trise
      banksel porte       ; 确认体0
      clrf   porte
      return
;---------------------------------
      end
离线XLDZZ
发帖
443
只看该作者 3楼 发表于: 2009-08-27
感谢 坛内弟兄答疑解惑