在写一个液晶显示的程序,刚接触液晶显示,写了一个简单的时钟程序来看效果。
程序初始运行良好,但加入键盘后,在某一次按下键盘后出现闪屏……
用仿真器调试,发现反复压栈,压栈的时间很莫名其妙,出栈后的位置在程序的中间位置,按理说不应当……
请教一下,对出现反复压栈的情况,应当怎样排查错误。
调了很长时间都没结果,希望指点一下……
先谢谢了……
按键需要做去抖动(debouncing)处理. 如果是在中断中处理按键, 在一次按键中不去抖动就会多次触发中断. FYI.
按键去抖动了,也设置了等待按键抬起……
压栈的位置处有个小循环,我设置了一个内存单元来控制循环次数,压栈的点就在给内存单元送循环次数之后,本来该单元已经减到了0,程序跳到此处后从0FFh开始减,到减到0时,就突然压了8-9个单元。内存单元并未在其他位置处修改。能引起中断的只有定时器的中断服务程序,中断服务程序不会修改该内存单元……
我把此处的循环去了以后,直接实现,电路就好了……
很郁闷……
好像也不是,我把堆栈留了32个单元,还是那样
我看了一下,在延时的时间里突然就多出了10个左右的压栈,所压的位置就在循环处,导致反复改写数据,使屏幕闪动……
今天改了一下,一运行就出现闪动,昨天是在按键后才有……
去了这个循环就好了……
不知什么原因……
DISP:
LCALL LCD_PRT;显示前面的字符串
MOV A,#0C0H;从第八个位置开始显示
LCALL WRCOM;
MOV P2,#DW_ADD;写数据的地址
MOV R1,#0FFH;
MOV NUM,#03H;要写入数据的个数
DISP1:MOV A,@R0;
LCALL CONV;16进制数先转换为BCD码,再转换为ASCII码,并分别显示
INC R0;
DJNZ NUM,DISP1;
; MOV A,@R0;
; LCALL CONV;16进制数先转换为BCD码,再转换为ASCII码,并显示
; INC R0;
; MOV A,@R0;
; LCALL CONV;16进制数先转换为BCD码,再转换为ASCII码,并显示
; INC R0;
; MOV A,@R0;
; LCALL CONV;16进制数先转换为BCD码,再转换为ASCII码,并显示
DEC R0;将R0调整回原位置
DEC R0;
RET;
谢谢了,麻烦zyzhang365了
NUM是个内存单元,我设的是41h,没有其他变量占用……
加注释的地方是不带循环时的程序
conv是个转换程序,应该没有影响
conv的代码在下面
;数据转换
CONV:
MOV B,#10 ;分离十位和个位
DIV AB;A中为十位,B中为个位
ADD A,#30H
MOVX @R1,A;转换后的数据送显示
LCALL DLY00;
MOV A ,B;
ADD A,#30H;
MOVX @R1,A;转换后的数据送显示
LCALL DLY00;
MOV A,#":";
MOVX @R1,A;显示分号
LCALL DLY00;
RET
DLY00:
MOV DLY3,#00H;
DJNZ DLY3,$;
RET;
DLY3 EQU 44H;
麻烦了……
其实我很久没有使用汇编写程序了, 希望别人能帮上你的忙. 你的SP初始值是多少?
应该不是溢出吧,我开始设的是70h,后来又改成了60h,还是那样
谢谢了,看不出来就算了,这是我自己随便调的个程序,刚用液晶,就写了个简单的时钟程序测试一下.
我昨天把程序改成了C,运行良好....
以后想用C,数据处理比较方便,也不用担心那么多的冲突...
多谢zyzhang365了...
希望zyzhang365给提点用C编程的经验和建议,谢谢了....