当前位置:   article > 正文

小白跟做江科大51单片机之基于定时器的按键控制LED流水灯_51定时器控制一个led亮

51定时器控制一个led亮

图1

图2

图3

 

图4

图3表示SYSclk的工作原理:因为ST89C52开发板上的晶振为12MHZ,所以系统会产生脉冲,慢慢达到12M,达到12MHZ之后经过上面的12兆分频的话,就是1兆赫兹,1兆赫兹1个周期就是1us。联通如图所示的计数器,就是每隔1us记一次数,记到最大值,产生中断。

图·5

SYSclk:系统时钟,即晶振周期,ST89C52开发板上的晶振为12MHZ。

定时器工作原理:如图4所示左边的计数系统会发送给定时器脉冲,计数器每隔一个脉冲就会加1,但因为是之前选择定时器工作模式是模式1,所以定时器只能接受到65535,到了65535就会溢出,TF0置于1,计数器归0,产生中断。 

寄存器是连接软硬件的媒介。

在单片机中寄存器就是一段特殊的RAM存储器一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式。

寄存器相当于一个复杂机器的“操作按钮。

每个定时器主要有两种寄存器:TCON TMOD。

TCON 包括:TF, TR, IE, IT。

定时器和中断结合:时钟计数,到了时间之后,定时器发起中断请求,中断导通后实现主函数的中断,先去执行中断函数,再执行主函数。

图6


编写代码的时候,首先编写TMOD=0X01;即0000 0001,倒数第3位为0表示是定时器状态,M1和M0为01表示工作在模式1,使用16位定时器;

低四位中GATE=0表示定时器只需要图2所示的TR0控制——因为从图3可知,中间那部分为计数单元,GATE如果给0,经过非门之后,得到1,INTO是或门,所以无需考虑它,计数单元只由TR0控制。

图7

编写定时器代码首先编写:TMOD=0X01;

图8

可位寻址:表示能分开,eg:P3=0;P3_1=1;

不可位寻址:表示不能分开

TF=0;表示不会刚开始就去申请中断

TR0=1;TR表示定时器是否开始,TR=1表示开启,TR=0表示中断

图9

关于计时问题

0~65535

每隔1us计数加一

总共定时时间65535us

开始定64535离计数器溢出差值1000,所以计时时间为1ms

TH0和TL0是存储数值的,其中TH0存储的是高位,TL0存储的是低位

所以定时器存储数据代码为:

TH0=64535/256

TL0=64535%256

ET0=1;//打开定时器0 中断允许

EA=1;//打开总中断

PT=0;//优先级默认是低位

到此定时器模块函数构造完成。


time0.c代码

#include <REGX52.H>
void Timer0_Init(void)        //1毫秒@12.000MHz
{
    //这里只用到一个定时器,一个就行
    TMOD &= 0xF0;            //设置定时器模式
    TL0 = 0x18;                //设置定时初始值
    TH0 = 0xFC;                //设置定时初始值
    TF0 = 0;                //清除TF0标志
    TR0 = 1;                //定时器0开始计时
    ET0=1;         //打开定时器0 中断允许
    EA=1;          //打开总中断
    PT0=0;          //优先级为0
}

中断部分的代码不需要调用,直接就能运行,原理已在之前讲过。

time0.h包含time0.c的函数,INTRINS.H是为了使用_crol_和_cror_函数

main.c代码

#include <REGX52.H>
#include "time0.h"
#include "Delay.h"
#include <INTRINS.H>
unsigned char flag=0;
unsigned int time=0;
void main()
{
    P2=0xfe;
    Timer0_Init();
    while(1)
    {
        if(P3_1==0)
        {
            Delay(20);
            while(P3_1==0);
            Delay(20);
            time++;
            if(time%2!=0)
            {
                flag=1;
            }
            else
            {
                flag=0;
            }
        }
        
    }
}

void Timer0_Routine()  interrupt 1
{
    static unsigned int count;
    count++;
    TL0 = 0x18;                //设置定时初始值否则从0开始计数
    TH0 = 0xFC;                //设置定时初始值
    if(count>=1000)
    {
        count=0;
        if(flag!=0)
        {
            P2=_crol_(P2,1);
        }
        else
        {
            P2=_cror_(P2,1);
        }
    }
}

最终效果可实现按键控制LED灯左右移动。

基于定时器的按键控制LED流水灯


自己做了一下按第一个按键LED流水灯向右移动,按第二个按键向左移动的代码。

#include <REGX52.h>
#include <time0.h>
#include <Delay.h>


unsigned char num=0;
unsigned char flag;

void main()
{
    time0_init();
  while(1)
 {
   if(P3_1==0)
     {
         Delay(20);
         while(P3_1==0);
         Delay(20);
         flag=1;
     }
    if(P3_0==0)
     {
         Delay(20);
         while(P3_0==0);
         Delay(20);
        flag=0;
     }
 }
}

void Timer0_Routine()  interrupt 1
{
    static unsigned int count;
    count++;
    TL0 = 0x18;                //设置定时初始值否则从0开始计数
    TH0 = 0xFC;                //设置定时初始值
        if(count>=1000)
        {
            count=0;
            if(flag==1)   //LED流水灯向做右移动的代码
            {
                     if(num<8)
                     {
                         P2=~(0x01<<num);
                         num++;
                         if(num==8)
                         {
                             num=0;
                         }
                     }
          }
            else   //LED流水灯向做左移动的代码
            {  
                 if(num>0)
                 {
                     num--;
                     P2=~(0x01<<num);
                     if(num==0)
                     {
                         num=8;
                     }
                 }
            }
        }    
}

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/726926
推荐阅读
相关标签
  

闽ICP备14008679号