历史上的今天
今天是:2024年12月19日(星期四)
2018年12月19日 | 51单片机 主循环和中断共享全局变量的冲突
2018-12-19 来源:eefocus
现象:工作中遇到一个大坑,STC11F32的运行灯闪的不均匀,大多数是500ms低电平和500ms高电平,但偶尔会有40ms左右的高、低电平出现,对,就这么简单的一个程序,奇哉怪哉!
//定义全局变量:ms计数器
unsigned int cnt_ms;
//定义全局变量:ms计数器备份
unsigned int cnt_ms_bk;
//定义LED对应的IO口
sbit LED = P3 ^ 3;
//主循环读访问
int main(void)
{
......
if ((cnt_ms - cnt_ms_bk) > 500)
{
led = ~led;
cnt_ms_bk = cnt_ms;
}
......
}
void timer0_interrupt(void) interrupt 1
{
......
TL0 = 0x0cd; //装在1ms定时初值
TH0 = 0x0f8;
count_1ms++;
......
}
解决方法:主循环程序修改如下,用示波器观察led的闪烁,结果是正常的。
int main(void)
{
......
EA = 0; //关中断
if ((cnt_ms - cnt_ms_bk) > 500)
{
led = ~led;
cnt_ms_bk = cnt_ms;
}
EA = 1; //开中断
......
}
原因分析:反汇编如下,为分析方便采用16位示例。
......
101: if ((cnt_ms - cnt_ms_bk) >= 500)
C : 0x0F18 900036 MOV DPTR, #msLedCtr(0x0036)
C : 0x0F1B E0 MOVX A, @DPTR
C : 0x0F1C F8 MOV R0, A
C : 0x0F1D A3 INC DPTR
C : 0x0F1E E0 MOVX A, @DPTR
C : 0x0F1F F9 MOV R1, A
C : 0x0F20 A3 INC DPTR
C : 0x0F21 E0 MOVX A, @DPTR
C : 0x0F22 FA MOV R2, A
C : 0x0F23 A3 INC DPTR
C : 0x0F24 E0 MOVX A, @DPTR
C : 0x0F25 FB MOV R3, A
C : 0x0F26 900031 MOV DPTR, #count_1ms(0x0031)
C : 0x0F29 E0 MOVX A, @DPTR
C : 0x0F2A FC MOV R4, A
C : 0x0F2B A3 INC DPTR
C : 0x0F2C E0 MOVX A, @DPTR //在此处被中断
C : 0x0F2D FD MOV R5, A
C : 0x0F2E A3 INC DPTR
C : 0x0F2F E0 MOVX A, @DPTR
C : 0x0F30 FE MOV R6, A
C : 0x0F31 A3 INC DPTR
C : 0x0F32 E0 MOVX A, @DPTR
C : 0x0F33 C3 CLR C
C : 0x0F34 9B SUBB A, R3
C : 0x0F35 FF MOV R7, A
C : 0x0F36 EE MOV A, R6
C : 0x0F37 9A SUBB A, R2
C : 0x0F38 FE MOV R6, A
C : 0x0F39 ED MOV A, R5
C : 0x0F3A 99 SUBB A, R1
C : 0x0F3B FD MOV R5, A
C : 0x0F3C EC MOV A, R4
C : 0x0F3D 98 SUBB A, R0
C : 0x0F3E FC MOV R4, A
......
......
282 : cnt_ms++;
C : 0x09D1 900031 MOV DPTR, #cnt_ms(0x0031)
C : 0x09D4 E0 MOVX A, @DPTR
C : 0x09D5 FC MOV R4, A
C : 0x09D6 A3 INC DPTR
C : 0x09D7 E0 MOVX A, @DPTR
C : 0x09D8 FD MOV R5, A
C : 0x09D9 A3 INC DPTR
C : 0x09DA E0 MOVX A, @DPTR
C : 0x09DB FE MOV R6, A
C : 0x09DC A3 INC DPTR
C : 0x09DD E0 MOVX A, @DPTR
C : 0x09DE 2401 ADD A, #0x01
C :0x09E0 FF MOV R7, A
C : 0x09E1 E4 CLR A
C : 0x09E2 3E ADDC A, R6
C : 0x09E3 FE MOV R6, A
C : 0x09E4 E4 CLR A
C : 0x09E5 3D ADDC A, R5
C : 0x09E6 FD MOV R5, A
C : 0x09E7 E4 CLR A
C : 0x09E8 3C ADDC A, R4
C : 0x09E9 FC MOV R4, A
C : 0x09EA 900031 MOV DPTR, #count_1ms(0x0031)
C : 0x09ED 1218B7 LCALL C ? LSTXDATA(C : 18B7)
......
假设在上述位置被中断前cnt_ms的值为0x00FF,cnt_ms_bk的值为0x0000时:R4装载的值为0xFF,本打算给R5装载值0x00,结果被中断打断,中断后cnt_ms++,后其值变为0x0100,中断执行完返回后继续主循环中装载R5,结果给R5装载值0x01,各位现在主循环中使用的cnt_ms为0x01FF了,这样就会造成脉冲的变窄。
我起先老纠结中断时会压栈,会将变量保存。实际中断时保存的是ACC, B, DPTR等寄存器,但是全局变量cnt_ms被保存到了xdata区,DPTR中断前后不变,但其指向的内容(xdata区)已被修改。
上一篇:单片机 uart中断处理函数例子
下一篇:C51 单片机 读取93C64
史海拾趣
|
处理器的体系结构定义了指令集(ISA)和基于这一体系结构下处理器的程序员模型。尽管每个处理器 性能不同,所面向的应用不同,每个处理器的实现都要遵循这一体系结构。ARM体系结构为嵌入系统发展 商提供很高的系统性能,同时保持优异的功耗和 面 ...… 查看全部问答> |
|
大家看一下,怎么样让这个板子上的SOUNDER响啊,用kei软件,C语言编写的程序应该是什么样的,哪位大侠帮我这个刚接触单片机的菜鸟编个程序啊,我怎么弄不响啊?谢谢大家了! QQ:553695150 [ 本帖最后由 tiankai001 于 2010-4-27 10:18 编辑 ]… 查看全部问答> |
|
现在用nrf905设计开发一个射频智能卡测试平台的无线接口,为增强实验的可靠性,我们在设计了PCB环形差分天线的前提下,通过两个跳线,将芯片的ANT1和ANT2通过匹配网络再连接到SMA天线接口处,以备PCB环形天线不能满足实验要求时,可以经过跳线连接 ...… 查看全部问答> |
|
;-------------------------------------------------------------------------- ;[H1+H2]+[ADR]+[CMD]+[CRC] ;[L1+L2]+[ID]+[TEM_1]+[TEM_2]+[TEM_3]+[TEM_4]+[TEM_5]+[DOOR] ;-------------------------------------------------------------- ...… 查看全部问答> |
|
ARM启动后,设置了PPL时钟工作频率,然后进入main函数执行,在main函数创建启动任务及其他任务,在启动任务里面创建系统滴答时钟定时器。 因为有个模块需要延时100MS复位时间,才能开始工作,初始化时间也要30MS左右。那么我能把这个 ...… 查看全部问答> |
|
$(\'swf_RHB\').innerHTML=AC_FL_RunContent(\'width\', \'550\', \'height\', \'400\', \'allowNetworking\', \'internal\', \'allowScriptAccess\', \'never\', \'src\', encodeURI(\'http://player.youku.com/player.php/sid/XMzY5MjkwNDIw/v.sw ...… 查看全部问答> |
|
我们寻觅那些卓然不群的开拓者、同样期待那些精益求精的坚守者,而你将成就的是一个远大的梦想、一段激情的旅程。如果不甘寂寞的你渴望今天就开始改变自己、改变世界,请申请加入我们!我们在一览LED英才网上发布招聘信息,期待您的加入。深圳市源 ...… 查看全部问答> |




