模板:自动重装和不自动重载区别
定时器中断方式:
跑一遍后溢出,TFx由硬件自动清零了,所以在中断服务函数中就不用多此一举中断标志位TFx=0了。
我们也不需要在中断服务函数里写TRx=1,因为中断一开启只要不另外暂停(TR0=0;),它本身就是像多线程一样一直在运行。
TMOD=0X01; 对模式的设置,中断服务函数里不用再写这句话了,这个在主函数一开始就设置了,再设置编译直接会报错,认为TMOD是个错误变量了。
定时器查询方式:
我们需要在查询方式延时函数里写TRx=1,因为查询方式跑一遍后,中断溢出标志位TFx等于1就停止了,停止就是TRx=0,所以我们要另外重新开启。并且TFx必须软件清零,所以在查询方式的延时函数中后面就得写TFx=0了。
而主函数中因为我们用的不是中断方式,所以就不需要写EA=1; ETx=1,TRx=1。
// ------------------------分 隔 符------------------------
自动重载:
定时器中断方式:
首先得在main函数中对初值THx和TLx赋值,即初始化(告诉CPU每多久中断一次)。在中断服务函数中不需要另外重新赋初值,因为它满了会自动重新装main函数配置好的初值。
查看代码
//定时器0初始化
void timer0_Init()
{
TMOD &= 0x0F; //设置定时器模式 00为16位自动重载 01为16位不自动重载
TH0 = 0xFC; //设置定时初始值:1毫秒
TL0 = 0x78;
ET0=1;
EA=1;
TR0=1; //上电开跑 启动定时中断
}
//定时器0中断服务函数
void timer0_Server()interrupt 3
{
//进入中断服务后执行的动作 一般建议不要太长,因为中断本来就是为了实时响应。如果代码语句超过本身中断时间,就一直困在中断了。
// e.g:我经常用定时器用来实时扫描按键的状态
keyProc(); //自己写的按键处理函数
}
//main
void main()
{
timer0_Init();
while(1)
{
//动作代码
}
}
定时查询方式:
不需要在main函数中对初值THx和TLx赋值,即初始化。直接在所用到的查询方式的延时函数中赋初值就好了,调用延时函数时候就装一次。
示例代码1:
查看代码
//定时器0初始化
void timer0_Init()
{
TMOD &= 0x0F; //设置定时器模式 00为16位自动重载 01为16位不自动重载
}
//延时函数:定时器0查询方式
void delayMs(unsigned int xms)
{
xms=xms/5; //减少外循环次数,增加程序运行效率
while(xms--)
{
TH0 = 0xEC; //设置定时初始值:5ms
TL0 = 0x78;
TR0=1; //溢出标志位为1后,TR也为0了,所以需要重新开启
while(!TF0); //到了5ms后 溢出标志位TF0就等于1
TF0=0; //所以为了下次又能调用 这里就要对溢出标志位清0
}
}
//main
void main()
{
timer0_Init();
while(1)
{
//动作代码
delayMs(); //调用延时函数
}
}
示例代码2:
查看代码
//延时函数:定时器0查询方式
void delayMs(unsigned int xms)
{
xms=xms/5; //减少外循环次数,增加程序运行效率
TMOD &= 0x0F; //设置定时器模式 00为16位自动重载 01为16位不自动重载
while(xms--)
{
TH0 = 0xEC; //设置定时初始值:5ms
TL0 = 0x78;
TR0=1; //溢出标志位为1后,TR也为0了,所以需要重新开启
while(!TF0); //到了5ms后 溢出标志位TF0就等于1
TF0=0; //所以为了下次又能调用 这里就要对溢出标志位清0
}
}
//main
void main()
{
while(1)
{
//动作代码
delayMs(); //调用延时函数
}
}
不自动重载:
定时器中断方式:
首先得在main函数中对初值THx和TLx赋值,即初始化。在中断服务函数中也需要另外重新赋初值,因为01不自动重载模式 它满了不会自动重新装main函数配置好的初值。
查看代码
//定时器0初始化
void timer0_Init()
{
TMOD &= 0x01; //设置定时器模式 00为16位自动重载 01为16位不自动重载
TH0 = 0xFC; //设置定时初始值:1毫秒
TL0 = 0x78;
ET0=1;
EA=1;
TR0=1; //上电开跑 启动定时中断
}
//定时器0中断服务函数
void timer0_Server()interrupt 3
{
TH0 = 0xFC; //设置定时初始值:1毫秒
TL0 = 0x78;
//进入中断服务后执行的动作 一般建议不要太长,因为中断本来就是为了实时响应。如果代码语句超过本身中断时间,就一直困在中断了。
// e.g:我经常用定时器用来实时扫描按键的状态
keyProc(); //自己写的按键处理函数
}
//main
void main()
{
timer0_Init();
while(1)
{
//动作代码
}
}
定时查询方式:
首先需要在main函数中对初值THx和TLx赋值,即初始化。然后直接在所用到的查询方式的延时函数中也是需要重新赋初值的,因为你一旦调用了一次,初值就没了。
示例代码1:
查看代码
//定时器0初始化
void timer0_Init()
{
TMOD &= 0x01; //设置定时器模式 00为16位自动重载 01为16位不自动重载
}
//延时函数:定时器0查询方式
void delayMs(unsigned int xms)
{
xms=xms/5; //减少外循环次数,增加程序运行效率
while(xms--)
{
TH0 = 0xEC; //设置定时初始值:5ms
TL0 = 0x78;
TR0=1; //溢出标志位为1后,TR也为0了,所以需要重新开启
while(!TF0); //到了5ms后 溢出标志位TF0就等于1
TF0=0; //所以为了下次又能调用 这里就要对溢出标志位清0
}
}
//main
void main()
{
timer0_Init();
while(1)
{
//动作代码
delayMs(); //调用延时函数
}
}
示例代码2:
查看代码
//延时函数:定时器0查询方式
void delayMs(unsigned int xms)
{
xms=xms/5; //减少外循环次数,增加程序运行效率
TMOD &= 0x01; //设置定时器模式 00为16位自动重载 01为16位不自动重载
while(xms--)
{
TH0 = 0xEC; //设置定时初始值:5ms
TL0 = 0x78;
TR0=1; //溢出标志位为1后,TR也为0了,所以需要重新开启
while(!TF0); //到了5ms后 溢出标志位TF0就等于1
TF0=0; //所以为了下次又能调用 这里就要对溢出标志位清0
}
}
//main
void main()
{
while(1)
{
//动作代码
delayMs(); //调用延时函数
}
}
作者QQ4577105