STC15F2K60S2单片机的定时器计数器例题.doc
第8章STC15F2K60S2单片机的定时/计数器例题例8.1 用T1方式0实现定时,在P1.0引脚输出周期为10mS的方波。解: 根据题意,采用T1方式0进行定时,因此,(TMOD)=00H。因为方波周期是10mS,因此T1的定时时间应为5mS,每5mS时间到就对P1.0取反,就可实现在P1.0引脚输出周期为10mS的方波。系统采用12M晶振,分频系数为12,即定时脉钟周期为1S,则T1的初值为:X = M -计数值= 65536 - 5000 = = 60536 =EC78H即:TH1 = ECH,TL1 = 78H。 (1)查询方式实现:ORG 0000H MOVTMOD,#00H;设T1为方式0定时模式MOVTH1,#0ECH;置5mS定时的初值MOVTL1,#78HSETBTR1;启动T1Check_TF1: JBCTF1,Timer1_Overflow ;查询计数溢出 SJMPCheck_TF1;未到5mS继续计数Timer1_Overflow: CPL P1.0 ;对P1.0取反输出SJMP Check_TF1;未到1s继续循环END (2)中断方式实现: ORG0000H LJMPMAIN ;上电复位后,转MAIN ORG001BH LJMPTimer1_ISR ;T1中断响应后,转 Timer1_ISR ORG0100H MAIN: MOV TMOD,#00H;设T1为方式0定时模式 MOV TH1,#0ECH;置5mS定时的初值MOV TL1,#78HSETB ET1SETB EA ;开放中断SETB TR1;启动T1SJMP $ ;原地踏步,模拟主程序 Timer1_ISR:CPL P1.0 ;对P1.0取反输出RETI ;中断返回,回到主程序执行 SJMP $ END 例8.2 用定时计数器扩展外部中断。解:当实际应用系统中有两个以上的外部中断源,而片内定时计数器未使用时,可利用定时计数器来扩展外部中断源。扩展方法是,将定时计数器设置为计数器方式,计数初值设定为满程,将待扩展的外部中断源接到定时计数器的外部计数引脚。从该引脚输入一个下降沿信号,计数器加1后便产生定时计数器溢出中断。因此,可把定时计数器的外部计数引脚作为扩展中断源的中断输入端。设采用T1实现,采用工作方2,即TH1、TL1的初值均为FFH,T1中断开放,即T1引脚(P3.5)为扩展外部中断的中断请求信号输入端,触发方式为下降沿触发。其初始化程序(中断方式)如下:ORG0000H LJMPMAIN ;上电复位后,转MAIN ORG001BH LJMPEX_ISR ;T1中断响应后,转 EX_ISR ORG0100H MAIN: MOV TMOD,#60H ;设T1为方式1计模式 MOV TH1,#0FFH MOV TL1,#0FFH SETB ET1 SETB EA ;开放中断 SETB TR1 ;启动T1 ;主程序其它指令 EX_ISR: ;扩展外部中断的中断服务程序 RETI END思考:试将例8.2的功能用T0或T1的方式0实现。例8.3 使信号灯循环点亮,首先按从左至右轮流点亮,再按从右至左轮流点亮,每个信号灯点亮的时间间隔为1秒。要求用单片机定时/计数器定时实现。 解:硬件电路比较简单,采用P1口输出驱动电平,低电平有效。电路如图8.7所示。 图8.7 流水灯显示电路系统采用12M晶振,分频系数为12,即定时时钟周期为1S;采用定时器T1方式0定时50mS,用R3做50ms计数单元,20次50mS定时即为1S,故R3的初始值为20。 汇编语言参考程序如下: 1)查询方式实现ORG0000HLOOP: MOV R2,#07H ;设置左移的次数MOV A,#0FEH ;设置信号灯的显示(左移)的起始状态值Left_Shift: MOV P1,A ;送显示控制信号LCALL DELAY ;利用软件与定时器,实现1s定时 RL A ; 改变信号灯显示状态,左移DJNZ R2,Left_Shift ;判断左移流程是否结束,若结束,转入右移控制MOV A,#7FH ;设置信号灯的显示(右移)的起始状态值,可省略 MOV R2,#07H ;设置右移的次数Right_Shift: MO P1,A ;送显示控制信号RR A ; 改变信号灯显示状态,右移LCALL DELAY ;利用软件与定时器,实现1s定时DJNZ R2,Right_Shift ;判断左移流程是否结束,若结束,又重新开始SJMP LOOPDELAY: MOV R3,#20 ;置50ms计数循环初值MOV TMOD,#00H;设定时器1为方式1 MOV TH1,#3CH;置定时器初值MOV TL1,#0B0HSETB TR1 ;启动T1Check_TF1:JBC TF1,Timer1_Overflow ;查询计数溢出SJMP Check_TF1;未到50ms继续计数Timer1_Overflow: DJNZ R3,Check_TF1 ;未到1s继续循环 CLR TR1 ;关闭T1 RET ;返回主程序 END2) 中断方式实现ORG0000H LJMPMAINORG001BHLJMPTimer1_ISRMAIN: MOV R3,#20 ;置50ms计数循环初值MOV TMOD,#00H;设定时器1为方式1 MOV TH1,#3CH;置50ms定时器初值MOV TL1,#0B0HMOV R2,#07H ;设置左移的次数 MOV P1,#0FEH ;设置信号灯的显示(左移)的起始状态值 MOV A,#0FEH ;设置信号灯的显示(左移)的起始状态值 CLR 00H ;设置左、右移标志位,为0左移,为1右移SETB ET1 SETB EA SETP TR1 ;启动T1定时器 SJMP $ ;原地踏步,模拟主程序Timer1_ISR: DJNZ R3,Exit_Timer1_ISR ;定时时间到,执行移位,否则中断结束 MOV R3, #20 JB 00H, Right_Shift ;判断左、右移控制 RL A ;左移控制 MOV P1, A DJNZ R2,Exit_Timer1_ISR ;判断左移流程是否结束,若结束,转入右移控制SETB 00H ;置位左、右移控制标志 MOV R2, #07H ;重新设置移位次数 SJMP Exit_Timer1_ISRRight_Shift: RR A ;右移控制 MOV P1, A DJNZ R2,Exit_Timer1_ISR ;判断左移流程是否结束,若结束,转入右移控制CLR 00H ;清0左、右移控制标志 MOV R2, #07H ;重新设置移位次数Exit_Timer1_ISR: RETI END C51参考程序如下: 1)查询方式实现 #include <REG51.H> /包含52标准文件头#include <intrins.h> /包含循环左移、右移子函数#define uchar unsigned char#define uint unsigned intuchar LED = 0xfe;/*-利用T1实现定时的子函数-*/void DELAY(void) /延时函数 1Suint i = 0;TMOD = 0x00;/T1工作模式1TH1 = 0x3c;TL1 = 0xb0;TR1 = 1;while(i<20)if(TF1=1) /查询T1溢出标志TF1 = 0;i+;/*-循环左移子函数-*/void Left_Shift(void)P1 = LED;DELAY(); /延时一秒LED = _crol_(LED,1); /循环左移一位/*-循环右移子函数-*/void Right_Shift(void)LED = _cror_(LED,1); /循环右移一位P1 = LED;DELAY(); /延时一秒/*-主函数-*/void main(void) uchar j;while(1)for(j=0;j<7;j+)Left_Shif (); for(j=0;j<7;j+)Right_Shift (); 2)中断方式实现#include <REG52.H> /包含52标准文件头#include <intrins.h> /包含循环左移、右移子函数#define uchar unsigned char#define uint unsigned char/*-定义全局变量-*/uchar LED = 0xfe;uchar i = 0;uchar t = 0;/*-T1初始化子函数-*/void Timer1_init(void) TMOD = 0x00; /T1工作模式1TH1 = 0x3c;TL1 = 0xb0;ET1 = 1;EA = 1;TR1 = 1;/*-LED循环显示子函数-*/void Shift(void) P1 = LED;t+;if(t<=7)LED = _crol_(LED,1); /循环左移一位else if(t<15) LED = _cror_(LED,1); /循环右移一位else t = 0;/*-T1中断服务子函数-*/void Timer1_int(void) interrupt 3 using 1 /定时T1中断服务程序i+;f(i=20)i = 0;Shift ();/*-主函数-*/void main(void) /主函数Timer1_init(); /T1初始化while(1) ; 例8.4 连续输入5个单次脉冲使单片机控制的LED灯状态翻转一次。要求用单片机定时/计数器计数功能实现实现。 解:采用T1实现,硬件如图8.8所示。 图8.8 信号灯的计数控制 采用T1的方式2的计数方式,初始值设置为FBH,当输入5个脉冲时,即溢出标志TF1,通过查询TF1或中断方式判断TF1标志,进而对P1.0LED灯进行控制。 汇编语言参考程序如下 : 1)查询方式实现ORG0000H MOV TMOD, #60H ;设定定时器1模式2,计数功能 MOV TH1, #0FBH MOV TL1, #0FBH ;设置计数器初值(2565) SETB TR1 ;启动计数Check_TF1: JBC TF1, Timer1_Overflow ;查询是否计数溢出 AJMP Check_TF1 Timer1_Overflow: CPL P1.0 ;当统计5个脉冲,LED灯状态翻转 AJMP Check_TF1 END 2)中断方式实现ORG0000HAJMPMAINORG001BHAJMPTimer1_ISRMAIN:MOV TMOD, #60H ;设定定时器1模式2,计数功能MOV TH1, #0FBH MOV TL1, #0FBH ;设置计数器初值(2565)SETB ET1 SETB EASETB TR1 ;启动计数SJMP $Timer1_ISR:CPL P1.0 ;当统计5个脉冲,LED灯状态翻转RETIEND C51参考程序如下: 1)查询方式实现#include<reg51.h>sbit led = P10;void timer_initial(void)TMOD = 0x60;/设定定时器1模式2,计数功能TH1 = 0xfb; /5个脉冲以后溢出TL1 = 0xfb; TR1 = 1;/开始计数器 void main(void)timer_initial();while(1)while(TF1=0); TF1 = 0;Led = led;/不断查询是否溢出,没有溢出,就等待溢出了;溢出了, /清空溢出标志,led取反 2)中断方式实现#include <reg51.h> #define uchar unsigned char#define uint unsigned charsbit LED = P10;/*-T1初始化子函数-*/void Timer1_init(void)TMOD = 0x60;/1设定定时器1模式2,计数功能TH1 = 0xfb;/设置计数器初值(计满溢出值5)TL1 = 0xfb;ET1 = 1;EA = 1;TR1 = 1;/启动计数/*-T1中断服务子函数-*/void Timer1_int(void) interrupt 3 using 1 /定时计数T1中断服务程序LED = LED;/*-主函数-*/void main(void) /主函数Timer1_init();/定时T1初始化while(1) ; 思考:用方式0实现。 例8.5 利用单片机定时器/计数器设计一个秒表,由P1口连接LED灯,采用BCD码显示,发光二极管亮表示1,暗则表示0,计满100s后从头开始,依次循环。利用一只按键控制秒表的启、停。利用复位键,返回初始工作状态。 解: 选用P1口作输出端,控制8只发光二极管显示,设发光二极管的驱动是低电平亮,高电平灭。P3.5接秒表的启、停按键。采用T0的方式0作定时器,12M晶振,分频系数为12,即定时时钟周期为1S汇编语言参考程序如下:ORG0000H LJMPMAIN ORG000BH LJMPTimer0_ISQMAIN: MOV TMOD,#00H ;T0方式1定时 MOV TH0,#3CH ;重新置T0 50ms定时的初值MOV TL0,#0B0HSETB ET0 SETB EA MOV R3,#14H ;置50ms计数循环初值(1s/50ms)MOV A, #00H;计数显示初始化 CPL A ;满足低电平驱动要求 MOV P1,A CPL A ;恢复秒表计数值Check_Start_Button: JNB P3.5, Start CLR TR0 SJMP Check_Start_ButtonStart: SETB TR0 SJMP Check_Start_ButtonTimer0_ISQ: DJNZ R3,Exit_Timer0_ISQ ADD A, #01 ;秒表加1 DA A ;十进制调整 CPL A ;满足低电平驱动要求 MOV P1,A CPL A ;恢复秒表计数值 MOV R3, #14H Exit_Timer0_ISQ: RETIENDC51参考程序如下:include <REG52.H> /包含52标准文件头#define uchar unsigned char#define uint unsigned charuchar dat=0; /定义BCD计数单元(范围:099)uchar i; /定义循环变量sbit key=P35; /定义按键/*-T0初始化子函数-*/void Timer0_init(void) TMOD = 0X00; /T0方式1TH0 = (65535-50000)/256; /赋初始值,50msTL0 = (65535-50000)%256; /赋初始值ET0=1;EA=1;/*-T0中断服务子函数-*/void Timer0_int(void) interrupt 1 using 1/T0中断服务子程序i+;if(i=20) /i=20时,计时1Si = 0;dat+;f(dat=100) /计时到100S时,又从0开始dat0;/*-启动子函数-*/void Start(void) /启动定时函数if(key=0) /判断按键按下TR0=1; /开始计时else TR0=0;/*-BCD码转换子函数-*/uchar BCD(uchar BCDat)/BCD转换uchar x;x = (BCDat/10)*10+BCDat%10;return(x);/*-主函数-*/void main(void)Timer0_init(); /T0初始化while(1)Start(); / 启动定时P1 = (BCD(dat); /送LED显示例8.6 编程在P3.0、P3.5、P3.4引脚上分别输出115.2KHZ、51.2KHZ、38.4KHZ的时钟信号。解:设系统时钟频率为12 KHZ,T0、T1工作在方式2定时状态,且工作在无分频模式,即各定时器的定时脉冲频率等于时钟频率,即(T0x12)(T1x12)(T2x12)1;各根据前面可编程时钟输出频率的计算公式,计算各定时器的定时初始值:(T2H)=FFH,(T2L)=CCH,(TH0)=(TL0)=8BH,( TH1)=(TL1)=64H(1) 汇编语言参考程序T2H EQU D6HT2L EQU D7HAUXR EQU 8EH INT_CLKO EQU 8FH ORG0000HMOV TMOD,#22H ;T0、T1工作方式2定时状态 ORL AUXR,80H ;T0工作在无分频模式 ORL AUXR,40H ;T1工作在无分频模式 ORL AUXR,04H ;T2工作在无分频模式 MOV T2H,#0FFH ;设置BRT定时器的初始值MOV T2L,#0CCH MOV TH0,#139 ;设置T0定时器的初始值 MOV TL0,#139 MOV TH1,#100 ;设置T1定时器的初始值 MOV TL1,#100 ORL INT_CLKO,07H ;允许CLKOUT0、CLKOUT1、CLKOUT2时钟输出 SETB TR0 ;启动T0 SETB TR1 ;启动T1 ORL AUXR,#10H ;启动T2 SJMP $ (2)C51参考程序include<reg51.h>sfr INT_CLKO = 0x8F;sfr AUXR = 0x8E;sfr T2H = 0XD6;sfr T2L = 0Xd7;main()TMOD = 0x22;AUXR = (AUXR|0x80); /T0工作在无分频模式AUXR = (AUXR|0x40) ; /T1工作在无分频模式AUXR = (AUXR|0x04) ; /T2工作在无分频模式T2H = 0xFF; /给T2、T0、T1定时器设置初值T2L = 0xCC;TH0 = 139;TL0 = 139;TH1 = 100;TL1 = 100;INT_CLKO (WAKE_CLKO|0x07); /允许T0、T1、T2输出时钟信号TR0 = 1; /启动T0TR1 = 1; /启动T1AUXR = (AUXR|0x10) ; /启动T2while(1); /无限循环 169