1.定时器与延时的区别
大家可能会觉得我们用延时函数照样可以实现上一讲代码的实验现象,但是定时器与延时的概念不同,延时函数需要占用CPU的使用权,正在延时的时候其他任务没有CPU的使用权就会拖慢执行效率。
而定时器是不需要占用CPU的使用权的,它是独立自己运行的,就像我们在第一讲的时候提到调好5分钟的闹钟,在这5分钟里我们可以随意执行任务,也可以什么事都不做,但是5分钟过后闹钟响了就要执行相关的任务了。
所以上一讲的代码的实现原理就是每隔51微秒,有个变量会自加1,过了1000个51微秒的时候LED的状态才会改变,可以说CPU在51ms的时间里基本没什么事做,只是在51微秒到了的时候做了“cnt++;”这样简单的任务,然后又空闲地等下一个51微秒的到来再执行“cnt++;”。
2.定时器中断函数
与外部中断一样,定时器中断也有中断函数,同理,程序去执行中断函数就会把TF0的中断标志位自动清0,所以只要我们用了定时器中断函数,那么TF0就可以不用再出现在程序书写中了。
还记得外部中断这个图吗
同样定时器0的中断函数使能如下
至于“interrupt”后面的数字为什么是1,请再看我们以前给过大家的这个图的中断函数编号就明白了
这些编号是为了区分哪些硬件资源的相关中断函数,如果我们同时使用两个定时器,那么只能用“interrupt
1”和“interrupt 3”来区分谁是谁的中断函数了。
使用“TIM0_IRQHandler”作为函数名也是模仿STM32定时器中断函数名的写法。
如果我们使用的是工作模式1,每次触发中断函数的执行内容首先就是再次给TH0和TL0赋初值保证下次的定时时间还是一样。
这里我们使用中断函数的执行方式来实现30ms的间隔流水灯,算出TH0和TL0合成的“16位的变量”要填充的值为37888=0x9400。
在中断函数里也是可以定义局部变量的,当然如果这个变量是用来辅助流水灯的,那么肯定是要定义成静态变量的。
3.代码
#include <reg52.h>
#include <function.h>//详见第六章第8讲
void main()
{
LED_Init();
EA = 1;
TMOD = 0x01;
TH0 = 0x94;
TL0 = 0x00;
ET0 = 1;
TR0 = 1;
while (1);
}
void TIM0_IRQHandler() interrupt 1
{
static u8 i;
TH0 = 0x94;
TL0 = 0x00;
P0=~(0x80>>i);
i++;
if (i>=8)i=0;
}
|
觉得30ms的流速太快,想改为300ms的话,修改一下中断函数即可,如下
void TIM0_IRQHandler() interrupt 1
{
static u8 i,cnt;
TH0 = 0x94;
TL0 = 0x00;
cnt++;
if (cnt>=10)
{
cnt=0;
P0=~(0x80>>i);
i++;
if (i>=8)i=0;
}
}
|
|