历史上的今天
返回首页

历史上的今天

今天是:2025年06月16日(星期一)

正在发生

2020年06月16日 | 51单片机C语言延时函数怎么定义和使用

2020-06-16 来源:eefocus

    C语言定义延时函数主要通过无意义指令的执行来达到延时的目的。C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使用unsigned char作为延时变量。

  以某晶振为12MHz的单片机为例,晶振为12MHz即一个机器周期为1us。现在定义一个延时xms毫秒的延时函数。


 void delay(unsigned int xms) // xms代表需要延时的毫秒

      {

      unsigned int x,y;

      for(x=xms;x>=0;x--)

      for(y=110;y>=0;y--);

      }


1.51单片机C语言延时函数的使用

下面给出一些经典的延时函数,(1)500ms延时子程序如下:


void delay500ms(void)

{

  unsigned char i,j,k;

  for(i=15;i>=0;i--)

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

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

}


计算分析:程序共有三层循环,一层循环n:R52 = 812 = 162us DJNZ 2us;二层循环m:R6*(n+3) = 202165 = 33330us DJNZ 2us + R5赋值 1us = 3us;三层循环: R7(m+3) = 1533333 = 499995us DJNZ 2us + R6赋值 1us = 3us

循环外: 5us 子程序调用 2us + 子程序返回 2us + R7赋值 1us = 5us

延时总时间 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms

计算公式:延时时间=[(2R5+3)*R6+3]*R7+5

(2)200ms延时子程序:


void delay200ms(void)

{

  unsigned char i,j,k;

  for(i=5;i》0;i--)

  for(j=132;j》0;j--)

  for(k=150;k》0;k--);

}


(3)10ms延时子程序:


void delay10ms(void)

{

  unsigned char i,j,k;

  for(i=5;i》0;i--)

  for(j=4;j》0;j--)

  for(k=248;k》0;k--);

}


(4)1s延时子程序:


void delay1s(void)

{

  unsigned char h,i,j,k;

  for(h=5;h》0;h--)

  for(i=4;i》0;i--)

  for(j=116;j》0;j--)

  for(k=214;k》0;k--);

}


关于单片机C语言的精确延时,网上很多都是大约给出延时值没有准确那值是多少,也就没有达到精确高的要求,而本函数克服了以上缺点,能够精确计数出要延时值且精确达到1us,本举例所用CPU为STC12C5412系列12倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。

共有三条延时函数说明如下:

  函数调用分两级:一级是小于10US的延时,二级是大于10US的延时


//小于10US的【用1US级延时】


//----------微秒级延时---------


for(i=X;i》X;i–) 延时时间=(3+5*X)/12 提示(单位us, X不能大于255)


//======大于10US《小于21.9955Ms的可用【10US级延时函数】=


void Delay10us(uchar Ms)

{

  uchar data i;

  for(;Ms》0;Ms--)

  for(i=26;i》0;i--);

}


i=[(延时值-1.75)*12/Ms-15]/4

  如想延时60US则 i=[(60-1.75)*12/6-15]/4=25.375≈26; 修改i的值=26,再调用上面的【10US级延时函数】Delay10us(6); 则就精确延时60US;如果想延时64US可以用这二种函数组合来用: Delay10us(6); for(i=9;i》X;i–) 共延时64US

  关于单片机C语言的精确延时,网上很多都是大约给出延时值没有准确那值是多少,也就没有达到精确高的要求,而本函数克服了以上缺点,能够精确计数出要延时值且精确达到1us,本举例所用CPU为STC12C5412系列12倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。


共有三条延时函数说明如下:


函数调用分两级:一级是小于10US的延时,二级是大于10US的延时


//小于10US的【用1US级延时】


//----------微秒级延时---------


for(i=X;i》X;i–) 延时时间=(3+5*X)/12 提示(单位us, X不能大于255)


//======大于10US《小于21.9955Ms的可用【10US级延时函数】=


void Delay10us(uchar Ms)

{

  uchar data i;

  for(;Ms》0;Ms--)

  for(i=26;i》0;i--);

}


i=[(延时值-1.75)*12/Ms-15]/4

  如想延时60US则 i=[(60-1.75)*12/6-15]/4=25.375≈26; 修改i的值=26,再调用上面的【10US级延时函数】Delay10us(6); 则就精确延时60US;

  如果想延时64US可以用这二种函数组合来用: Delay10us(6); for(i=9;i》X;i–) 共延时64US

2.下面给出有关在C51中延时子程序设计时要注意的问题(一些经验之谈)


(1)、在C51中进行精确的延时子程序设计时,尽量不要或少在延时子程序中定义局部变量,所有的延时子程序中变量通过有参函数传递。

 (2)、在延时子程序设计时,采用do…while,结构做循环体要比for结构做循环体好。

 (3)、在延时子程序设计时,要进行循环体嵌套时,采用先内循环,再减减比先减减,再内循环要好。


一. 500ms延时子程序产生的汇编:


C:0x0800 7F0F MOV R7,#0x0F


  C:0x0802 7ECA MOV R6,#0xCA


  C:0x0804 7D51 MOV R5,#0x51


  C:0x0806 DDFE DJNZ R5,C:0806


  C:0x0808 DEFA DJNZ R6,C:0804


  C:0x080A DFF6 DJNZ R7,C:0802


  C:0x080C 22 RET


二.200ms延时子程序产生的汇编


C:0x0800 7F05 MOV R7,#0x05


  C:0x0802 7E84 MOV R6,#0x84


  C:0x0804 7D96 MOV R5,#0x96


  C:0x0806 DDFE DJNZ R5,C:0806


  C:0x0808 DEFA DJNZ R6,C:0804


  C:0x080A DFF6 DJNZ R7,C:0802


  C:0x080C 22 RET


三.10ms延时子程序产生的汇编:


C:0x0800 7F05 MOV R7,#0x05


  C:0x0802 7E04 MOV R6,#0x04


  C:0x0804 7DF8 MOV R5,#0xF8


  C:0x0806 DDFE DJNZ R5,C:0806


  C:0x0808 DEFA DJNZ R6,C:0804


  C:0x080A DFF6 DJNZ R7,C:0802


  C:0x080C 22 RET


四.1s延时子程序产生的汇编


C:0x0800 7F05 MOV R7,#0x05


  C:0x0802 7E04 MOV R6,#0x04


  C:0x0804 7D74 MOV R5,#0x74


  C:0x0806 7CD6 MOV R4,#0xD6


  C:0x0808 DCFE DJNZ R4,C:0808


  C:0x080A DDFA DJNZ R5,C:0806


  C:0x080C DEF6 DJNZ R6,C:0804


  C:0x080E DFF2 DJNZ R7,C:0802


  C:0x0810 22 RET


3.另外一些关于延时的例子

http://www.ceet.hbnu.edu.cn/bbs/viewthread.php?TId=3749,作者:小秋


晶振:12MHz


1:5~500us


void delay(unsigned char i)

{

  while(--i) ;

}


计算方法:ix2+5 可完成5~515us的延时


2:10us~2ms


void delay(unsigned char i)

{

  for( ;i》0 ;i--) ;

}


计算方法:ix8+10 可完成10us~2.050ms的延时


3:2ms~130ms


void delay(unsigned char i,unsigned char j)

{

  for( ;j》0 ;j--)

  for( ;i》0 ;i--) ;

}


计算方法:(ix2+3)xj+5 u


推荐阅读

史海拾趣

ADDtek公司的发展小趣事

对不起,我无法提供有关ADDtek公司发展的故事。

All Sensors公司的发展小趣事

All Sensors在传感器技术领域一直保持着世界领先的地位。公司掌握着核心的MEMS传感器技术,如独有的CoBeam2 TM传感器技术等。这些技术的应用使得All Sensors的传感器在精度、稳定性和寿命等方面都达到了行业领先水平。同时,公司还不断投入研发,推出更多创新产品,满足不断变化的市场需求。

Dolphin Interconnect Solutions Asa公司的发展小趣事

随着电子行业的快速发展和市场竞争的加剧,Dolphin Interconnect Solutions ASA面临着前所未有的挑战。为了应对这些挑战,公司积极调整战略方向,加大在人工智能、物联网等新兴领域的投入。同时,Dolphin还加强了与产业链上下游企业的合作,共同推动产业链的转型升级。这些努力使得Dolphin在激烈的市场竞争中保持了稳健的发展态势。

Digital公司的发展小趣事

DIALIGHT公司一直专注于工业LED照明领域的发展。他们深入了解工业空间照明的需求和挑战,设计了一系列专为工业应用而定制的LED照明产品。这些产品不仅易于安装和维护,而且能在恶劣的环境下持续使用。此外,DIALIGHT还提供集成系统解决方案,帮助客户降低能源成本、维护成本和碳足迹,同时提高设施的安全性和生产力。通过不断创新和优质服务,DIALIGHT在工业LED照明领域赢得了广泛的认可和信赖。

台湾凌通(Generalplus)公司的发展小趣事
连接线路接触不良或松动也可能导致指示灯闪烁。可检查连接线路是否牢固,无松动或接触不良的情况。
EPC公司的发展小趣事

最后一家EPC公司深知创新是企业发展的核心动力。公司注重研发投入和人才培养,建立了专业的研发团队和完善的研发体系。公司不断跟踪行业发展趋势和技术动态,积极引进新技术、新工艺和新材料,推动产品升级和产业升级。同时,公司注重创新成果的转化和应用,将新技术、新工艺和新材料应用于实际项目中,提高了项目的竞争力和附加值。通过持续的创新和积累,公司逐渐在电子行业中形成了独特的技术优势和核心竞争力。

请注意,以上故事仅为框架性描述,并未包含具体的公司名称、项目细节和具体数字。您可以根据这些框架性描述进一步深入了解相关公司的发展情况,并结合实际案例进行具体分析和撰写。

问答坊 | AI 解惑

既然STM32如此名声鹊起--不得不看看STM32 Primer

既然STM32如此名声鹊起--不得不看看STM32 Primer    编号: 1475040 类型:菜鸟提问 作者:geyin    时间:2009-4-11 10:45:26     访问次数:0 发贴IP:221.232.138.131 投票加精0      & ...…

查看全部问答>

雪天跪地求助:朋友们谁了解ip通信的都进来说说

我们公司100多人,要把目前使用的传统电话系统换成ip的。调研了很多,思科和Avaya东西是不错,可是老板批的钱有限,受用不起,国内一些小厂商的东西又担心稳定性太低。近期朋友推荐一款据说整体性价比还可以的美国捷思锐的中小企业语音通信系统,已 ...…

查看全部问答>

关于ALTIUM DESIGNER 标题框的问题。

更改标题框中TITLE的VALUE值为sd,但是确认后,TITLE未发生任何改变。…

查看全部问答>

CAN总线接口电路的硬件设计

CAN总线接口电路的硬件设计…

查看全部问答>

远程更新操作系统

    谁做过远程更新WINCE操作系统这方面的,这个大致怎样实现,有哪些方式?…

查看全部问答>

新手,串口输出问题,请各位大侠拔刀相助一下

//************************************************************************* //                               串口通信 //环境:C805 ...…

查看全部问答>

*** 请问如何选择 PMOS 的Vgs参数? ***

  我想开关一些设备的供电电源, PCB板画好了, 负载在正极. (原本用可控硅关断接地). 锂电池: 输入电压3.2~4.2; 是个变化的过程, 我要用IO口控制PMOS, 低电平打开, 高电平断开; 这个IO口高电平是3.3v, 低电平0v.  请问我该选择 ...…

查看全部问答>

了解一些锂离子电池寿命的充电和放电的方法

人们一直非常重视提高锂离子电池的容量,以期以物理尺寸最小的电池实现最长的产品工作时间。但是在有些应用中,较长的电池寿命、较多的充电次数或较安全的电池比电池容量更重要。本文介绍几种可以极大延长电池寿命的锂离子电池充电和放电方法。几乎 ...…

查看全部问答>

【深度评测STM32 Nucleo】+st-link utility工具试用

本帖最后由 fyaocn 于 2014-12-15 11:11 编辑 进一步的测试中,从网上搜到了很多适用的工具,其中最傻瓜的就是这个ST-LINK GUI Utility了。把程序下载的板子,可以直接查看到内存的数据,更牛的是可以直接修改,包括运行的中间数据。 STM提供了 ...…

查看全部问答>