movwf space1 ; 将第二行时间的显示空区域用空格填满 movwf space2 ; 否则偶的LCM会在空白处显示一对\字符 movwf space3 movwf space4 movwf space5 movwf space6 movwf space7 movwf space8 return
;**************************************** _disp2 movlw 0c0H
movwf PORTC ; 设定第二行显示位置 call _enable
movlw 0x10 ; 共显示16个字符 movwf count1
movlw 0x24 ; 获取显示缓冲区的首地址 movwf FSR ; 取得显示字符的地址 again2
movfw INDF ; 间接寻址获取字符ASCII码 call _write ; 输出到LCD显示 incf FSR
decfsz count1 ; 若显示完毕,则退出,否则继续显示下一字符 goto again2
retlw 0
;**************************************** _write ;送数据到LCD子程序 movwf PORTC bsf PORTA,RS bcf PORTA,RW bcf PORTA,E call _delay50ms bsf PORTA,E retlw 0
;*********写入LCM控制命令的子程序 _enable
bcf PORTA,RS
bcf PORTA,RW bcf PORTA,E call _delay50ms bsf PORTA,E retlw 0
;***************************************** _table1 ; 取第一行的显示码 addwf PCL ; 地址偏移量加当前PC值 dt \ retlw 00H
;****************************************** _delay50ms ; 根据需要,时间有
movlw 0x3c ; 晶振为4 Mhz,为0x3c时,大概15ms movwf x loop_x movlw 0xff movwf y loop_y decfsz y goto loop_y decfsz x goto loop_x return
;**************************
_bin_bcd ; 因为秒分钟小时的值不大于60,故采用此BCD码子程序来转换 movfw bin ; 8位二进制转换成2位BCD码 clrf bcd_h gtenth
movwf bcd_l movlw d'10' subwf bcd_l,w skpc goto exit movwf bcd_l incf bcd_h goto gtenth exit retlw 0
;**************************** end ;源程序结束
大约看了一下,
中断保护和中断恢复的顺序和方法都错了.
谢谢您的启发,我来分析一下程序中的“中断保护与恢复”是否错。 ORG 0x004 ; interrupt vector location
movwf w_temp ; save off current W register contents movf STATUS,w ; move status register into W register movwf status_temp ; save off contents of STATUS register movf PCLATH,w movwf pclath_temp movf FSR,w
movwf fsr_temp ; 保护现场
;保存W到w_temp中去
;STATUS通过w保存到status_temp中去 ;PCLATH通过w保存到pclath_temp中去 ;FSR通过w保存到fsr_temp中去
;这里好象没有错.
; return from interrupt end_int ; 恢复现场
movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents movf pclath_temp,W movwf PCLATH movf fsr_temp,W movwf FSR retfie
; 恩,这里有错了,斑竹提醒得对...
; W寄存器应该最后恢复,因为恢复PCLATH,FSR都要用到W...
; 谢谢谢版,由于程序模板中保存现场时只考虑了W和STATUS,所以,我在添加保存和恢复FSR,PCLATH时,没有留意其恢复的先后次序...
真的很谢谢斑竹的指点.... 按下面改变应该没错...
end_int ; 恢复现场
movf status_temp,w ; retrieve copy of STATUS register movwf STATUS ; restore pre-isr STATUS register contents movf pclath_temp,W movwf PCLATH
movf fsr_temp,W movwf FSR swapf w_temp,f
swapf w_temp,w ; restore pre-isr W register contents retfie
还不行. 次序还是错了.
你要知道MOVF这个指令会影响STATUS的Z位,所以会有后面的两个SWAPF的指令来恢复W寄存器.仔细揣摩一下SWAPF指令的含义.
无论在什么情况下中断保护中第一是保护W,然后保护STATUS.然后再保护其它...恢复的顺序相反,最后恢复W,之前是恢复STATUS.STATUS会影响到许多运算的结果,还有寄存器的页面等也由STATUS来决定.
下午上班时小弟发现w_temp等变量不是定义在70H后的快速存取区,因此,斑竹说得对,这样保存和恢复现场还是存在问题...
今天下午通过调试,又发现了更多的问题...
其实
W_TEMP定义在哪个区块并不重要,只是定义了W_TEMP之后,在其它区块的同一个位置不得定义其它变量,这样才能保证中断保护的正常执行.其中的原因是在寄存器直接寻址时,其地址只有低7位有效.
我是一个刚接触微芯单片机的菜鸟,以前学过51系列单片机,前几天编写了一个利用TMR1作为定时器实现500ms定时、同时通过同步串口交替发送数据的程序,用的编译软件为 MPLAB IDE V6.30,单片机为 pic16f73,在编译调试过程中碰到以下问题:
1. 在编译报告中有以下信息:Register in operand not in bank 0. Ensure that bank bits are correct.
可是我已经在程序中注意了,语句如下
BSF STATUS,RP0 ;换bank1
CLRF TRISA CLRF TRISC
结果报告指出以上 TRISA、TRISC两个寄存器出现以上报告的相关信息。但是编译还是成功的,只是在实验板上发现没有实现预想功能,定时不起作用,不知道结果不对和这个信息报告是否有关系?是否出现这样的错误报告就可能会影响程序的正常运行?可是语句中已经转化到了bank1,为什么又还会出现这样的错误报告呢?
2. 程序在MPLAB 中模拟单步运行的时候,发现当定时到了TMR1产生溢出以后,却无法产生响应的中断
以及跳转到中断向量 0x04 去执行中断程序,不知这是不是和编译软件有关?还是程序本身的问题(中
相关推荐: