打印

关于延迟函数的一些问题

[复制链接]
3446|13
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
sonjs|  楼主 | 2012-7-31 18:58 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
小生对51单片机刚入门,过程中对延迟函数感到比较困惑,下面附上例说C51一书中的一个小程序

//==声明区=============================
#include        <reg51.h>        //        定义8x51暂存器的标头档,P2-17~19
#define        LED        P1                        //        定义LED接至Port 1
void delay1ms(int);                //        声明延迟函数
void left(int);                        //        声明单灯左移函数
//==主程序===================================
main()                                        //        主程序开始
{        IE=0x81;                        //        准许INT 0中断(6-4页)
        LED=0x00;                        //        初值=0000 0000,灯全亮       
        while(1)                        //        无穷循环,程序一直跑
        {        delay1ms(250);        //        延迟250*1m=0.25s
                LED=~LED;                //        LED反相
        }                                        //        while循环结束
}                                                //        主程序结束
//==子程序===================================
/* INT 0的中断子程序 - 单灯左移3圈 */
void my_int0(void) interrupt 0        //        INT0 中断子程序开始
{        unsigned saveLED=LED;        //        储存中断前LED状态
        left(3);                        //        单灯左移3圈
        LED=saveLED;                //        写回中断前LED状态
}                                                //        结束INT0 中断子程序
/* 延迟函数,延迟约x 1ms */
void delay1ms(int x)        //        延迟函数开始
{        int i,j;                        //        声明整数变数i,j
        for (i=0;i<x;i++)        //        计数x次,延迟x 1ms
                for (j=0;j<120;j++);        //        计数120次,延迟1ms
}                                                //        延迟函数结束
/* 单灯左移函数,执行x圈 */
void left(int x)                 //        单灯左移函数开始
{        int i, j;                        //        声明变数i,j
        for(i=0;i<x;i++)        //        i循环,执行x圈
        {        LED=0xfe;                //        初始状态=1111 1110,最右灯亮
                for(j=0;j<7;j++)//        j循环,左移7次
                {        delay1ms(250);        //        延迟250*1m=0.25s
                        LED=(LED<<1)|0x01;         //        左移1位後,LSB设为1
                }                                //        j循环结束
                delay1ms(250);        //        延迟250*1m=0.25s
        }                                        //        i循环结束*/
}                                         //        单灯左移函数结束
不明白的是for (j=0;j<120;j++)这句为什么 计数120次就延迟1ms?感觉最中心的问题在于这个时间单位,即for (j=0;j<120;j++)计数一次是多少时间?
实在困惑,望高手给予指点

相关帖子

沙发
sonjs|  楼主 | 2012-7-31 19:11 | 只看该作者
有关延迟函数的另一个困惑是这样的
#include<reg51.h>
#define uint unsigned int
sbit D1=P1^0;
void delay(int);
void main()
{
        D1=0;
        delay(10);
        D1=1;
        delay(10);
}
void delay(int z)
{       
        unsigned int x,y;
        for(x=z;x>0;x--)
        for(y=120;y>0;y--);
}
这段代码实现的功能大致是这样的,一个LED灯间隔一定的时间闪烁。如果对程序进行如下修改能否实现同样的功能?
#include<reg51.h>
#define uint unsigned int
sbit D1=P1^0;
void delay(int);
void main()
{
D1=0;
delay(120);
D1=1;
delay(120);
}
void delay(int z)
{       
unsigned int x,y;
for(x=10;x>0;x--)
for(y=120;y>0;y--);
}
就是这两段代码的延迟时间是一致的吗?为什么?求救…

使用特权

评论回复
板凳
sinonion| | 2012-7-31 19:17 | 只看该作者
翻IO,示波器卡波形!

使用特权

评论回复
地板
原野之狼| | 2012-7-31 19:42 | 只看该作者
能够能软仿真 那么仿真一下就知道多少个周期了
或者拿示波器来看
或者看汇编代码后估算

使用特权

评论回复
5
NE5532| | 2012-7-31 20:31 | 只看该作者
因为指令运行消耗了时间,所以起到延时的目的,C语言因为有编译器在,很难说清翻译成了多少句汇编,示波器直接看运行时间是王道。

使用特权

评论回复
6
shell.albert| | 2012-7-31 20:34 | 只看该作者
CPU执行指令是需要时间的,叫做指令周期。
如SUB减法可能是2个指令周期,JMP跳转可能是3个指令周期,(可能噢,具体得查手册)
你写的C程序会被翻译成汇编语言,你看一下汇编语言。
再计算一下汇编语言中使用的助记符,每一个助记符的指令周期,加起来就行了。

书上的也不是很准,LED这种程序,并不多能闪闪,看到结果就行。

使用特权

评论回复
7
wukunshan| | 2012-7-31 21:28 | 只看该作者
这个问题也来问?楼主是不是没有学过C语言?买一本C语言的书来看,就很明白了。

使用特权

评论回复
8
qiujiahongde| | 2012-8-1 08:32 | 只看该作者
这个问题也来问?楼主是不是没有学过C语言?买一本C语言的书来看,就很明白了。
wukunshan 发表于 2012-7-31 21:28

在批评人家之前请考虑好,别误导人家,延迟多少时间最终是看编译器汇编之后的代码。

使用特权

评论回复
9
ayb_ice| | 2012-8-1 09:08 | 只看该作者
利用指令延时的函数,核心还是用汇编写有保证些

使用特权

评论回复
10
frlop| | 2012-8-1 09:18 | 只看该作者
在批评人家之前请考虑好,别误导人家,延迟多少时间最终是看编译器汇编之后的代码。
qiujiahongde 发表于 2012-8-1 08:32

正解。

使用特权

评论回复
11
misra| | 2012-8-1 10:08 | 只看该作者
楼主大侠  莫愁。我也是搞了很久太晓得 这个软件延时是个咋回事。
软件延时一般是不咋准确的,都是自己凑出来的。 另外 在不同的单片机下,相同的函数 延时的时间是不一样的。一定要注意。
另外 不同的优化级别也是不一样的。  所以可以通过伪指令 把优化级别把延时函数给限制住。

延时函数有时候还是用的上的,不过像楼主觉得例子里面那种过于随便的用延时,不值得提倡。当然练习用  令当别论。

另外  还是用定时器来模拟软件延时比较好一点。
弄个一秒的定时器

在定时器终端服务程序里面写上

        if (TimingDelay != 0x00) {
                TimingDelay--;
        }


然后再写个函数
void Delay(__IO INT16U nTime)
{
  TimingDelay = nTime;

  while(TimingDelay != 0);
}

然后就可以调用这个函数了。
我见过还ST  ATMEL  不少官方代码 都这样写的  可以考虑

希望楼主基础打好 。。。。。。。。

使用特权

评论回复
12
有意思| | 2012-8-1 10:42 | 只看该作者
要比较精确的延时
void delay()
{
  //初始化定时器
//等待定时器计数器完成
}
这样的思想应该比较精确

使用特权

评论回复
13
sonjs|  楼主 | 2012-8-1 15:47 | 只看该作者
确实基础不好,我会努力的,谢谢 7# wukunshan

使用特权

评论回复
14
sonjs|  楼主 | 2012-8-1 15:48 | 只看该作者
看到大家这么热心的对待一个初学者,我很感动,谢谢大家

使用特权

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

本版积分规则

0

主题

44

帖子

0

粉丝