- list p = 16f876a
- #include
- __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _XT_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF & _DEBUG_ON
- CBLOCK 0X20
- W_TEMP ;定义保护W寄存器的备份寄存器位于bank0地址0x20处,注意bank1的0xa0,bank2的0x120,bank3的0x1a0都必须留给w_temp
- STATUS_TEMP ;定义保护STATUS寄存器的备份单元
- PCH_TEMP ;定义保护PCLATH寄存器的备份单元
- FSR_TEMP ;定义保护FSR寄存器的备份单元
- COUNT1
- COUNT2
- COUNT3
- ENDC
- ORG 0X0000
- NOP
- GOTO main
- ORG 0X0004
- CALL INT_PROTECT
- CLRF PCLATH ;跳转前设定正确的PCLATH
- GOTO INT_TABLE ;跳转到中断查询表
- main:
- CALL RB0_INT_INIT
- ;中断产生后进入中断服务程序,查询INTF中断标志位。
- ;若INTF = 1,则处理RB0/INT中断,处理完毕后(或处理前)软件必须清除INTF中断标志位
- banksel TRISA
- BCF TRISA,2
- banksel PORTA
- BSF PORTA,2 ;LED_OUTSIDE ON
- loop:
- GOTO loop
- ;************************中断初始化*************************
- RB0_INT_INIT:
- BANKSEL TRISB ;片选bank1
- BSF TRISB,0 ;RB0为输入模式
- ;BCF OPTION_REG,7 ;使能弱上拉
- BCF OPTION_REG,INTEDG ;下降沿中断
- BANKSEL PORTB ;返回到bank0
- BCF INTCON,INTF ;确保有效中断发生前中断标志为0
- BSF INTCON,INTE ;允许RB0/INT中断响应
- BSF INTCON,GIE ;打开总中断允许使能位
- RETURN
- ;************************中断保护******************************
- INT_PROTECT:
- ;保护中断现场
- MOVWF W_TEMP ;立即把W寄存器复制到备份寄存器中
- MOVF STATUS,W ;把STATUS放置到W寄存器中暂存,虽然movf指令执行结果会改变STATUS,但在发生变化之前原内容以送进W
- ;此指令也可以用“swapf status,w”,在最后恢复时需用swapf指令配对
- CLRF STATUS ;此时可以改变STATUS,设定RP1:RP0 = 00,指向bank0
- MOVWF STATUS_TEMP ;把存在W的原STATUS的值复制到其备份单元
- MOVF PCLATH,W ;把原PCLATH的值复制到W
- MOVWF PCH_TEMP ;把存在W的原PCLATH的值复制到其备份单元
- MOVF FSR,W ;把原FSR的值复制到W
- MOVWF FSR_TEMP ;把存在W的原FSR的值复制到其备份单元
- ;...................;保护其他需要备份的寄存器
- ;到此,全部寄存器已经妥善保护,可以执行中断服务代码了
- RETURN
- ;*************************中断恢复**********************************
- INT_EXIT:
- ;中断服务程序出口
- CLRF STATUS ;设定RP1:RP0 = 00,指向bank0
- ;............. ;恢复其他要恢复的寄存器
- MOVF FSR_TEMP,W ;取FSR保护的内容
- MOVWF FSR ;恢复FSR
- MOVF PCH_TEMP,W ;取PCLATH保护的内容
- MOVWF PCLATH ;恢复PCLATH
- MOVF STATUS_TEMP,W ;取STATUS保护的内容
- MOVWF STATUS ;恢复STATUS
- ;到此,除W寄存器外所有其他保护寄存器已经全部恢复
- ;在接下来的恢复W寄存器过程中千万不能破坏他们的内容
- SWAPF W_TEMP,F ;先把W_TEMP的内容高低半字节交换一次
- SWAPF W_TEMP,W ;再把W_TEMP的内容高低半字节交换一次,但结果放在W内 ;用法说明详见P58页
- RETFIE ;中断返回,GIE被自动置1,可以响应其他中断
- ;************************中断源查询程序******************************************
- INT_TABLE:
- BTFSS INTCON, T0IE ;TIMER0中断使能标志位T0IE是否为1,为1跳
- GOTO RB0_INT_ASK
- BTFSC INTCON, T0IF ;TIMER0是否发生中断,为0跳
- GOTO TMR0_INT_START ;是,跳到TMR0_INT_START中断程序
- RB0_INT_ASK:
- BTFSC INTCON, INTF
- GOTO INT_RB4_LED_ON_OR_OFF
- ;**************************中断服务程序**********************************************
- INT_RB4_LED_ON_OR_OFF:
- CALL INT_PROTECT
- BCF INTCON,INTF ;先将中断标志位清0,保证下次中断发生
- BTFSC PORTB,4 ;为1(即灭)则点亮,为0(即亮)则跳点灭
- GOTO AAA
- CALL LED_GREEN_OFF
- CALL INT_EXIT
- AAA:
- CALL LED_GREEN_ON
- CALL INT_EXIT
- ;******************************LED_GREEN_ON***************************************
- LED_GREEN_ON:
- BANKSEL TRISB
- BCF TRISB,4 ;RB4为输出状态
- BANKSEL PORTB
- BCF PORTB,4 ;RB4为低电平,点亮
- RETURN
- ;*******************************LED_GREEN_OFF*************************************
- LED_GREEN_OFF:
- BANKSEL TRISB
- BCF TRISB,4 ;RB4为输出状态
- BANKSEL PORTB
- BSF PORTB,4 ;RB4为高电平,点灭
- RETURN
- ;**********************************TMR0中断服务程序*******************************
- TMR0_INT_START:
- NOP
- ;*****************************延时程序********************************************
- DELAY_1s:
- MOVLW 0X06 ;1秒延迟
- MOVWF COUNT1
- delay1:
- MOVLW 0X0EB
- MOVWF COUNT2
- delay2:
- MOVLW 0X0EC
- MOVWF COUNT3
- delay3:
- DECFSZ COUNT3,F
- GOTO delay3
- DECFSZ COUNT2,F
- GOTO delay2
- DECFSZ COUNT1,F
- GOTO delay1
- RETURN
- end
复制代码背景:小菜我刚接触PIC单片机没多久,写了一个验证RB0/INT下降沿触发中断的程序,遇到了小麻烦,只能下降沿触发一次,后面出现下降沿触发点灯就没反应,不知为何,我用ISIS做了仿真不行。请诸位帮我分析分析,看看什么原因一起研究研究~附上仿真图
此帖出自
小平头技术问答
没用过PIC的汇编,不懂。
估计可能是进入中断后没有清必要的标志吧,很多片子都需要手动清除某个标志才能为下一次中断做准备。建议参考一下官方的例程!
一周热门 更多>