本节包含以下内容:7-1 定时器、7-2 按键控制LED流水灯模式&定时器时钟,时钟基于LCD1602显示
本笔记默认学习者已拥有:
1.Keil5和stc烧写工具 等各种软件、驱动、环境;
2.有一个属于自己的 51单片机开发板及相关零件 ;
3.认识C语言的语法;
本人使用的51开发板为 郭天祥C51 TX-1C增强版开发板 ;
本笔记根据B站up主:江科大自化协的教学视频 整理得到ヾ(•ω•)
7-1 定时器
之前我们使用的 按键、数码管、LCD1602都是 单片机I/O控制的 外设,
但定时器的电路在单片机内部,它是单片机的内部设备;
(3)操作系统的任务切换,像一些高级的单片机,它里面就有一个专门的系统的 滴答定时器,
它可以用来计时,让操作系统来执行多任务;
可以参考 STC89C52.pdf(提取码:ncst) 中的 第7章定时器/计数器;
T为Timer的缩写,即定时器;
原理分析
本节只分析 模式1 的 工作模式;
原理——计数系统
TL=Timer_Low,TH=Timer_High,计数系统能 记两个字节,高字节为TH,低字节为TL,
0代表它是 定时器0,计数系统 可以存[0,65535]这个范围内的数
1.时钟每给 计数系统 提供一个脉冲,16位计数器 中的值就会+1;
2.当 16位计数器 已经加到65535时,再给其脉冲,就会产生溢出,计数器就会回到0的位置;
即\(65535+1=0\),而其溢出时会置一个 标志位,即TF0(Timer_Flag 0),有标志位,它就会向中断系统申请中断;
原理——时钟
TX-1C开发板的晶振为11.0592MHz;
1.时钟有两个来源,一个为SYSclk(system_clock),另一个为T0 Pin,T0 Pin是单片机的外部接口;
2.时钟可以由 系统时钟提供,也可以由外部引脚来提供,当它由 外部引脚 来提供时钟时,定时器 即为 计数器;
本节不介绍其 计数器 的功能,只介绍 时钟 由 系统时钟 来提供 计数脉冲;
3.12M 的脉冲一般会进行 分频,默认的 12T模式 会将 12M脉冲 进行 12分频,则输出频率为 1MHz;
1Mhz 一周期为 1微秒,即计数单元每隔 1微秒 就会记一次数;
4. \(C / \overline{T}\) 是一种选择开关,\(\overline{T}\)代表寄存器中的一位,这种开关是控制时钟的提供来源的,
如果这一位配置为1,就会执行\(C(counter 计数器 )\)的功能,
如果这一位配置为0,就会执行\(T(Timer定时器)\)的功能;
本节使用 12T模式,\(C / \overline{T}\)配置为1,使用系统时钟为 时钟 提供脉冲;
原理——中断系统
中断 相当于 程序可以同时执行两项任务;
外部中断2、外部中断3是 STC89C52型号增加的中断源,新型号单片机对于老型号单片机 功能上是向下兼容的;
PPT中 中断源 少了一个 定时器2中断;
RX、TX也是串口中断;
1.单片机通过配置寄存器来控制内部线路的连接;
2.开关到底处于哪一位置,是由寄存器来控制的;
3.M1/M0是控制其处于哪种模式,GATE是门控端,TR0(Timer_Ready)控制定时器是否启动;
4.TCON(Timer_Control),TMOD(Timer_Mode);
5.IE是中断使能端;
6.在定时器电路中,GATE连接着 非门(一个三角形连接着一个圆圈,即 左侧给1 右侧为0);
非门 前面有个 弯月芽形状 为 或门(有1即1+);
再往前 半圆弧方块 为 与门(有0即0);
相关知识的详细 请参考 STC89C52.pdf(提取码:ncst)
7-2 按键控制LED流水灯模式&定时器时钟
如下为定时器0的模块
Timer0.c
#include<reg51.h>
/**
* @brief 定时器0初始化,1毫秒@11.0592MHz
* @param 无
* @retval 无
*/
void Timer0_Init(void){ //定时器初始化
//TMOD=0x01; //0000 0001 设置模式
TMOD&=0xF0; //把TMOD的低四位清零,高四位保持不变
TMOD|=0x01; //把TMOD的最低位置1,高四位保持不变
//不可位寻址寄存器 不能 将每一位单独赋值
// 可位寻址寄存器 能 将每一位单独赋值
TF0=0; //中断溢出标志位 TF0=1 表示 产生中断
TR0=1; //定时器是否开启
TL0=0x66;
TH0=0xFC;
ET0=1;
EA=1;
PT0=0;
}
/*
定时器中断函数模板
void Timer0_Routine() interrupt 1{
static unsigned int T0Count;
TL0=0x66;
TH0=0xFC;
++T0Count;
if(T0Count>=1000){
T0Count=0;
led1=~led1;
}
}
*/
Timer0.h
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0_Init(void);
#endif
以下为独立按键的模块
Key.c
#include<reg51.h>
#include<Delayms.h>
/**
* @brief 获取独立按键键码
* @param 无
* @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
*/
unsigned char Key(){
unsigned char KeyNumber=0;
if(T0==0){ Delayms(20);while(T0==0);Delayms(20); KeyNumber=1; }
if(T1==0){ Delayms(20);while(T1==0);Delayms(20); KeyNumber=2; }
if(WR==0){ Delayms(20);while(WR==0);Delayms(20); KeyNumber=3; }
if(RD==0){ Delayms(20);while(RD==0);Delayms(20); KeyNumber=4; }
return KeyNumber;
}
Key.h
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key(void);
#endif
按键控制LED流水灯模式.c
#include<reg51.h>
#include<Timer0.h>
#include<Key.h>
#include<INTRINS.h>
unsigned char KeyNum;
unsigned int LEDMode;
void main(){
P1=0xFE;
Timer0_Init();
while(1){
KeyNum=Key();
if(KeyNum==1) LEDMode=(LEDMode+1)%2;
}
}
void Timer0_Routine() interrupt 1{
static unsigned int T0Count;
TL0=0x66;
TH0=0xFC;
++T0Count;
if(T0Count>=500){
T0Count=0;
if(LEDMode==0) P1=_crol_(P1,1);
else P1=_cror_(P1,1);
//_crol_ 循环左移
//_cror_ 循环右移
}
}
运行结果如下
定时器时钟.c
#include<reg51.h>
#include<Delayms.h>
#include<LCD1602.h>
#include<Timer0.h>
unsigned char Sec=55,Min=59,Hour=23;
void main(){
LCD_Init();
Timer0_Init();
LCD_ShowString(1,1,"Clock:");
LCD_ShowString(2,1," : : ");
while(1){
LCD_ShowNum(2,1,Hour,2);
LCD_ShowNum(2,4,Min,2);
LCD_ShowNum(2,7,Sec,2);
}
}
void Timer0_Routine() interrupt 1{
static unsigned int T0Count;
TL0=0x66;
TH0=0xFC;
++T0Count;
if(T0Count>=1000){
T0Count=0;
++Sec;
if(Sec>=60){
Sec=0;
++Min;
if(Min>=60){
Min=0;
++Hour;
if(Hour>=24) Hour=0;
}
}
}
}
运行结果如下
相关知识
一般晶振上会标有数字,表示其为 x MHz,我的开发板 晶振 为 11.0592MHz;