蓝桥杯单片机定时器中断的使用方法详解
目录
配置定时器中断
用定时器定时1ms
用定时器中断来刷新数码管并显示count
用定时器中断写一个时钟
总结
配置定时器中断
新建工程后首先添加头文件,撰写main主函数
主循环前关闭所有外设
在STC烧录软件中配置定时1ms的定时器1,定时器模式为16位自动重载,时钟模式为1T,频率为12MHz,复制代码
在主函数前粘贴定时器1初始化函数,并使能定时器中断,开启定时器中断(ET1=1;EA=1;)
再将定时器1初始化函数名添加到主循环前,初始化定时器1并开启中断
最后配置定时器中断服务函数,定时器1的中断号为3
用定时器定时1ms
配置好定时器中断后,便可以实现精确定时完成一些功能
比如设置一个无符号整形的全局变量count,使count每1s加一次
1s=1000ms,所以用1ms的定时器要想实现定时1s,就需要定时器计数1000次
于是需要再定义一个无符号整形的全局变量time_1s,使time_1s在中断函数中每1ms加一次,当time_1s从0加到1000次即定时到1000ms时使time_1s归0,此时使count加一;time_1ms重新从0加到1000归0,count再次加一;如此往复便实现了count每秒加一
用定时器中断来刷新数码管并显示count
首先定义一个无符号char形全局变量time_8ms来定时刷新数码管和数组变量SMG[8]来储存数码管段选码(8位数码管8个段选)
接着从STC烧录器中范例程序将数码管标准字库复制粘贴下来
然后定义数码管刷新的函数
要想实现动态数码管的刷新,就要在很短的时间内不断刷新数码管,此时可以利用定时器中断每8ms刷新一次数码管
利用time_8ms在定时器中断中定时8ms归0,不断调用数码管刷新函数来实现每8ms刷新一次数码管8个位和8个段
例如:
当time_8ms=0时,调用数码管刷新函数smg(0,SMG[0]);
当time_8ms=1时,调用数码管刷新函数smg(1,SMG[1]);
当time_8ms=2时,调用数码管刷新函数smg(2,SMG[2]);
当time_8ms=3时,调用数码管刷新函数smg(3,SMG[3]);
……
当time_8ms=7时,调用数码管刷新函数smg(7,SMG[7]);
当time_8ms=8时time_8ms回到0;
0-7为8位数码管位选和段选
(使数码管显示两位数count,令count加到99后归0)
最后使写出数码管显示count的函数,令数码管后两位显示count
将此函数放到主函数循环中
效果展示
用定时器中断写一个时钟
现在你已经学会了用定时器使一个整形变量每秒加一并在数码管上显示,于是便可以进一步制作一个显示时分秒的时钟
首先定义三个无符号整形的全局变量shi,fen,miao用来在数码管上显示时分秒,分和秒都是60进制,时是24进制;于是我们只需要利用定时器计时一秒钟,使miao每秒加一,当加到60的时候miao归0,此时fen加一,当分加到60的时候fen归0,此时shi加一,当shi加到24的时候shi归0;
如此便形成了一个24小时制的时钟(初始值设置shi=23,fen=59,miao=56方便观察)
效果展示
总结
现在你已经学会了最基本的定时器用法,可以使用定时器中断实现更多想要实现的功能;比如利用定时器中断来实现延时,会比delay软件延时好得多,不会干扰到主函数;也可以使用多个定时器,比如写一个呼吸灯,利用定时器1定时1ms来计时和刷新数码管,利用定时器0定时100us来完成pwm输出……
代码开源
#include <STC15F2K60S2.H>
unsigned char time_8ms,SMG[8];
unsigned int time_1s,count;
unsigned int shi=23,fen=59,miao=56;
unsigned char code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black - H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
unsigned char code t_com[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
void smg(unsigned char wei,duan)
{
P0=0xFF; //消影
P2=0xC0;P0=t_com[wei];P2=0x00; //数码管位选
P2=0xE0;P0=~t_display[duan];P2=0x00; //数码管段选
}
void Timer1_Init(void) //1毫秒@12.000MHz
{
AUXR |= 0x40; //定时器时钟1T模式
TMOD &= 0x0F; //设置定时器模式
TL1 = 0x20; //设置定时初始值
TH1 = 0xD1; //设置定时初始值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1; //使能定时器1中断
EA = 1; //开启定时器中断
}
void count_display(void)
{
SMG[0]=16; //数码管标准字库中16为0x00即熄灭数码管
SMG[1]=16;
SMG[2]=16;
SMG[3]=16;
SMG[4]=16;
SMG[5]=16;
SMG[6]=count/10; //显示count的十位数
SMG[7]=count%10; //显示count的个位数
}
void time_display(void)
{
SMG[0]=shi/10; //显示shi的十位数
SMG[1]=shi%10; //显示shi的个位数
SMG[2]=17; //显示-
SMG[3]=fen/10; //显示fen的十位数
SMG[4]=fen%10; //显示fen的个位数
SMG[5]=17; //显示-
SMG[6]=miao/10; //显示miao的十位数
SMG[7]=miao%10; //显示miao的个位数
}
int main(void)
{
P2=0x80;P0=0xFF;P2=0x00; //关闭LED外设
P2=0xA0;P0=0x00;P2=0x00; //关闭蜂鸣器继电器
Timer1_Init();
while(1)
{
// count_display();
time_display();
}
}
void server() interrupt 3 //定时器1中断函数(定时器1中断号为3)
{
time_1s++;
if(time_1s>1000)
{
time_1s=0;
// if(++count==99)count=0;
if(++miao==60) //miao加到60归0,fen+1
{
miao=0;
if(++fen==60) //fen加到60归0,shi+1
{
fen=0;
if(++shi==24) //shi加到24归0
{
shi=0;
}
}
}
}
time_8ms++;
if(time_8ms==8)time_8ms=0;
smg(time_8ms,SMG[time_8ms]);
}