找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3906|回复: 9
收起左侧

51单片机延时

[复制链接]
ID:208445 发表于 2017-6-28 10:46 | 显示全部楼层 |阅读模式
void delay(unsigned int n)
{
    while(n--);
}

void main()
{
   delay(10);       
}

delay(10)是延时多长时间的?在晶振是12M的情况下


我用KEIL 查,转成的汇编如下:

main 函数

C:0x0020    7F03     MOV      R7,#0x03
C:0x0022    7E00     MOV      R6,#0x00
C:0x0024    020003   LJMP     delay(C:0003)
C:0x0027    00       NOP      
C:0x0028    00       NOP   


     3: void delay(unsigned int n)
     4: {
     5:         while(n--);
C:0x000F    EF       MOV      A,R7
C:0x0010    1F       DEC      R7
C:0x0011    AC06     MOV      R4,0x06
C:0x0013    7001     JNZ      C:0016
C:0x0015    1E       DEC      R6
C:0x0016    4C       ORL      A,R4
C:0x0017    70F6     JNZ      delay(C:000F)
     6: }
     7:  
C:0x0019    22       RET      


从上述汇编中可以看到,n每次执行一遍,需要大概4条单周期指令+2条双周期指令,也就没每次延时 8μ秒
所以10次的话,那就是 8*10 + 4 + 2
其中4为函数参数入栈和跳转,2位函数返回。

问题
1)不知道这样理解对不对?
2)另外,不知道KEIL生产hex的时候,会不会对汇编再进行优化?
2)C:0x0011    AC06     MOV      R4,0x06 没看明白这条汇编有什么用,为什么将0x06放入R4,为什么是0x06,为什么是R4?
     C:0x0016    4C       ORL      A,R4. 这条也不明白,直接判断A是否为0不就得了,为什么还要与R4或呢?
     


回复

使用道具 举报

ID:207702 发表于 2017-6-28 13:04 来自手机 | 显示全部楼层
你简单问题复杂化,你用调试模式直接可以看大概延时多久有必要这样吗

评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:214628 发表于 2017-6-28 16:11 | 显示全部楼层
1)delay(10)是延时多长时间的,首先我可以告诉你,不知道。
为什么呢?那是因为在你的这个程序中,delay是做变量运算的,你的单片机是高速单片机,这个delay10就快,是低速单片机就慢。
所以它不是精确延时,只能说是模糊延时,想精确延时,就用定时器,这样可以算出来具体时间。
2)KEIL生产hex的时候,会不会对汇编再进行优化?这个问题keil只是对你的程序进行汇编,至于优化在51版本里,我没听说过,在MDK版本里我听说过。所以要看版本。
3)你的汇编我不太懂,建议你去看汇编语言这本书,里面有详细讲解。

评分

参与人数 1黑币 +60 收起 理由
admin + 60 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:7485 发表于 2017-6-28 16:59 | 显示全部楼层
keil转的汇编有些是真的很麻烦。
回复

使用道具 举报

ID:215268 发表于 2017-6-28 17:01 | 显示全部楼层
可能是编的程序不对
回复

使用道具 举报

ID:215559 发表于 2017-6-28 17:43 | 显示全部楼层
延时要根据晶振频率来计算,12M的晶振也即是时钟周期为83.3ns,然后再根据数据的读取延时来计算准确的延时时间。在单片机中,一个时钟节拍执行一条代码,执行10次也即是833ns,再根据板上布线延时,所以延时时间还会更长一些。但是在51中想要知道确切的延时的话,使用仿真芯片在Keil中进行仿真就可以了

评分

参与人数 1黑币 +50 收起 理由
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:215568 发表于 2017-6-28 18:01 | 显示全部楼层
//延时 void Delay(WORD n){              WORD x;          while(n--)           {      x=500;   while(x--);  }         }
回复

使用道具 举报

ID:208445 发表于 2017-6-29 10:40 | 显示全部楼层
梦孤城 发表于 2017-6-28 17:43
延时要根据晶振频率来计算,12M的晶振也即是时钟周期为83.3ns,然后再根据数据的读取延时来计算准确的延时 ...

嗯,12M晶振的话,对于C51来说,一个指令周期=一个机器周期=12个时钟周期,也就是1μs。加上些线的延时,可能稍微延长些。
回复

使用道具 举报

ID:208445 发表于 2017-6-29 10:47 | 显示全部楼层
zhczlzhang 发表于 2017-6-28 16:11
1)delay(10)是延时多长时间的,首先我可以告诉你,不知道。
为什么呢?那是因为在你的这个程序中,delay ...

我其实也没要求很精确,就一个模糊的值,就行。我再看吴鉴英C51开发板里面的DS18B20的代码,里面有很多关于时序的操作,要延时多长时间。

delay(5); 说是延时大概44us
delay(20); 说是延时大概140us
delay(80); 说是延时大概530us

我感觉每一个是6-9之间的样子,相差是不是有点大。我原以为应该在8-9之间。
回复

使用道具 举报

ID:123289 发表于 2017-6-30 01:18 | 显示全部楼层
关于“MOV      R4,0x06”
因为没有:MOV   R4, R6 这条指令,而0x06在CPU复位后,与R6是等价的。

关于“ORL      A,R4. 这条也不明白,直接判断A是否为0不就得了,为什么还要与R4或呢?”
因为:前面A取的是R7,如果直接判断A,就是看R7是否为0,“与R4或”之后,就是判断R7、R4同时为0。

C在编译时(转汇编)是很“蠢”的,不如自己写的爽。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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