本節包含以下內容: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;