delayms(1)延时不对

[复制链接]
353|26
 楼主 | 2019-3-14 14:54 | 显示全部楼层 |阅读模式

/**********************************************************
延时函数
**********************************************************/
void delayms(unsigned int ms)
{
unsigned char k;
while(ms--)
{
for(k = 0; k < 114; k++);
}
}

请问:delayms(1)怎么是延时了1ms呢?不应该是2*114us么?
| 2019-3-14 14:57 | 显示全部楼层
你可以在keil中去调试,就能看出延时时间

使用道具

评论回复
| 2019-3-14 15:00 | 显示全部楼层
这种延时只是粗略的延时 更好的方式可以采用库函数来延时

使用道具

评论回复
 楼主 | 2019-3-14 15:03 | 显示全部楼层
晶振是12M的
一条for语句执行时间是2微秒,114次不应该是228微秒么?
但实际执行后确实1000微秒
为什么呢?

使用道具

评论回复
| 2019-3-14 15:06 | 显示全部楼层

...这还要看你晶振多少啊,这延时只是个大概啊。要准确延时就用定时器

使用道具

评论回复
 楼主 | 2019-3-14 15:08 | 显示全部楼层

keil软件中能看到单条语句执行的时间么?
我原来用的万利的仿真器,很方便,可以看到单条语句执行的时间
在keil中能看到单条语句的执行时间么?

使用道具

评论回复
| 2019-3-14 15:12 | 显示全部楼层
你在keil中进行调试就知道怎么延时了:
   将你的延时程序改成如下

        在keil中利用视图中的反汇编,会出现如下:
         其中的汇编CLR指令,MOV,INC都是消耗一个机器周期,CJNE是两个机器周期,根据循环条件,第三行和第四行要执行114次,所以此延时程序消耗的机器周期数为
         N=1+1+(1+2)*114;由此可以推出语句(for(k = 0; k < n; k++);)所消耗的机器周期数为N=3*n+2,近似于N=3*n;
         二重循环时:for(k = 0; k < m; k++);
                       for(k = 0; k < n; k++);
         所消耗的机器周期数近似:N=3*m*n;当单片机的晶振频率为12M时,机器周期就是1Us所以你要延时多少时间直接用以上公式算就行,如m=100,n=200时,就延时了60000us,即60ms'

使用道具

评论回复
| 2019-3-14 15:15 | 显示全部楼层

你在keil中进行调试就知道怎么延时了:
将你的延时程序改成如下

使用道具

评论回复
| 2019-3-14 15:18 | 显示全部楼层
127635c8a0043a3ec1.png

使用道具

评论回复
 楼主 | 2019-3-14 15:21 | 显示全部楼层

还有吗

使用道具

评论回复
| 2019-3-14 15:25 | 显示全部楼层

在keil中利用视图中的反汇编,会出现如下:




其中的汇编CLR指令,MOV,INC都是消耗一个机器周期,CJNE是两个机器周期,根据循环条件,第三行和第四行要执行114次,所以此延时程序消耗的机器周期数为

N=1+1+(1+2)*114;由此可以推出语句(for(k = 0; k < n; k++);)所消耗的机器周期数为N=3*n+2,近似于N=3*n;

二重循环时:for(k = 0; k < m; k++);

for(k = 0; k < n; k++);

所消耗的机器周期数近似:N=3*m*n;当单片机的晶振频率为12M时,机器周期就是1Us所以你要延时多少时间直接用以上公式算就行,如m=100,n=200时,就延时了60000us,即60ms'

使用道具

评论回复
| 2019-3-14 15:28 | 显示全部楼层
496335c8a02992f144.png

使用道具

评论回复
 楼主 | 2019-3-14 15:32 | 显示全部楼层

请看一下这个小的延时函数
/*************延时函数*************/

void delay(void)
{
  unsigned char i,j,k;

  for(k=10;k>0;k--)

  for(j=10;j>0;j--)

  for(i=100;i>0;i--);
}

//注:1、延时时间大约为i*j*k*2us。
//    2、i取值越大,k取值越小时间越准。
//    3、晶振为12M。

这是我当时实践过的,误差不是很大
但如果像你的公式好像就差的太大了

使用道具

评论回复
| 2019-3-14 15:36 | 显示全部楼层

/**********************************************************
   延时函数
**********************************************************/
void delayms(unsigned int ms)
{
   unsigned char k;
   while(ms--)
   {
     for(k = 0; k < 114; k++);
   }
}

给大家推荐这个简单实用的延时函数
delay(1)确实是延时1ms,但是却算不来怎么得来的
,根据南湖游子的公式应该是3*114+2=344us

使用道具

评论回复
| 2019-3-14 15:38 | 显示全部楼层
看keil反汇编代码计算吧

使用道具

评论回复
| 2019-3-14 15:41 | 显示全部楼层
晶振是12M的
一条for语句执行时间是2微秒,这个是有问题的
实际上这种软件延时一般都是不精确的
精确的话建议用计时器

使用道具

评论回复
| 2019-3-14 15:44 | 显示全部楼层
编译成汇编代码后对应的条数并不是2,你可以看一下Keil编译后生成的汇编代码数一下.

使用道具

评论回复
| 2019-3-14 15:47 | 显示全部楼层

给出的例子汇编是u8类型的,LZ你的是u16类型的,要麻烦些,看反汇编吧,上面有思路

使用道具

评论回复
| 2019-3-14 15:52 | 显示全部楼层

我一般都是用定时器或者SYSTICK来做延时。用死循环延时不仅耗费资源而且不准确

使用道具

评论回复
| 2019-3-14 15:55 | 显示全部楼层
这个要看晶振,如果不是原来频率的晶振,就不会是1ms

使用道具

评论回复
扫描二维码,随时随地手机跟帖
您需要登录后才可以回帖 登录 | 注册

本版积分规则

我要发帖 投诉建议 创建版块 申请版主

快速回复

您需要登录后才可以回帖
登录 | 注册
高级模式

论坛热帖

快速回复 返回顶部 返回列表