发现一个怪问题:for语句延时时间的问题

[复制链接]
5232|14
 楼主| mcuatmel 发表于 2011-1-28 16:19 | 显示全部楼层 |阅读模式
调试一个脉冲程序,大体如下:
sbit sPaulse=P1^2;
uchar i;
uint j,wtemp1;

wtemp1=...;
EA=0;
for (i=0;i<30;i++)
{
    sPaulse=0;
    for(j=0;j<80;j++);
    sPaulse=1;
    for(j=0;j<wtemp1;j++);
}
EA=1;
此处wtemp1变量代入50,150,250三个变量时得出的延时时长不是成比例的,不知是为什么,请高手指点。
wubowww888 发表于 2011-1-28 16:43 | 显示全部楼层
C语言不好,猜测“for(j=0;j<wtemp1;j++);”这条指令有其指令时间,没考虑在内?
NE5532 发表于 2011-1-28 19:43 | 显示全部楼层
C语言要翻译成机器码,不是你看的一个for那么简单,不信你看编译出来的汇编代码。
yewuyi 发表于 2011-1-29 08:57 | 显示全部楼层
请尽量不要使用指令延时来实现精确的时间控制。

一般软件延迟只会用在那些时间多点少点无所谓,时间也很短的那种场合。
zq1987731 发表于 2011-1-29 09:53 | 显示全部楼层
EA=0;
for (i=0;i<30;i++)
{
    sPaulse=0;
    for(j=0;j<80;j++);
    sPaulse=1;
    for(j=0;j<wtemp1;j++);
}
EA=1;


又一个死读书的,这样的程序只能称之为“教学范例”
红色的2句对实时性要求高的程序而言就是毁灭性的,单片机玩到入门阶段后一般人首先就会抛弃delayms();这种东西,也就是说,这种研究根本就是浪费时间

建议LZ把精力多放在定时器和状态机方向
如果非要纠结于此,用Keil前后插2断点多试几次就会得到类似于
(wtemp1 × 延时时间) + 常数
的关系式来
 楼主| mcuatmel 发表于 2011-1-29 15:25 | 显示全部楼层
谢楼上各位!
非我不想用定时器,我的定时器实在不够用了,51单片机,双串口的那种,用了两个串口,两种波特率,数码管显示用了T0,还有一个脉冲接收解码,用了T1,脉冲发码想再用一个定时器,可是没有了。
现在问题只能是凑合解决了,用T0同时做发码,这样数码显示时会有问题,但终还可以用。
 楼主| mcuatmel 发表于 2011-1-29 15:25 | 显示全部楼层
谢楼上各位!
非我不想用定时器,我的定时器实在不够用了,51单片机,双串口的那种,用了两个串口,两种波特率,数码管显示用了T0,还有一个脉冲接收解码,用了T1,脉冲发码想再用一个定时器,可是没有了。
现在问题只能是凑合解决了,用T0同时做发码,这样数码显示时会有问题,但终还可以用。
zq1987731 发表于 2011-1-29 16:47 | 显示全部楼层
用T0同时做发码,这样数码显示时会有问题

从这里就能看出中断以及主程序的分工就没有处理好
无非就是脉冲接收编码的ISR服务时间过长导致同时刷新数码管产生延误
事实上假设定时器的中断ISR设为1ms触发一次,每次触发都修改2个时基分别对应这2个任务,数码管显示只要20ms响应一次就足够,那么自然就能定时器复用,怎么可能还会有这种问题
wang198203 发表于 2011-1-29 16:48 | 显示全部楼层
可能和编译工具有关吧。我碰到过一次。程序短的时候,用FOR语句延时差不多,程序长的时候,FOR语言汇编后生成很多没用的东西,浪费很长时间。
coody 发表于 2011-1-29 17:30 | 显示全部楼层
7楼,按这样说,那一个复杂点的项目,有几十上百种定时, 那得用什么MCU呢?要有几十个定时器
刘前辈 发表于 2011-1-30 17:35 | 显示全部楼层
把   for(j=0;j<wtemp1;j++);    改写为
while(--wtemp1);
就成比例了。

当然要把wtemp1说明为uchar 类型
uchar  wtemp1=50;  //150,250……

    22: while(--wtemp1);
C:0x08A8    1508     DEC      wtemp1(0x08)
C:0x08AA    AF08     MOV      R7,wtemp1(0x08)
C:0x08AC    EF       MOV      A,R7
C:0x08AD    70F9     JNZ      C:08A8
    23: }


 楼主| mcuatmel 发表于 2011-1-30 19:53 | 显示全部楼层
谢楼上!有时间我试下。
8楼:按你说的,20ms数码管显示一次,那是静态的吧,我的是5ms一次/位。
10楼:该用多少定时器得看情况,我一个定时器中断中处理过十几种任务,一般的程序我只用一个定时器,但遇特殊情况不能共用的也没办法,如果一个定时器能解决所有问题的话那现在的ARM处理器就没必要集成6个以上的定时器了。
zq1987731 发表于 2011-1-30 23:28 | 显示全部楼层
to mcuatmel:
20ms是单个8段码的情况,我只是按50Hz举例,这里不用说20ms,即使5ms甚至2.5ms,在定时器复用的前提下根本不算问题,ISR中只根据中断作标志位处理,其余一概在主循环中进行!!!这种情况下模拟出几十个定时器根本就是游刃有余。
另外ARM集成的大量定时器,建议LZ好好看看到底用在什么地方,顺便看看主流RTOS中的设计,思维就不会这么狭隘
fushaobing 发表于 2011-2-1 10:41 | 显示全部楼层
当然不成比例了。
看反汇编就知道是为什么了。比如j=0就没有包括在循环次数里。
要按比例延时,还得依靠示波器测试,对wtemp1的初值进行微调。
norman33 发表于 2011-2-1 15:47 | 显示全部楼层
同意4楼,正式工程上是不能有长时间死等的情况的,频繁开关中断会丢中断请求这对系统实时性是有很大影响的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

512

主题

1456

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部