一、简述
记--通过代码方式实现软件延时(不精确延时)。
二、指令周期
单片机需要一个时钟信号送给内部各个电路,才能使它们有节拍地协同工作。时钟信号的频率是由外部震荡电路的晶振频率决定的。
外接晶振的频率 = 时钟信号的频率 = 工作频率。(如24MHz,12MHz,11.0592MHz)
震荡周期:为单片机提供时钟脉冲的振荡源的周期。
震荡周期 = 1/晶振频率 (如晶振频率是12MHz时,振荡周期 = 1/12MHz = (1/12)us)
机器周期:51系列单片机的一个机器周期由12个震荡周期组成。
机器周期 = 12 * 振荡周期
(如晶振频率是24MHz时,振荡周期 = 1/24MHz = (1/24)us,机器周期 = 12*(1/24)us = 0.5us)
(如晶振频率是12MHz时,振荡周期 = 1/12MHz = (1/12)us,机器周期 = 12*(1/12)us = 1us)
(如晶振频率是11.0592MHz时,振荡周期 = 1/12MHz = (1/11.0592)us,机器周期 = 12*(1/11.0592)us = 1.085us)
指令周期:单片机执行一条指令所用的时间。
一般来说,单片机执行1个简单的指令需要一个机器周期,执行复杂的指令需要两个机器周期。
三、软件延时
通过一个循环来实现延时
测试代码:
#include void delay(void)//延时函数 { unsigned char i; for(i=0; i<100; i++) ; } void main(void) { while(1) { //dosomething() delay(); } } 在Keil C51 环境下编译后,点击"调试"--"开始";在执行"视图"--"反汇编",可以看到延时函数对应的汇编代码。 其中: CLR指令消耗1个机器周期 MOV指令消耗1个机器周期 INC指令消耗1个机器周期 CJNE指令消耗2个机器周期 根据循环条件,INC指令和CJNE指令总共要执行100次(0x64=100),共消耗机器周期(1+2)*100=300, 加上CLR指令和MOV指令,循环程序总共消耗机器周期:1+1+300=302 如果单片机的晶振频率为11.0592MHz,则机器周期 = 12*(1/11.0592)us = 1.085us。 那么for循环程序耗时为302*1.085us=327.67us。 deley()函数用时:0.06607530s-0.000422209s=0.065653091s=65.653091ms=65653.091us (指令的执行时间不代表函数的执行时间。函数跳转需要时间,开辟函数栈、临时变量、回收栈资源等需要时间,因此c语言有内联(inline)函数,宏函数(带参宏)用来提高执行效率)。 两层循环 #include void delay(void)//延时函数 { unsigned char i, j; for(i=0; i<100; i++) for(j=0; j<200; j++) ; } void main(void) { while(1) { //dosomething() delay(); } } 注:对于C语言编译器,某些编译器会进行代码优化,比如循环里面什么都没做,编译器有可能将循环去掉。 软件延时不精准:因为相当于是通过控制CPU做某一些预定消耗一定时间的动作,根据CPU执行完成判断已经过去多长时间。但是CPU有可能在中途被其他进程强行占用(优先级高的进程),CPU被迫中断当前执行,优先执行优先级较高的任务,当执行完优先级较高的任务,才回来继续执行之前中断的任务,那么延时就会加长。比如想要延时1分钟,我们预定执行A动作之后,刚好耗时1分钟,那么让CPU执行这个动作就达到延时1分钟。如果当CPU执行到一半时,突然有一个紧急任务S(优先级高)发生,要求CPU立即处理,那么CPU就会中断当前任务A,优先处理紧急任务S,等待执行完毕,才回来继续执行之前被中断的任务A。那么当A任务执行完毕,我们预期是从执行开始到结束消耗时间1分钟,但是实际上已经过去不止1分钟,因为中途被中断了。所以软件延时时间越长,容易被中断,而且CPU不能长时间被一个进程独占,延时越不精准。 要实现精确的延时可使用硬件延时:使用定时器/计数器。定时器/计数器是根据时钟信号脉冲计数的,是直接跟硬件晶振相关的。 //函数名:delay_1ms(uint x) //功能:利用定时器0精确定时1ms //调用函数: //输入参数:x,1ms计数 //输出参数: //说明:延时的时间为1ms乘以x void delay_1ms(uint x) { TMOD=0X01;//开定时器0,工作方式为1 TR0=1;//启动定时器0; while(x--) { TH0=0Xfc;//定时1ms初值的高8位装入TH0 TL0=0X18;//定时1ms初值的低8位装入TL0 while(!TF0);//等待,直到TF0为1 TF0=0; //重置溢出位标志 } TR0=0;//停止定时器0; } 延时1s:delay_1ms(1000); //1000ms = 1s
上一篇:单片机 矩阵式按键
下一篇:一个简易的51单片机串口接收和发送程序
推荐阅读最新更新时间:2024-11-11 10:56
设计资源 培训 开发板 精华推荐
- LT1374-5、采用 SO-8 封装的高效率 500kHz、4.5A 降压转换器
- 使用 Analog Devices 的 LTC2862AIDD-2 的参考设计
- OP213ESZ-REEL精密比较器典型应用
- 具有 10A 断路器的 LTC4368HDD-1 24V 应用的典型应用电路
- AD8316ACP-EVAL,AD8316 评估板,0.1GHz 至 2.5GHz,70dB 对数检波器/控制器
- 高压双向电流检测放大器的评估套件
- 兼容野火挑战者F429V1开发板
- 多谐振荡闪烁灯
- 使用 Analog Devices 的 LT3693 的参考设计
- LTC2241CUP-12 演示板,CMOS 输出,VCC = 2.5V,210Msps,12 位,10MHz< AIN< 250MHz