在总结延时函数前,有必要先说明一下:
机器周期在使用12M晶振时是1us;在使用11.0592M晶振时是1.09us。
1、1us的延时函数
想要准确延时1us,直接使用一个空指令就能实现。
2、当我们想要准确延时几十微秒以上的时间时,推荐使用软件延时。
例如以下程序:
void Delay_us(unsigned char us)
{
while(us--);
}
这个程序的工作过程:
1、 如果不执行while(us--); (也就是当us = 0时),这个函数一共需要14us的时间;
2、而 while(us--); 每执行一次消耗约6us的时间。
经过示波器测量后,确定这个函数任意us值的延时都是非常准确的。
2、当我们想要准确延时1ms及以上,推荐使用定时器进行延时。
使用定时器进行延时涉及定时器的知识,网上也有很文章讲的很详细,这里就不细说。
3、最后放上我使用示波器校正后的延时程序 “Delay.c” 。
#include <reg52.h>
#include "Delay.h"
/**
* 函数名称: Timer0_Init
*
* 功能说明: 定时器0的初始化
*
* 参数说明: 无
*
* 函数返回: 无
*/
void Timer0_Init()
{
TMOD &= 0xF0; // 清除定时器0工作模式配置(保留定时器1工作模式配置)
TMOD |= 0x01; // 配置定时器0工作模式1(16位定时器模式)
TF0 = 0; // 清除溢出中断标志位
TR0 = 0; // 停止定时器
}
/**
* 函数名称: Delay_us(14us - 1ms)
*
* 功能说明: 1、 最低延时14us(当us=0时);
* 2、 us加1,则延时增加6us;
* 3、 最高延时1ms
* 4、 误差为0
*
* 参数说明: us - 要延时的微秒数
*
* 函数返回: 无
*/
void Delay_us(unsigned char us)
{
while(us--);
}
/**
* 函数名称: Delay_ms(1ms - 1min)
*
* 功能说明: 1、 最低延时1ms(当ms=1时);
* 2、 ms加1,则延时增加1ms;
* 3、 最高延时1分钟
* 4、 ms越大,误差越大. ms = 1 时误差为0,延时1分钟时误差为3%
*
* 参数说明: ms - 要延时的毫秒数
*
* 函数返回: 无
*/
void Delay_ms(unsigned int ms)
{
/* 循环一次则完成一次1ms的延时 */
while(ms--)
{
/* 设置定时器初值 */
/* 40是示波器修正值 */
TH0 = (65536-1000+40) >> 8; // 定时器初值高字节
TL0 = (65536-1000+40) & 0xFF; // 定时器初值低字节
/* 启动定时器 */
TR0 = 1;
/* 等待定时器溢出 */
while (TF0 == 0); // 等待定时器溢出标志位被置位
/* 关闭定时器 */
TR0 = 0;
TF0 = 0; // 清除溢出标志
}
}
在主程序对定时器0进行初始化 Timer0_Init() 后,就能直接使用Delay_ms()
对于几微秒的延时,推荐直接使用空指令就可以了
以上都是基于12M晶振下进行校准的,用于11.0592M晶振的延时误差也很小,11.0592M晶振1ms延时误差大约在0.1ms以内。
当然使用这样的延时会有程序死等的弊端,有更好的设计希望大家指导一下。
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_48786435/article/details/144208524
|