首先说说定时器/计数器有什么区别,其实,定时器/计数器在硬件上用的是芯片内部的相同部分,因此我们总是看到把他们写成"定时器/计数器",但他们唯一区别在于:①作为计数器,在减到0以后,输出一个信号便结束,除非重新触发
②作为定时器,减到0以后,自动恢复初值重新计数,并不断产生信号
下面简单列举几个例子
根据芯片手册,可以得到引脚图和定时、计数设置的方法
这是80C52单片机引脚图,位于英文版第1页
这是定时/计数设置顺序,见中文版第55页
这是中断序列号,特别注意定时器/计数器2的中断号为5,见中文版P24
先看寄存器TMOD的功能描述,见中文版第51页
以下是实例
① 定时器(关于此段详细使用请看中文版P51-P55)/*每隔1s灯闪烁一次,但由于晶振11.0592M时最长定时71.777ms,因此 采用1s=1000ms=50ms*20次,即每次中断50ms,进入中断20次*/ /***(定时器与计数器不同在于它中断一次后能复位继续下一次)**/ #include<reg52.h> void timer0_init(); /*中断初始化,使定时器/计数器开始工作*/ void led(); /*中断后对led进行操作*/ unsigned char code table[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f}; int t,num; void main(void) { timer0_init(); led(); } void timer0() interrupt 1 { t++; } void timer0_init() { //设置工作方式控制字 TMOD=0x01; //即设置TMOD为0000 0001,定时器0,工作方式1(16位定时/计数器) //定时初值的计算并装入 /*由[12/(11.0592*10^6)]*x=50ms=50*10^3μs,得到x=46080*/ TH0=(65536-46080)/256;//求(65536-46080)构成的16为二进制数的高8位,H代表高/high,0代表定时器0 TL0=(65536-46080)%256;//求(65536-46080)构成的16为二进制数的低8位,L代表低/low,0代表定时器0 //开放主机中断 EA=1; ET0=1; //0代表定时器0 //设置启/停位TRx TR0=1; //0代表定时器0 } void led() { while(1) { if(t==20) { t=0; //中断1s后使t清零 P1=table[num]; num++; if(num==8) num=0; } } }
定时器1和0设置相同,不在赘述
由于
又由于计数器计数1次所需时间很短,肉眼无法分辨,因此这里在引进一个delay_ms(unsigned int z)延时函数,用以使计数到1暂停1s以便让人能看清
#include<reg52.h> void counter0_init(); /*中断初始化,使定时器/计数器开始工作*/ void input_simulate(); /*模仿外部输入到T0/P3.4的信号*/ void delay_ms(unsigned int z); /*延时函数,以便看到一次计数后led变化*/ void main() { counter0_init(); input_simulate(); if(TL0==1)//进行判断 P1=0x0f; delay_ms(1000);//延时1s input_simulate(); if(TL0==2) P1=0xf0; delay_ms(1000); } void counter0_init() { //设置工作方式控制字 TMOD=0X05;//即0000 0101,计数器0,方式2(16位定时/计数器) //计数初值的计算并装入 TH0=0X00; TL0=0X00; //开放主机中断 ET0=1; EA=1; //设置启停位TRx TR0=1; } void input_simulate() { T0=0; T0=1; } void delay_ms(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); }
#include<reg52.h> void timer2_init(); /*中断初始化,使定时器/计数器开始工作*/ void led(); /*中断后对led进行操作*/ unsigned char code table[]={0xfe,0xfd,0xfb,0xf7, 0xef,0xdf,0xbf,0x7f}; int t,num; void main() { timer2_init(); led(); } void timer0() interrupt 5 { TF2=0; /*特别注意定时器2要软件把TF2至0*/ t++; } void timer2_init() { //设置工作方式控制字 T2CON=0x04;/*设置T2CON为0000 0100,定时器2,内部定时器,16位自动重装*/ //计数初值的计算并并装入 /*由[12/(11.0592*10^6)]*x=50ms=50*10^3μs,得到x=46080*/ TH2=(65536-46080)/256;/*求(65536-46080)构成的16为二进制数的高8位,H代表高/high,0代表定时器0*/ TL2=(65536-46080)%256;/*求(65536-46080)构成的16为二进制数的低8位,L代表低/low,0代表定时器0*/ //中断允许位ETx,EA的设置 ET2=1; EA=1; //启停位TRx的设置 TR2=1; } void led() { while(1) { if(t==20) { t=0; /*中断1s后使t清零*/ P1=table[num]; num++; if(num==8) num=0; } } }
#include<reg52.h> void counter2_init(); /*中断初始化,使定时器/计数器开始工作*/ void input_simulate(); /*模仿外部输入下降沿的信号*/ void delay_ms(unsigned int z); /*延时函数,以便看到一次计数后led变化*/ void main() { counter2_init(); input_simulate(); if(T2EX==1)//进行判断 EXF2=0; P1=0x0f; delay_ms(1000);//延时1s input_simulate(); if(T2EX==2) EXF2=0; P1=0xf0; delay_ms(1000); } void counter2_init() { //设置工作方式控制字 T2CON=0X0D;/*即0000 1101,计数器0,方式2(16位定时/计数器)*/ //计数初值的计算并装入 TH2=0X00; TL2=0X00; //开放主机中断 ET2=1; EA=1; //设置启停位TRx TR2=1; } void input_simulate(void) { T2EX=1; T2EX=0; } void delay_ms(unsigned int z) { unsigned int x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); }