打印

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

[复制链接]
4076|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 | 只看该作者
请尽量不要使用指令延时来实现精确的时间控制。

一般软件延迟只会用在那些时间多点少点无所谓,时间也很短的那种场合。

使用特权

评论回复
5
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 × 延时时间) + 常数
的关系式来

使用特权

评论回复
6
mcuatmel|  楼主 | 2011-1-29 15:25 | 只看该作者
谢楼上各位!
非我不想用定时器,我的定时器实在不够用了,51单片机,双串口的那种,用了两个串口,两种波特率,数码管显示用了T0,还有一个脉冲接收解码,用了T1,脉冲发码想再用一个定时器,可是没有了。
现在问题只能是凑合解决了,用T0同时做发码,这样数码显示时会有问题,但终还可以用。

使用特权

评论回复
7
mcuatmel|  楼主 | 2011-1-29 15:25 | 只看该作者
谢楼上各位!
非我不想用定时器,我的定时器实在不够用了,51单片机,双串口的那种,用了两个串口,两种波特率,数码管显示用了T0,还有一个脉冲接收解码,用了T1,脉冲发码想再用一个定时器,可是没有了。
现在问题只能是凑合解决了,用T0同时做发码,这样数码显示时会有问题,但终还可以用。

使用特权

评论回复
8
zq1987731| | 2011-1-29 16:47 | 只看该作者
用T0同时做发码,这样数码显示时会有问题

从这里就能看出中断以及主程序的分工就没有处理好
无非就是脉冲接收编码的ISR服务时间过长导致同时刷新数码管产生延误
事实上假设定时器的中断ISR设为1ms触发一次,每次触发都修改2个时基分别对应这2个任务,数码管显示只要20ms响应一次就足够,那么自然就能定时器复用,怎么可能还会有这种问题

使用特权

评论回复
9
wang198203| | 2011-1-29 16:48 | 只看该作者
可能和编译工具有关吧。我碰到过一次。程序短的时候,用FOR语句延时差不多,程序长的时候,FOR语言汇编后生成很多没用的东西,浪费很长时间。

使用特权

评论回复
10
coody| | 2011-1-29 17:30 | 只看该作者
7楼,按这样说,那一个复杂点的项目,有几十上百种定时, 那得用什么MCU呢?要有几十个定时器

使用特权

评论回复
11
刘前辈| | 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: }


使用特权

评论回复
12
mcuatmel|  楼主 | 2011-1-30 19:53 | 只看该作者
谢楼上!有时间我试下。
8楼:按你说的,20ms数码管显示一次,那是静态的吧,我的是5ms一次/位。
10楼:该用多少定时器得看情况,我一个定时器中断中处理过十几种任务,一般的程序我只用一个定时器,但遇特殊情况不能共用的也没办法,如果一个定时器能解决所有问题的话那现在的ARM处理器就没必要集成6个以上的定时器了。

使用特权

评论回复
13
zq1987731| | 2011-1-30 23:28 | 只看该作者
to mcuatmel:
20ms是单个8段码的情况,我只是按50Hz举例,这里不用说20ms,即使5ms甚至2.5ms,在定时器复用的前提下根本不算问题,ISR中只根据中断作标志位处理,其余一概在主循环中进行!!!这种情况下模拟出几十个定时器根本就是游刃有余。
另外ARM集成的大量定时器,建议LZ好好看看到底用在什么地方,顺便看看主流RTOS中的设计,思维就不会这么狭隘

使用特权

评论回复
14
fushaobing| | 2011-2-1 10:41 | 只看该作者
当然不成比例了。
看反汇编就知道是为什么了。比如j=0就没有包括在循环次数里。
要按比例延时,还得依靠示波器测试,对wtemp1的初值进行微调。

使用特权

评论回复
15
norman33| | 2011-2-1 15:47 | 只看该作者
同意4楼,正式工程上是不能有长时间死等的情况的,频繁开关中断会丢中断请求这对系统实时性是有很大影响的。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

512

主题

1456

帖子

2

粉丝