《蓝桥杯CT107D单片机竞赛板》:定时器模块
Posted Mascotttttt
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《蓝桥杯CT107D单片机竞赛板》:定时器模块相关的知识,希望对你有一定的参考价值。
定时器模块
实验简介
定时器配置实现LED亮灭,流水灯效果,蜂鸣器是否发声,继电器是否吸附,数码管示值,数字秒表。
实验原理图
实验原理
声明:实验原理部分来自普中51单片机攻略和《“蓝桥杯”全国软件和信息技术专业人才大赛(电子类)实训指导书》
-
定时器介绍:定时计数器可以用于精确事件定时。IAP15F2K61S2 单片机内部集成了 3 个 16 位的定时/计数器 T0、 T1 和 T2,其核心部件是一个加法计数器( TH 和 TL),对输入脉冲进行计数。若计数脉冲来自系统时钟,则为定时器方式;若计数脉冲来自 T0( P34)、 T1( P35)或 T2( P31)引脚,则为计数器方式。
-
知识补充:学习定时器需要了解CPU 时序的有关知识。 振荡周期: 为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期) 。机器周期:即CPU周期,完成一个基本操作所需要的时间。机器周期=1/单片机的内部时钟频率。内部时钟频率是外部时钟的
12 分频
,也就是说当外部晶振的频率输入到单片机里面的时候要进行 12分频。1 个机器周期含12 个振荡周期。指令周期:完成 1 条指令所占用的全部时间,它以机器周期为单位。外接晶振为 12MHz 时,振荡周期=1/12us;机器周期=1us;指令周期=1~4us;可知工作在定时模式时最高单次定时时间约为65535*1us=65ms < 100ms,也就是说单次定时无法达到0.1s,这点在后面的综合模块中会用到 -
特殊功能寄存器介绍:TMOD是定时/计数器的工作方式寄存器, 确定工作方式和功能; TCON是控制寄存器, 控制 T0、 T1 的启动和停止及设置溢出标志。
- 工作方式寄存器 TMOD。
工作方式寄存器 TMOD 用于设置定时/计数器的工作方式,低四位
用于 T0,高四位
用于 T1。GATE
是门控位,GATE = ,软件使 TR0 或 TR1 为 1,能启动定时/计数器工作。GATE = 1,软件使 TR0 或 TR1 为 1,再使外部中断引脚 INT0/1 也为高电平时, 才能启动定时/计数器工作。C/T
:定时/计数模式选择位。 C/T =0 为定时模式;C/T =1 为计数模式。M1M0
:定时/计数器 T0 和 T1 具有四种工作方式,由特殊功能寄存器 TMOD 中的 M1 和 M0 位决定,具体工作方式设置,下图示。
其中我们特别解释一下,方式 1 的计数位数是 16 位, 由 TL0 作为低 8 位, TH0 作为高 8 位, 组成了16 位加 1 计数器。 门控位 GATE = 0
,经过非门反相,再经过或门输出为1,此时仅由 TR0 控制与门的开启, 与门输出 1 时, 控制开关接通, 计数开始;而门控位 GATE = 1
,我们类比可以分析出,此时与门的开启由外中断引脚信号和 TR0 共同控制,由此解释了上述工作方式寄存器 TMOD中门控位GATE的相关赋值方式。方式1其结构图如下所示:
- 控制寄存器 TCON
TCON 的低 4 位用于控制外部中断,可以去《蓝桥杯CT107D单片机竞赛板》:中断模块查看。TCON 的高 4 位用于控制定时/计数器的启动和中断申请。TF1
:T1 溢出中断请求标志位。 T1 计数溢出时由硬件自动置 TF1为 1。CPU 响应中断后 TF1 由硬件自动清 0。 T1 工作时, CPU 可随时查询 TF1 的状态。 所以, TF1 可用作查询测试的标志。这点我们会在后面的综合应用中使用到,TF1 也可以用软件置 1 或清 0, 同硬件置 1 或清 0 的效果一样。TR1
:T1 运行控制位。TR1 = 1,定时器1工作,TR1 = 0,定时器停止工作。TR1 由软件置 1 或清 0。TF0
,和TR0
用法类似于定时器1。
- 定时器配置:①TMOD
设置定时器模式
,确定 T0 和 T1 的工作方式。②根据所要定时的时间计算初值
,并将其写入THx,TLx中,例如外部晶振12MHZ,定时1ms,每次获取输入脉冲,即经历了一个机器周期1us时间,1ms/1us=1000。计数 1000 个,对于方式1为16位的定时/计数器,由于计数器到65535 再加 1 才会溢出,故初值=65535-1000+1=64536=FC18H,所以初值即为 THx=0XFC,TLx=0X18。③若
使用中断,则对 EA 赋值,开放
定时器中断④启动
定时器的运行控制位TRx
实验程序
定时器0控制LED隔 1 秒闪烁
//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器
//typedef unsigned char uchar;
#define uchar unsigned char
#define uint unsigned int
#endif
//main.c--通过定时器 0中断控制 D1 指示灯间隔 1 秒闪烁。
#include "config.h"
uchar uled = 0;
void close_peripheral()
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0xaf;
P2 &= 0x1f;
void Timer0Init() //1000微秒@12.000MHz
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //打开定时器 0 中断允许
EA=1; //打开总中断
void main()
close_peripheral();
Timer0Init();
while(1);
void timer0() interrupt 1
static uint i;//静态变量存储器内部会自动赋初值为0
TL0 = 0x18; //设置定时初值,定时1ms
TH0 = 0xFC;
i++;
if (1000 == i)
i = 0;
uled ^= 1;
P2 = (P2 & 0x1f) | 0x80;
P0 = ~uled;
P2 &= 0x1f;
定时器0控制蜂鸣器和继电器
main.c代码主要改变部分
void timer0() interrupt 1
static uint i;//静态变量存储器内部会自动赋初值为0
TL0 = 0x18; //设置定时初值,定时1ms
TH0 = 0xFC;
i++;
if (1000 == i)
i = 0;
uled ^= 0x50;
P2 = (P2 & 0x1f) | 0xa0;
P0 = ~uled;
P2 &= 0x1f;
定时器1实现流水灯效果
//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器
#include<intrins.h>
//typedef unsigned char uchar;
#define uchar unsigned char
#define uint unsigned int
#endif
//main.c--通过定时器 1中断控制 LED 模块实现每隔0.5s移位
#include "config.h"
uchar time = 0;
void Timer1Init(void) //50毫秒@12.000MHz
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0xB0; //设置定时初值
TH1 = 0x3C; //设置定时初值
TF1 = 0; //清除TF1标志
TR1 = 1; //定时器1开始计时
ET1 = 1;//打开定时器1的中断允许
EA = 1;//打开总中断
void main()
uchar data1 = 0xfe;
Timer1Init();
while(1)
P2 = (P2 & 0x1f) | 0x80;
P0 = data1;
P2 &= 0x1f;
if (time >= 10)
time = 0;
data1 = (data1 << 1) | 0x01;
if(0xff == data1)
data1 = 0xfe;
void timer1() interrupt 3
time++;
TL1 = 0xB0; //设置定时初值
TH1 = 0x3C; //设置定时初值
定时器0每2ms对S7进行扫描,按下则n值加1,数码管显示
//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器
#include<intrins.h>
//typedef unsigned char uchar;
#define uchar unsigned char
#define uint unsigned int
void Delay20ms(); //@12.000MHz
#endif
//main.c--2ms对S7进行扫描,按下n值加1,数码管显示
#include "config.h"
sbit S7 = P3^0;
uchar dspcom = 0;
uchar dspbuf[8];
uchar n = 0;
//共阴数码管段选表
uchar tab[] = //标准字库
// 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
void close_peripheral()
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0xaf;
P2 &= 0x1f;
void Timer0Init(void) //2毫秒@12.000MHz
AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x30; //设置定时初值
TH0 = 0xF8; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1;//打开定时器0中断允许
EA = 1;//打开总中断
void display()
//消隐
P2 = (P2 & 0x1f) | 0xe0;
P0 = 0xff;
//位选
P2 = (P2 & 0x1f) | 0xc0;
P0 = 1 << dspcom;
//段选
P2 = (P2 & 0x1f) | 0xe0;
P0 = ~tab[dspbuf[dspcom]];
P2 &= 0x1f;
if (++dspcom == 8)
dspcom = 0;
void main()
close_peripheral();
Timer0Init();
while(1)
if (0 == S7)
Delay20ms();//消抖
if (0 == S7)
n++;
dspbuf[0] = n / 10;
dspbuf[1] = n % 10;
if (n >= 100)
n = 0;
while(!S7);
void timer0() interrupt 1
//重新赋初值
TL0 = 0x30; //设置定时初值,2毫秒
TH0 = 0xF8;
display();//每隔2ms扫描一次
void Delay20ms() //@12.000MHz
unsigned char i, j, k;
_nop_();
_nop_();
i = 1;
j = 234;
k = 113;
do
do
while (--k);
while (--j);
while (--i);
定时器1实现数字秒表–使用定时器1查询
注意:该实验与下一个实验区别可以观察Timer1Init()函数,以及TF1的使用
//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器
#include<intrins.h>
//typedef unsigned char uchar;
#define uchar unsigned char
#define uint unsigned int
void Delay20ms(); //@12.000MHz
#endif
//main.c--定时器1实现数字秒表
#include "config.h"
uchar dspcom = 0;
uchar dspbuf[8];
uint cnt;
uchar sec, min;//秒,分
//共阴数码管段选表
uchar tab[] = //标准字库
// 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
void close_peripheral()
P2 = (P2 & 0x1f) | 0x80;
P0 = 0xff;
P2 = (P2 & 0x1f) | 0xa0;
P0 = 0xaf;
P2 &= 0x1f;
void Timer1Init(void) //2毫秒@12.000MHz
AUXR &= 0xBF; //定时器时钟12T模式
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x10; //设置定时器模式
TL1 = 0x30; //设置定时初值
TH1 = 0xF8; //设置定时初值
TR1 = 1; //定时器1开始计时
void data_proc()
dspbuf[0] = 16;//tab[16] = 数码管灭
dspbuf[1] = 16;
dspbuf[2] = 16;
dspbuf[3] = 16;
dspbuf[4] = min / 10;
dspbuf[5] = min % 10;
dspbuf[6] = sec / 10;
dspbuf[7] = sec % 10;
void display()
//消隐
P2 = (P2 & 0x1f) | 0xe0;
P0 = 0xff;
//位选
P2 = (P2 & 0x1f) | 0xc0;
P0 = 1 << dspcom;
//段选
P2 = (P2 & 0x1f) | 0xe0;
P0 = ~tab[dspbuf[dspcom]];
P2 &= 0x1f;
if (++dspcom == 8)
dspcom = 0;
void main()
close_peripheral();
Timer1Init();
while(1)
if (TF1)//定时器T1溢出标志
data_proc();
display();//每隔2ms扫描一次
cnt++;
TF1 = 0;
//重新赋初值,每隔2ms
TL1 = 0x30; //设置定时初值
TH1 = 0xF8; //设置定时初值
if (cnt >= 500)
cnt = 0;
sec++;
if (sec >= 60)
sec = 0;
min++;
if (min >=60)
min = 0;
定时器1实现数字秒表
//config.h--用于声明头文件,声明函数,声明一些经常使用的变量或难书写的语句
#ifndef _CONFIG_H
#define _CONFIG_H
#include <STC15F2K60S2.H>//对应芯片函数头文件,定义了一些特殊功能寄存器
#include<intrins.h>
//typedef unsigned char uchar;
#define uchar unsigned char
#define uint unsigned int
#endif
以上是关于《蓝桥杯CT107D单片机竞赛板》:定时器模块的主要内容,如果未能解决你的问题,请参考以下文章