zoukankan      html  css  js  c++  java
  • 51单片机 第七节 定时器

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

  • 相关阅读:
    Android学习笔记:TabHost 和 FragmentTabHost
    JS兼容性处理
    【题解】数颜色--带修改莫队
    技巧--对拍
    学习笔记--数论--莫比乌斯反演初认识
    【题解】售票系统--一道毒瘤题
    【题解】P3391 文艺平衡树
    学习笔记--计算几何
    题解 P2661 【信息传递】
    学习笔记--简化剩余系与欧拉函数φ( )
  • 原文地址:https://www.cnblogs.com/Potrem/p/51_7.html
Copyright © 2011-2022 走看看