c语言的单片机delay延时函数详解

本文详细介绍了在C语言嵌入式开发中如何使用循环和定时器进行延时,包括基本的循环延时函数实现、时钟周期计算,以及如何利用定时器实现更高效的长延时处理。涵盖延时需求的场景如按键处理、IO防抖和任务调度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环境

开发环境:NY-IDE
单片机 :NY8B062D

延时函数

延时函数,作为一种常用函数,在不同的领域有不同的用处。而在嵌入式以及C语言的编写中,我们常常遇到需要自己来编写延时函数的情况,这种情况之下,了解其原理就显得必要。

一、是什么

简单来说,延时函数的目的就在于等,实际上就是要等一段时间再来执行接下来的代码。而这种简单的等,又可以采用多种方法来实现。例如:

名称描述
循环采用for或者while循环,让计算机跑无用的代码,从而达到延时的目的
定时器通过定时器的计时功能,来达到延时的目的
系统调用该功能其实还是通过以上的两种方式来实现,当时这种功能出现在有系统的程序里面,执行系统延时的情况下,单片机可以去执行别的函数,直到系统时间到,从而回来接着执行该代码,这实际上也提高了效率

二、为什么

为什么要延时?
我们有时候要等,但是又不能等太久。这就是延时函数的作用。简单来说,就是和上课铃一样,上课要上45分钟,我们就要延时。

三、用在哪里?

  1. 按键、io防抖动
  2. 计时
  3. 任务调度

四、怎么做

1、循环延时

首先我认为,要搞懂的东西就是几个周期的区别,这一篇文章有明确的介绍
链接: 关于时钟,指令,机器周期的详解

搞懂了周期的概念之后,来看看函数,这就是一个典型的例子

//延时函数
void delay(int count)
{
	int i;
	for(i=1;i<=count;i++)
	;
}

计算公式

时钟周期 = 1/时钟频率
机器周期 = 完成一个基本操作所需要的时间 = 时钟周期*n(n取决于单片的不同而不同)
指令周期 = 完成一次指令所需的时间           = 一或者两个机器周期 

而我们的计算公式则是:
(count(次数)*指令周期所需的时钟周期数(例如c51就是12)*循环中的指令数)/时钟频率

例如:

时钟频率:8Mhz
机器周期:2个时钟周期
指令周期:6个机器周期 = 12个时钟周期

delay(50);
void delay(int count)
{
	int i;
	for(i=1;i<=count;i++)
	;
}

延时 = (1/8M)*12*50*2(计数)  =  0.000075 s= 75us

链接: for循环详解.

2、定时器延时

有些时候,特别是当延时时间比较长的时候,for循环就显得十分的不现实了,这时候定时器就显得十分重要了。实际上,我们换个模式来思考问题,定时器就是一个可以自己跑的for循环。
思路:我们设置好一个定时器的循环时间,然后每次循环完成标志位加一,然后在自己的任务里面,判断标志位的大小,当数据达到的时候,就来处理对应的事件,这有利于单片机效率的提高

初始化定时器:

/****************************************************************************
* 函数名   : user_timer1_init()
* 功  能   : 初始化timer1定时器
* 输 入    : 
* 全局变量 : 
* 输    出 : 
*****************************************************************************/
void user_timer1_init(void)
{
	//;Initial Timer1	
	TMRH = 0;
	TMR1 = 0xFF;								// Load 0xFF to TMR1 (Initial Timer1 register)
	T1CR1 = C_TMR1_Reload | C_TMR1_En;      	// Enable Timer1, Initial value reloaded from TMR1, Non-stop mode 
	T1CR2 = C_TMR1_ClkSrc_Inst | C_PS1_Div256;	// Enable Prescaler1, Prescaler1 dividing rate = 1:256, Timer1 clock source is instruction clock
	
	//;Setting Interrupt Enable Register	
	INTE = C_INT_TMR1;							// Enable Timer1
	ENI();										// Enable all unmasked interrupts			
}

中断中设置事件
/****************************************************************************
* 函数名   : __interrupt()
* 功  能   : 中断函数
* 输 入    : 
* 全局变量 : 
* 输    出 : 
*****************************************************************************/
void _isr(void) __interrupt(0)
{
	static unsigned int timer_count   = 0;//作计数使用
	
	/*timer1 中断函数*/
	if(INTFbits.T0IF)
	{
		if(timer_count <32)
		{
			timer_count++;
		}
		else if(timer_count == 32)
		{
			delay_10s = 1;	//延时十秒成功
			timer_count=0;
		}
		INTF= (unsigned char)~(C_INT_TMR0);	// Clear T0IF
	}
}
最后在while里面处理

   while(1)
    {
    	if(delay_10s  == 1)
    	{
    	/*这里就表示我们延时十秒成功了*/
		}
    }

根据引用\[1\]和引用\[3\]中的代码,可以编写一个简单的c51延时函数delay。以下是一个示例代码: ```c #define uchar unsigned char #define uint unsigned int #define ulong unsigned long // 延时10*n微秒 void delay_10us(unsigned int n) { unsigned char i; i = 2 * n; while (--i); } // 延时n毫秒 void delay_ms(unsigned int n) { unsigned int i, y; for (i = n; i > 0; i--) { for (y = 114; y > 0; y--); } } ``` 这个延时函数可以根据需要进行调整,根据引用\[1\]中的晶振频率为11.0592MHz,可以使用delay_10us函数来实现微秒级的延时,使用delay_ms函数来实现毫秒级的延时。你可以根据自己的需求来调整延时的时间。 #### 引用[.reference_title] - *1* *2* [c51简单delay函数,不同类型同值字符的延时时间不同](https://blog.csdn.net/m0_49624386/article/details/113835095)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【代码收藏夹 · C51】51单片机延时函数](https://blog.csdn.net/qq_34802028/article/details/126887333)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值