
第十五次课(共2学时)一、授课题目:STC15F2K60S2的定时/计数器(下)二、教学目标和任务:1.掌握STC15F2K60S2单片机定时/计数器的中断编程方法和查询编程方法;2.掌握通过定时/计数器实现方波:3.掌握通过定时/计数器实现电子钟和秒表。三、教学重难点:重点:定时/计数器。难点:电子钟和秒表的实现。四、授课过程:回顾:STC15F2K60S2单片机定时/计数器(TO/T1)的结构工作原理、控制和工作方式。0.引入采用实验用开发板演示电子钟的现象,引入本节课的内容。1.中断编程方法和查询编程方法定时器/计数器的编程方式有两种:1)中断方式,利用中断函数进行编程,此时需要设置TMOD,Tix12、THi、TLxiA,ETi,TRi。计数或者定时满了以后的操作写在中断函数里,中断号1(TO)或3(T1)。2)查询方式,此时需要设置TMOD,THx、TLx,TRx。无需打开中断。查询中断标志TFx即可。语句为if(TFx==1)下面通过例题来说明这两种编程方式。1
1 第十五次课(共 2 学时) 一、授课题目:STC15F2K60S2 的定时/计数器(下) 二、教学目标和任务: 1. 掌握 STC15F2K60S2 单片机定时/计数器的中断编程方 法和查询编程方法; 2. 掌握通过定时/计数器实现方波; 3. 掌握通过定时/计数器实现电子钟和秒表。 三、教学重难点: 重点:定时/计数器。 难点:电子钟和秒表的实现。 四、授课过程: 回顾:STC15F2K60S2 单片机定时/计数器(T0/T1)的结构、 工作原理、控制和工作方式。 0.引入 采用实验用开发板演示电子钟的现象,引入本节课的内容。 1. 中断编程方法和查询编程方法 定时器/计数器的编程方式有两种: 1) 中断方式,利用中断函数进行编程,此时需要设置 TMOD,Tix12、THi、TLxiA,ETi,TRi。计数或者定时满了以 后的操作写在中断函数里,中断号 1(T0)或 3(T1)。 2) 查询方式,此时需要设置 TMOD,THx、TLx,TRx。无 需打开中断。查询中断标志 TFx 即可。语句为 if(TFx==1){ } 下面通过例题来说明这两种编程方式

例题1:请用T0控制P1.0引脚输出10ms方波,晶振频率为12MHz。分析:方波的实现可以通过5ms将引脚电平翻转一次实现。假设我们TOX12设置为O;设置方法为AUXR=AUXR&7f;计数周期为1μs。5ms需要翻转5000次。初值=65536-5000=TH0*256+TL0因此:THO=(65536-5000)/256TH0=(65536-5000)%256初始化程序可以通过烧录软件获得。但是并不推荐这种方法,自己写的话有利于掌握原理。考试的时候也没有烧录软件。中断初始化程序如下:void TimerOInit(void)//5毫秒@12.000MHz1AUXR&=Ox7F://定时器时钟12T模式TMOD=OxFO://设置定时器模式TL0=(65535-5000%256://设置定时初值THO=(65535-5000)/256://设置定时初值TFO=O://清除TFO标志TRO=1://定时器0开始计时1中断方式需要打开响应开关#include"stc15f2k60s2.h"#define uchar unsigned char;2
2 例题 1:请用 T0 控制 P1.0 引脚输出 10ms 方波,晶振频 率为 12MHz。 分析:方波的实现可以通过 5ms 将引脚电平翻转一次实 现。假设我们 T0X12 设置为 0;设置方法为 AUXR=AUXR&7f; 计数周期为 1μs。5ms 需要翻转 5000 次。 初值=65536-5000=TH0*256+TL0 因此: TH0=(65536-5000)/256 TH0=(65536-5000)%256 初始化程序可以通过烧录软件获得。但是并不推荐这种方 法,自己写的话有利于掌握原理。考试的时候也没有烧录软件。 中断初始化程序如下: void Timer0Init(void) //5 毫秒@12.000MHz { AUXR &= 0x7F; //定时器时钟 12T 模式 TMOD &= 0xF0; //设置定时器模式 TL0 = (65535-5000)%256; //设置定时初值 TH0 = (65535-5000)/256; //设置定时初值 TF0 = 0; //清除 TF0 标志 TR0 = 1; //定时器 0 开始计时 } 中断方式需要打开响应开关 #include "stc15f2k60s2.h" #define uchar unsigned char;

sbit out=P10:voidinttoOinterrupt1( out= out:)void mainfTimerlInit O:EA=1:ETO=1:while(1);查询方式需要手动清零TFO#include"stc15f2k60s2.h"#define uchar unsigned char;sbit out=P1'0;void main(1out=;TimerlInit O:while(1) (if (TF1=-1)(TF1=0: out=out: 1)思考:若采用的是方式1,程序应该怎么写?方式1和方式0的区别在于有无自动重装功能。采用方式3
3 sbit out=P1^0; void intt0() interrupt 1 { out=~out;} void main() { Timer1Init(); EA=1; ET0=1; while(1); } 查询方式需要手动清零 TF0 #include "stc15f2k60s2.h" #define uchar unsigned char; sbit out=P1^0; void main() { out=0; Timer1Init(); while(1){ if (TF1==1) {TF1=0; out=~out; }} } 思考:若采用的是方式 1,程序应该怎么写? 方式 1 和方式 0 的区别在于有无自动重装功能。采用方式

1时,除了需要将TMOD重新设置外,每次计满溢出后还需要再次设置初值。例题2:用2位数码管显示计时时间,最小计时单位为“百毫秒”,计时范围0.1~9.9s。当第1次按一下计时功能键时,秒表开始计时并显示;第2次按一下计时功能键时,停止计时,将计时的时间值送到数码管显示:第3次按一下计时功能键,秒表清0,并停止计时。再次按一下计时功能键,则重复上述计时过程。如果计时到9.9s,蜂鸣器报警,再重新开始从0计时。分析:首先完成秒表,100ms的定时,单靠定时器完不了,我们需要设置10ms的定时器。定义一个全局变量msecond,单位一百毫秒。每100ms,将msecond加1。当加到99后,下一次回到0。显示数据时,用数码管最低两位进行显示。十位为msecond/10个位为msecond%10显示时需要在十位带上小数点,将段码和0x80做按位或运算即可。程序如下:#include"stc15f2k60s2.h"#include#define uint unsigned int#defineucharunsigned char4
4 1 时,除了需要将 TMOD 重新设置外,每次计满溢出后还需要 再次设置初值。 例题 2:用 2 位数码管显示计时时间,最小计时单位为“百 毫秒”,计时范围 0.1~9.9s。当第 1 次按一下计时功能键时, 秒表开始计时并显示;第 2 次按一下计时功能键时,停止计时, 将计时的时间值送到数码管显示;第 3 次按一下计时功能键, 秒表清 0,并停止计时。再次按一下计时功能键,则重复上述 计时过程。如果计时到 9.9s,蜂鸣器报警,再重新开始从 0 计 时。 分析: 首先完成秒表,100ms 的定时,单靠定时器完不了,我们 需要设置 10ms 的定时器。 定义一个全局变量 msecond,单位一百毫秒。每 100ms, 将 msecond 加 1。当加到 99 后,下一次回到 0。 显示数据时,用数码管最低两位进行显示。 十位为 msecond/10 个位为 msecond%10 显示时需要在十位带上小数点,将段码和 0x80 做按位或 运算即可。 程序如下: #include"stc15f2k60s2.h" #include #define uint unsigned int #define uchar unsigned char

ucharcodeseg=[0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x070x7f,0x6f,0x40) :uchar codewei[]=(Oxf7,Oxfb,Oxfd,Oxfe,Ox7f,Oxbf, Oxdf, Oxef) ;sbit weix=P2°7;sbitduanx=P2~6://无论何时只要用到了数码管,这四句请事先写好。sbitbeep=P3~2://用到了蜂鸣器ucharmsecond,k;//全局变量,一个用来计时值,一个用来记录10ms定时完成次数void Delay2ms()//@12.000MHzvoid Delay200ms()void display(tPO=wei[0] :weix=l;weix=0;P0=seg[msecond%10];duanx=1;duanx=0;Delay2ms (;//个位不需要小数点PO-wei[1]:weix=l;weix=0;P0=seg[msecond/10]/0x80;duanx=1;duanx=0Delay2ms ()://十位需要小数点void beepa O1uchar i;5
5 uchar code seg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x40}; uchar code wei[]={0xf7,0xfb,0xfd,0xfe,0x7f, 0xbf,0xdf,0xef}; sbit weix=P2^7; sbit duanx=P2^6;//无论何时只要用到了数码管,这四句请事先 写好。 sbit beep=P3^2;//用到了蜂鸣器 uchar msecond,k; //全局变量,一个用来计时值,一个用来记录 10ms 定时完成次数 void Delay2ms() //@12.000MHz void Delay200ms() void display() { P0=wei[0];weix=1;weix=0; P0=seg[msecond%10];duanx=1;duanx=0; Delay2ms(); //个位不需要小数点 P0=wei[1];weix=1;weix=0; P0=seg[msecond/10]|0x80;duanx=1;duanx=0; Delay2ms(); //十位需要小数点 } void beepa() { uchar i;

for(i=0;i<5;i++)(beep=0;Delay200ms(;beep=1;Delay200ms();1蜂鸣器报警函数void TO int Ointerruptltk++:1/记录计数满了10ms的次数if(k==10)//满了100msLk=0://满了以后回到0,重新计时if(msecond<99)msecond++://没有到9.9s,就计数值加1else(msecond=0;//到了以后清屏PO=0xff:weix=1:weix=0:beepa(://报警)L1void maint//计数频率AUXR=AUXR&0x3f;//工作方式TMOD=0x00:6
6 for(i=0;i<5;i++) { beep=0;Delay200ms();beep=1;Delay200ms(); } } 蜂鸣器报警函数 void T0_int() interrupt 1 { k++; // 记录计数满了 10ms 的次数 if(k==10) //满了 100ms { k=0; //满了以后回到 0,重新计时 if(msecond<99) msecond++;//没有到 9.9s,就计数值加 1 else {msecond=0; P0=0xff;weix=1;weix=0; //到了以后清屏 beepa(); //报警} } } void main() { AUXR=AUXR&0x3f; //计数频率 TMOD=0x00; //工作方式

TH0=(65536-10000)/256;1/设置初值TL0=(65536-10000)%256;TFO=0;TRO=1://启动EA=1;ETO=1//开中断k=0;msecond=0;//初值设置while(1)(display ( :)按键程序分析:按键按下一次,可以计数,只要一开始将TRO=O:同一个按键控制三个不同功能,需要在按键程序里加入计数值knum;按下一次按键让knum=1二次knum=2:三次knum=3;四次kum=l;即可。当knum=1,TRO=1;当knum=2,TRO=0:当knum=3,将msecond=0;需要加入一个按键处理函数,如下:主函数里需要将TR=O:并在调用函数时,加入按键处理函数即可。void keypro()1if (K1==0)Delay10ms () ;7
7 TH0=(65536-10000)/256; TL0=(65536-10000)%256; //设置初值 TF0=0;TR0=1; //启动 EA=1;ET0=1; //开中断 k=0;msecond=0; //初值设置 while(1) {display();} } 按键程序分析: 按键按下一次,可以计数,只要一开始将 TR0=0; 同一个按键控制三个不同功能,需要在按键程序里加入计 数值knum;按下一次按键让knum=1;二次knum=2;三次knum=3; 四次 kum=1;即可。 当 knum=1,TR0=1; 当 knum=2,TR0=0; 当 knum=3,将 msecond=0; 需要加入一个按键处理函数,如下: 主函数里需要将 TR=0;并在调用函数时,加入按键处理 函数即可。 void keypro() { if(K1==0) { Delay10ms();

if (K1==0)tif (knum<3)knum++:else knum=l:switch(knum)(case(1):TRO-1:break:_case(2) :TRO=0:break:case(3):(msecond=0:TRO=0:break:)default:msecond=msecond:11while(K1==0) :11例题3:时钟程序设计,设计电子钟,可实现小时、分钟、秒的显示。24小时制。当时间到00-00-00时,通过蜂鸣器进行提示。分析:计满1s,需要50mS,20次。每次计满20次时,分析是否需要进位。分四种情况:23:59:59,下一次为00:00:00XX:59:59,下一次xx+1:00:00xX:yy:59下一次xx:yy+1:00XX: yy: zz下一次xx:yy:zz+1显示通过数码管显示:时间六位加两个分隔符。如:20-56-238
8 if(K1==0) { if(knum<3)knum++; else knum=1; switch(knum) {case(1):TR0=1;break; case(2):TR0=0;break; case(3):{msecond=0;TR0=0;break;} default:msecond=msecond; } } while(K1==0); } } 例题 3:时钟程序设计,设计电子钟,可实现小时、分钟、 秒的显示。24 小时制。当时间到 00-00-00 时,通过蜂鸣器进 行提示。 分析:计满 1s,需要 50ms,20 次。每次计满 20 次时,分 析是否需要进位。分四种情况: 23:59:59,下一次为 00:00:00 XX:59:59,下一次 xx+1:00:00 XX:yy:59 下一次 XX:yy+1:00 XX:yy:zz 下一次 xx:yy:zz+1 显示通过数码管显示:时间六位加两个分隔符。 如:20-56-23

程序如下:#include"stc15f2k60s2.h"#include#defineuint unsigned int#defineuchar unsigned charsbit duanx=P26;sbit weix=P2°7;sbit beep=P3~2;uchar k,second,minius,hour;ucharcodeseg[J={0x3f,0x06,0x5b,0x4f,0x66,0x6d0x7d,0x07,0x7f,0x6f,0x40);uchar codewei[J={Oxf7,Oxfb,Oxfd,Oxfe,Ox7f,Oxbf, Oxdf, Oxef) :uchar shijian[8] ;void Delay2ms ():void Delay100ms O ;void numpro(tshijian[o]=second%10;shijian[1]=second/10;shijian[2]-10;shijian[3]=minius%10;shijian[4]=minius/10;shijian[5]=10;9
9 程序如下: #include"stc15f2k60s2.h" #include #define uint unsigned int #define uchar unsigned char sbit duanx=P2^6; sbit weix=P2^7; sbit beep=P3^2; uchar k,second,minius,hour; uchar codeseg[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d, 0x7d,0x07,0x7f,0x6f,0x40}; uchar code wei[]={0xf7,0xfb,0xfd,0xfe,0x7f, 0xbf,0xdf,0xef}; uchar shijian[8]; void Delay2ms(); void Delay100ms(); void numpro() { shijian[0]=second%10; shijian[1]=second/10; shijian[2]=10; shijian[3]=minius%10; shijian[4]=minius/10; shijian[5]=10;

shijian[6]=hour%10;shijian[7]=hour/10void display(tuchar i;for(i=0;i<8;i++)1PO=wei[i];weix=1;weix=0;PO=seg[shijian[i]]:duanx-l;duanx=0;Delay2ms();void TO intOinterrupt1tchar i;k++;if (k==20)(k=0;if((second==59)&&(minius==59)&&(hour==23))(second=0;minius=0;hour=0;)elseif((second==59)&&(minius==59))(second=0;minius=0;hour++;)elseif((second==59))(second=O;minius++;)10
10 shijian[6]=hour%10; shijian[7]=hour/10; } void display() { uchar i; for(i=0;i<8;i++) { P0=wei[i];weix=1;weix=0; P0=seg[shijian[i]];duanx=1;duanx=0; Delay2ms(); } } void T0_int() interrupt 1 { char i; k++; if(k==20) {k=0; if((second==59)&&(minius==59)&&(hour==23)) {second=0;minius=0;hour=0; } else if((second==59)&&(minius==59)) {second=0;minius=0;hour++;} else if((second==59)) {second=0;minius++;}