第五章 单片机的定时器和计数器
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
要想计数器计得一定数量的计数值后,计数器计满溢出,就需把预置的 计数初值设为计数值的补数。对于13位计数器,求计数值补数的方法就 是先把十进制的计数值转换13位二进制数,在把其取反加1。例如计数 值为10,则10转换成13位二进制数为00000000 01010B,取反为 11111111 10101,再加1为11111111 10110B。 由于定时器Ti的计数器是由两个8位的特殊功能寄存器THi和TLi构成。而 定时器Ti处于方式0下工作时,计数器只用到了其中13位,即THi的8位 和TLi的低5位,而TLi的高3位弃之不用。计数值10的13位计数初值 11111111 10110B,高8位存放在THi中,低5位存放在TLi中。定时器Ti 处于方式0下工作时,闲置的TLi的高3位可设为000B。所以综上所述, 要想计数器计得脉冲信号的10个脉冲,即计数器加10,计数器计满溢出, 应把THi设为FFH,TLi设为16H。
1.标准库函数 标准库函数是由C51的编译器提供的,用户不必定义这 些函数,可以直接调用。KEIL C51编译器提供了100多个 库函数供我们使用。常用的C51库函数包括一般I/O口函数、 访问SFR地址函数等,在C51编译环境中,以头文件的形式 给出。 2.用户自定义函数 用户自定义函数是用户根据需要自行编写的函数,它 必须先定义之后才能被调用。
定时器的初始值的计算
对于不同的工作方式,计数器位数不同,故最大计数值M也不同: 方式0:M=213=8192
方式1:M=216=65536
方式2:M=28=256 方式3:定时器0分为2个8位计数器,每个M均为256。
因为定时/计数器是作加1计数,并在计满溢出时产生中断,因此初
值X的计算如下: X = M – 计数值
(TMOD)=00000000B=00H
TMOD
TCON
GATE TF1
C/T
TR1
M1 TF0
M0 TR0
GATE
C/T
M1
M0
例2:在工作方式0下,定时器T1引脚对用T0计数器产生的 P1.0引脚上周期为2ms的方波,进行计数,要求每计满5次, 将P1.1状态取反,在P1.1 上产生周期为20ms的方波。
C语言的函数
在C语言程序中,子程序的作用是由函数来实现的,函数是C语言的
基本组成模块,一个C语言程序就是由若干个模块化的函数组成的。
C程序都是由一个主函数main( )和若干个子函数构成,有且只有一 个主函数,程序由主函数开始执行,主函数根据需要来调用其他函数,
其它函数可以有多个。
函数分类和定义
在定时器Ti处于方式1下工作时,计数器用到 了全部16位来计数,由THi作为高8位和TLi作 为低8位构成。若计数器要计的计数值还为10, 那么计数器预置的计数初值为何值?我们知道, 预置的计数初值就是计数值的补数,对于16位 计数器,求计数值补数的方法就是先把十进制 的计数值转换16位二进制数,在把其取反加1。 10转换成16位二进制数为00000000
#include <reg51.h>//包含头文件reg51.h sbit P1_0=P1^0;//定义P1.0引脚位名称为P1_0 sbit P1_1=P1^1;//定义P1.1引脚位名称为P1_1 void time_0() interrupt 1 //定时器0溢出中断 { //重装定时器0计数初值 TL0=0x18;TH0=0xE0; P1_0=~P1_0; //方波电平反相 } void time_1() interrupt 3 //定时器1溢出中断 { P1_1=~P1_1; //方波电平反相 }
void main() //主程序 { //设置T0为方式0定时,T1为方式2计数 TMOD=0x60; //设置定时器0计数初值,计数到1000就溢 出 TL0=0x18;TH0=0xE0; //设置定时器1计数初值,计数到5就溢出 TL1=0xFB;TH1=0xFB; EA=1;ET0=1;ET1=1;//开中断 TR0=1; //启动T0 TR1=1; //启动T1 while(1); }
#include <reg51.h>//包含头文件reg51.h sbit P1_0=P1^0;//定义P1.0引脚位名称为P1_0 sbit P1_1=P1^1;//定义P1.1引脚位名称为P1_1 //T0中断服务子程序 void time_0() interrupt 1 //定时器0溢出中断 { //重装定时器0计数初值 TL0=0x18;TH0=0xE0; //方波电平反相 P1_0=~P1_0; } //T1中断服务子程序 void time_1() interrupt 3 //定时器1溢出中断 { //重装定时器1计数初值 TL1=0x1B;TH1=0xFF; P1_1=~P1_1; //方波电平反相 }
第五章
定时与中断系统
本章内容
定时/计数器 C语言的函数
8051片内有两个16位定 时器/计数器(简称定时 器),如图12.1所示。它们 实际上都是16位二进制加 1计数器。每个定时器都 可通过两个特殊功能寄存 器TMOD和TCON,由软 件设置为定 时工作方式或 计数工作方式及其他灵活 多样的可控功能方式。
例1:利用T0计数器的工作方式0产生1ms的定时,在P1.0引脚 上输出周期为2ms的方波,如图所示。设单片机晶振频率 f=12MHz。
解:由图看出,加上12MHz晶振的振荡器12分频后的脉冲信号的周期为: 由于计数器计得一个12分频后的脉冲,需的时间。故要定时,则计数器 要计得1000个12分频后的脉冲,即计数初值要加计数值1000,并计满溢 出。 现计算在工作方式0产生1ms的定时,预置的计数初值应为何值? 1000转换成13位二进制数为00011111 01000B ( 29 28 27 26 25 23 ),取反为11100000 10111,再加1为 11100000 11000B。于是预置的TH0初值为E0H,TL0初值为18H。
举 例2
用T1、工作方式2实现1秒延时,晶振频率为12MHz。 因工作方式2是8位计数器,其最大定时时间为:256×1s = 256s,为实现1秒延时,可选择定时时间为250s,再 循环4000次。定时时间选定后,可确定计数值为250,则 T1的初值为:X = M 计数值=256 250 = 6 = 6H。采用 T1方式2工作,因此,TMOD =0x20。
例3:在工作方式2下,定时 器T1引脚对用定时器T0器产 生的P1.0引脚上周期为2ms 的方波,进行计数,要求每 计满5次,将P1.1状态取反, 在P1.1 上产生周期为10ms 的方波。
解 :P1.1的方波由T1(P3.5)引脚输入,每发生一次负跳变,计数器加1,每输入5 个脉冲,计数器发生溢出中断,中断服务程序将P1.1取反一次。 T1在方式2下,对外部信号T1计数,则工作方式寄存器TMOD设置为:(TMOD) =01100000B=60H。T0做方式0定时时,TMOD的低4位一般取0000B。 计算T1的计数初值: 由于要计的计数值为5,5转换成二进制数为00000101B,取反为11111010B, 再加1为11111011B,于是TL1的计数初值为11111011B (FBH),重装初值寄存 器(TH1)=FBH。
Timer1 TMOD TCON
GATE TF1
Timer0
M0 TR0 GATE
C/T
TR1
M1 TF0
ห้องสมุดไป่ตู้C/T
M1
M0
M1 M0
工作模式
功能说明
00
01 10 11
方式0
方式1 方式2 方式3
13位计数器
16位计数器 自动再装入8位计数器 定时器0:分成两个8位计数器;定时器1:停止计数
定时器Ti方式0的13位计数器何种情况下,会产生溢出,并置位溢出标 志位TFi,向CPU请求中断。当13位二进数加1,使其最高位向前进位 时,就产生溢出。即13位二进制数11111111 11111B加1,则会溢出, 变为00000000 00000B。 我们知道,对于13位计数器,若预置计数初值为11111111 11111B, 只能计得脉冲信号的一个脉冲,即计数器加1,计数器就会溢出。按这 样的思路,要使计数器计得脉冲信号的10个脉冲,即计数器加10,计 数器计满溢出,那么应给计数器预置计数初值为何值?计数初值应为 11111111 10110B,因为11111111 10110B+1010B(10)=00000000 00000B。
计算出来的结果X转换为16进制数后分别写入TL0(TL1)、TH0
(TH1)。 注意!方式0时初始值写入时,对于TL不用的高3位应填入0!
举 例1
用T1、工作方式0实现1秒延时函数,晶振频率为12MHz。 方式0采用13位计数器,其最大定时时间为:8192×1s = 8.192ms,因此,定时时间不可能象任务7中一样选择50ms, 可选择定时时间为5ms,再循环200次。 定时时间为5ms,则计数值为5ms/1s =5000,T1的初值为: X = M 计数值= 8192 5000 = 3192 = C78H = 0110001111000B 13位计数器中TL1的高3位未用,填写0,TH1占高8位,所 以,X的实际填写值应为: X = 0110001100011000B = 6318H
#include <reg51.h>//包含头文件reg51.h void delay1s()// delay1s延时函数 { unsigned char i; TMOD=0x00; // 置T1为工作方式0 for(i=0;i<200;i++){ // 设置200次循环次数 TH1=0x63; // 设置定时器初值 TL1=0x18; TR1=1; // 启动T1 while(!TF1); // 查询计数是否溢出,即定时5ms时间到,TF1=1 TF1=0; // 5ms定时时间到,将定时器溢出标志位TF1清零 } } void main() { unsigned char i,w; TMOD=0x00;//设置T1为方式0 while(1) { w=0x01;//显示码初值为01H for(i=0,i<8;i++) { P1=~w;//w取反后送P1口,点亮相应流水灯 w<<=1;//点亮灯的位置移动 delay1s();//调用delay1s延时函数 } } }
举 例1
用T1方式0实现1秒延时函数如下: void delay1s() { unsigned char i; TMOD=0x00; // 置T1为工作方式0 for(i=0;i<200;i++){ // 设置200次循环次数 TH1=0x63; // 设置定时器初值 TL1=0x18; TR1=1; // 启动T1 while(!TF1); // 查询计数是否溢出,即定时5ms时间到,TF1=1 TF1=0; // 5ms定时时间到,将定时器溢出标志位TF1清零 } }
举 例2
用定时器工作方式2实现的1秒延时函数如下: void delay1s() { unsigned int i; // i取值范围为0~4000,因 此不能定义成unsigned char TMOD=0x20; // 设置T1为方式2 TH1=6; // 设置定时器初值, 放在for循环之外 TL1=6; for(i=0;i<4000;i++){ // 设置4000次循环次数 TR1=1; // 启动T1 while(!TF1); // 查询计数是否溢出,即定时250s 时间到,TF1=1 TF1=0; // 250s定时时间 到,将定时器溢出标志位TF1清零 } }
void main() //主程序 { ;//设置T0为方式0定时,T1为方式0计数 TMOD=0x40; //设置定时器0计数初值 TL0=0x18;TH0=0xE0; //设置定时器1计数初值 TL1=0x1B;TH1=0xFF; EA=1;ET0=1;ET1=1;//开中断 TR0=1; //启动T0 TR1=1; //启动T1 while(1); }