LQB04 定时器代码使用01,定时闪烁灯和定时框架。

43 篇文章 0 订阅

1、STC-ISP软件定时函数的生成,定时案例库的学习;
2、定时器0,闪烁LED1;定时500ms,间隔
定时器1,闪烁LED2,定时800ms,间隔。
3、快速搭建框架。
这里只讲解直接的使用,不讲解内部细节。
定时器,stc15单片机有定时器0,1,2,这三个使用。
传统的51单片机也有0,1,2三个,但是定时器2的寄存器名称不一样;需要注意;

stc15单片机的定时器模式0,都可以自动重装,而传统的不型,需要手动每次在中断函数里面设置初值,达到重装初值的效果;

stcISP软件的定时器的使用。

定时初值的产生。
定时初值的话,需要理解一下。
stc15单片机定时器,比赛的时候,都是设置16位模式,。
定时器是一个房间,这个房间容量可以设置,一般设置16位模式,就是说这个房间最大可以放入0-2的16次方,就是说0-65535个数字,数字到了65535,就会产生溢出,或者你可以设定一个初值,不从0开始放数据,而从一个初值N,比如60000放数据,那么60000到65535需要计数15535次,之后,就到了65535,也会产生溢出。控制初值,就能够控制定时的时间,每次计数假如是1秒钟,那么就需要15535秒。
但是这个计数时基51单片机是可调的,一般设置12分频,假如单片机晶振是12Mhz,那么就是1Mhz频率加一,就是1个微秒加一次,频率等于周期的倒数,可以算出这个1微秒。
但是比赛一般要求是11.0592M,那么除以12除不尽,因此会有误差。如果要精密产生,需要对误差进行补偿,比赛的时候不用管这个误差。

如果溢出了,如果打开定时器的中断,也打开了EA总的中断,那么就会第一个跳到中断服务函数里面执行代码,这个中断服务函数有个中断入口,在stc15的头文件已经定义好了,不用我们管。第二个同时会把房间清空,如果具备自动重装功能,那么就会从初值开始,继续加到65535就溢出,如果没自动重装功能,需要用代码再设置一次初值。

综上思路,需要1、设定定时初值;
2、打开定时器开关TR,TR=0关闭定时器,TR=1打开定时器,相当于一个叫做TR的水龙头;
3、打开定时器中断ET0,ET0负责定时器0,ET1负责定时器1;
具体上述流程可以看STC-ISR软件的代码,
4、打开单片机的总中断EA,EA=1,就是打开,EA=0;关闭。

了解了上述的要点,我们还要知道一点,假如设置16位定时器模式,单片机是8位单片机,一个寄存器放不了16位那么多的数据,因此对于定时器0分为了TH0,TL0两个定时器,放高8位数据,TL0放低八位的数据。
因此,我们需要把定时初值,拆开位高8位和低8位,放到具体寄存器中。

STCISP案例代码也有具体的思路,可以直接拿来用。。

STCISP代码解读。

代码1,定时器0模式0,16位重装,C语言。
在这里插入图片描述
具体代码,解读视频链接看B站我的LQBNEW系列,LQB04

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 定时器0的16位自动重装载模式举例---------------*/
/* --- Mobile: (86)13922805190 -------------- -------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966-------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* --- Web: www.GXWMCU.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
/* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序        */
/*---------------------------------------------------------------------*/

//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz


#include "reg51.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;

//-----------------------------------------------

#define FOSC 11059200L

#define T1MS (65536-FOSC/1000)      //1T模式
//#define T1MS (65536-FOSC/12/1000) //12T模式

sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;

sfr AUXR = 0x8e;                    //Auxiliary register
sbit P10 = P1^0;

//-----------------------------------------------

/* Timer0 interrupt routine */
void tm0_isr() interrupt 1 using 1
{
    P10 = ! P10;                    //将测试口取反
}

//-----------------------------------------------

/* main program */
void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
    P6M0 = 0x00;
    P6M1 = 0x00;
    P7M0 = 0x00;
    P7M1 = 0x00;

    AUXR |= 0x80;                   //定时器0为1T模式
//  AUXR &= 0x7f;                   //定时器0为12T模式

    TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
    TL0 = T1MS;                     //初始化计时值
    TH0 = T1MS >> 8;
    TR0 = 1;                        //定时器0开始计时
    ET0 = 1;                        //使能定时器0中断
    EA = 1;

    while (1);
}


解读
第一行,包括头文件,这里包括的是传统的头文件,因此后面需要加很多行sfr P0M1 = 0x93;
sfr P0M0 = 0x94;定义之类的。
如果直接包括的是stc15的头文件,就不用这么多行。因为已经包括了。
在这里插入图片描述
第二个,用宏定义,定义了晶振,下载频率选择11.0592M,后面有个L,是为了防止编译的时候出错。

第三个,如果你后面设置的是1T模式,那么就要这行;
如果用12T模式,用第四行。两个只能二选一。
可以看到12T模式,慢一些,因为包括多了/12》
在这里插入图片描述
stc15单片机多的一些寄存器的定义,由于reg51头文件没包括,所以这里写多一些。
我们如果比赛的使用stc15h头文件,不需要自己再写这些。

在这里插入图片描述
定时器0的中断函数,我们不需要声明这个函数,系统自带的。
只需要修改里面的代码。

在这里插入图片描述
1是让stc15的IO口都是双向输出模式,其实stc15蓝桥杯的单片机,不用这些也行,默认是双向口,如果用其他单片机,不太确定的话,最好加上这些,那么效果就是既能够作为输入,也能当输出了。
不然有些IO口智能作为输出口,有些只能做输入口,不能两个兼顾。

2是用AUXR设置定时器0是1T模式还是12T模式,可以看下AUXR寄存器,看芯片手册,stc15单片机手册。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
AURX |=0x80;意思是或1000 0000,将B7位设置位1,其他位保持不变,那么就是等于T0X12=1,
那么就设置了1T模式,快速模式。
在这里插入图片描述
AUXR
AUXR &=0x7F;目的就是让与0111 1111,将最高位设置位0,其他不变,
那么就是传统的51单片机速度。

在这里插入图片描述
TMOD=0x00;
看下TMOD寄存器;
在这里插入图片描述
在这里插入图片描述
TMOD=0x00.
这个寄存器,都是00000000.
看功能,都是模式0,自动16位重装模式。
C、T位也是等于0,等于定时器模式。如果等于1等于计数器模式。这里是用来做定时器。

注意如果定时器0作为定时器,定时器器1作为计数器,那么就是设置
TMOD=01000000=0x40;请注意理解。。。。

在这里插入图片描述
这个是初值的赋值。
把初值分解位高八位和低八位。
高八位是直接右移8位;放到TH0中
低八位是不管。因为空间就这么大,就小的先进去,大的放不进去,就不能放了。放到TL0中。

在这里插入图片描述
T1MS,这个是宏定义写的。

在这里插入图片描述
三个控制开关,
定时器0的开关TR0;
定时器0的中断开关,有时候还定时器不一定要中断,所以有时候不用开定时器中断‘’
单片机的总中断,EA;

后面while1大循环。

定时1ms时间到,就进入到中断函数了,执行IO口的翻转。

问题,如果我要定时100ms怎么办?
定时1秒怎么办?

这个时候,我们需要设置一个全局变量,计算1ms的个数,如果到了100次到了100ms,就让这个变量归0,那么就可以实现100ms。

/* Timer0 interrupt routine */
int cnt1ms=0;
void tm0_isr() interrupt 1 using 1
{
cnt1ms++;
if(cnt1ms==100)
{
P10=~P10;
cnt1ms=0;//归0
}
   
}

问题,如果我要10ms干一个事情,20ms干一个事情,35ms干一个事情,怎么实现,分时循环的目标?

修改代码。

int cnt1ms=0;
int cnt35ms=0;
void tm0_isr() interrupt 1 using 1
{
	cnt1ms++;
	cnt35ms++;
	if(cnt1ms%10==0)
	{
		P10=~P10;
	}
	if(cnt1ms%20==0)
	{
		P20=~P20;
		cnt1ms=0;
	}
	if(cnt35ms==35)
	{
		P21=~P21;
		cnt35ms=0;
	}
   
}

其他定时器也是一样。
在这里插入图片描述

定时器1的16位定时模式

注意中断函数名不一样,因为入口不一样;
注意寄存器有些名字也不一样,TH1,TL1,TR1,这些。

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 定时器1的16位自动重装载模式举例---------------*/
/* --- Mobile: (86)13922805190 -------------- -------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966-------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* --- Web: www.GXWMCU.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
/* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序        */
/*---------------------------------------------------------------------*/

//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz


#include "reg51.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;

//-----------------------------------------------

#define FOSC 11059200L

#define T1MS (65536-FOSC/1000)      //1T模式
//#define T1MS (65536-FOSC/12/1000) //12T模式

sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;

sfr AUXR = 0x8e;                    //Auxiliary register
sbit P10 = P1^0;

//-----------------------------------------------

/* Timer1 interrupt routine */
void tm1_isr() interrupt 3 using 1
{
    P10 = ! P10;                    //将测试口取反
}

//-----------------------------------------------

/* main program */
void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
    P6M0 = 0x00;
    P6M1 = 0x00;
    P7M0 = 0x00;
    P7M1 = 0x00;

    AUXR |= 0x40;                   //定时器1为1T模式
//  AUXR &= 0xdf;                   //定时器1为12T模式

    TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
    TL1 = T1MS;                     //初始化计时值
    TH1 = T1MS >> 8;
    TR1 = 1;                        //定时器1开始计时
    ET1 = 1;                        //使能定时器0中断
    EA = 1;

    while (1);
}


定时2模式

/*---------------------------------------------------------------------*/
/* --- STC MCU Limited ------------------------------------------------*/
/* --- STC15F4K60S4 系列 定时器2的16位自动重装载模式举例---------------*/
/* --- Mobile: (86)13922805190 -------------- -------------------------*/
/* --- Fax: 86-0513-55012956,55012947,55012969 ------------------------*/
/* --- Tel: 86-0513-55012928,55012929,55012966-------------------------*/
/* --- Web: www.STCMCU.com --------------------------------------------*/
/* --- Web: www.GXWMCU.com --------------------------------------------*/
/* 如果要在程序中使用此代码,请在程序中注明使用了STC的资料及程序        */
/* 如果要在文章中应用此代码,请在文章中注明使用了STC的资料及程序        */
/*---------------------------------------------------------------------*/

//本示例在Keil开发环境下请选择Intel的8058芯片型号进行编译
//若无特别说明,工作频率一般为11.0592MHz


#include "reg51.h"

typedef unsigned char BYTE;
typedef unsigned int WORD;

//-----------------------------------------------

#define FOSC 11059200L

#define T1MS (65536-FOSC/1000)      //1T模式
//#define T1MS (65536-FOSC/12/1000) //12T模式

sfr P0M1 = 0x93;
sfr P0M0 = 0x94;
sfr P1M1 = 0x91;
sfr P1M0 = 0x92;
sfr P2M1 = 0x95;
sfr P2M0 = 0x96;
sfr P3M1 = 0xb1;
sfr P3M0 = 0xb2;
sfr P4M1 = 0xb3;
sfr P4M0 = 0xb4;
sfr P5M1 = 0xC9;
sfr P5M0 = 0xCA;
sfr P6M1 = 0xCB;
sfr P6M0 = 0xCC;
sfr P7M1 = 0xE1;
sfr P7M0 = 0xE2;

sfr IE2       = 0xaf;               //中断使能寄存器2
sfr AUXR      = 0x8e;               //辅助寄存器
sfr T2H       = 0xD6;               //定时器2高8位
sfr T2L       = 0xD7;               //定时器2低8位

sbit P10 = P1^0;

//-----------------------------------------------
//中断服务程序
void t2int() interrupt 12           //中断入口
{
    P10 = !P10;                     //将测试口取反
      
//  IE2 &= ~0x04;                   //若需要手动清除中断标志,可先关闭中断,此时系统会自动清除内部的中断标志
//  IE2 |= 0x04;                    //然后再开中断即可
}

//-----------------------------------------------

/* main program */
void main()
{
    P0M0 = 0x00;
    P0M1 = 0x00;
    P1M0 = 0x00;
    P1M1 = 0x00;
    P2M0 = 0x00;
    P2M1 = 0x00;
    P3M0 = 0x00;
    P3M1 = 0x00;
    P4M0 = 0x00;
    P4M1 = 0x00;
    P5M0 = 0x00;
    P5M1 = 0x00;
    P6M0 = 0x00;
    P6M1 = 0x00;
    P7M0 = 0x00;
    P7M1 = 0x00;

    AUXR |= 0x04;                   //定时器2为1T模式
//  AUXR &= ~0x04;                  //定时器2为12T模式
    T2L = T1MS;                     //初始化计时值
    T2H = T1MS >> 8;
    AUXR |= 0x10;                   //定时器2开始计时
    
    IE2 |= 0x04;                    //开定时器2中断
    EA = 1;

    while (1);
}


比赛的时候,一般定时1ms就够了,如果你要定时5ms,就类似上面的思路,定义一个全局变量,不断累加。
当然,你也可以设置初值。可以用这生成,也可以修改
在这里插入图片描述
修改,这个1000代表1ms,如果要2ms,将1000改为2000
在这里插入图片描述

编程实验。 LED1间隔300ms闪烁 LED2间隔500ms闪烁; 蜂鸣器间隔600ms发声。

代码如下,手打代码过长见B站我的网址,LQBNEW系列,LQB04;

//定时器0---LED1,300ms闪烁  LED2,500ms闪烁
//定时器1---LED3和LED4,200ms闪烁
//定时器2----LED 5和LED6,1s闪烁
#include "stc15.h"
//若无特别说明,工作频率一般为11.0592MHz

typedef unsigned char BYTE;
typedef unsigned int WORD;

int  cnt300msT0=0,cnt500msT0=0;
int  cnt1msT1=0;
int  cnt1msT2=0;
//-----------------------------------------------
#define FOSC 11059200L
#define T1MS (65536-FOSC/1000)      //1T模式
//-----------------------------------------------

#define LED 4
#define ULN 5
#define COM 6
#define ABC 7
unsigned char LEDbuf;  //缓冲变量
unsigned char ULNbuf; //缓冲变量

void choose573(unsigned char x);   //函数具体定义在main后面,需要声明


/* Timer0 interrupt routine */
void tm0_isr() interrupt 1 using 1
{
	cnt300msT0++;
	cnt500msT0++;
	if(cnt300msT0==300)
	{
	    cnt300msT0=0;
		//LED1取反; 让P00取反   0000 0001
		choose573(LED);
		LEDbuf = LEDbuf ^ 0x01;
		P0= LEDbuf;
		choose573(0);	
	}
	if(cnt500msT0==500)
	{
	    cnt500msT0=0;
		//LED2取反;
			choose573(LED);  //0000 0010
		LEDbuf = LEDbuf ^ 0x02;
		P0= LEDbuf;
		choose573(0);	
	}
    
}

/* Timer1 interrupt routine */
void tm1_isr() interrupt 3 using 1
{
	cnt1msT1++;
	if(cnt1msT1==200)
	{
	       cnt1msT1=0;
		//动作
		//LED3,4取反;
			choose573(LED);  //0000 1100
		LEDbuf = LEDbuf ^ 0x0C;
		P0= LEDbuf;
		choose573(0);
	}
	
	
}
//-----------------------------------------------
//中断服务程序
void t2int() interrupt 12           //中断入口
{
	cnt1msT2++;
	if(cnt1msT2==1000)
	{
	      cnt1msT2=0;
		//LED 取反
				choose573(LED);  //0011 0000
		LEDbuf = LEDbuf ^ 0x30;
		P0= LEDbuf;
		choose573(0);
	}
   
}

//-----------------------------------------------
/* main program */
void main()
{

    AUXR |= 0x80;                   //定时器0为1T模式
	  AUXR |= 0x40;                   //定时器1为1T模式
    AUXR |= 0x04;                   //定时器2为1T模式
	
    TMOD = 0x00;                    //设置定时器为模式0(16位自动重装载)
    TL0 = T1MS;                     //初始化计时值
    TH0 = T1MS >> 8;
	  TL1 = T1MS;                     //初始化计时值
    TH1 = T1MS >> 8;   
	  T2L = T1MS;                     //初始化计时值
    T2H = T1MS >> 8;
    TR0 = 1;                        //定时器0开始计时
    ET0 = 1;                        //使能定时器0中断
	
	  TR1 = 1;                        //定时器1开始计时
    ET1 = 1;                        //使能定时器0中断
	
	  AUXR |= 0x10;                   //定时器2开始计时  
	  IE2 |= 0x04;                    //开定时器2中断
    EA = 1;

    while (1);
	

}

void choose573(unsigned char x)
{
	switch(x)
	{
		case 0:
			P2 =P2&0x1F;break;
		case LED:
			P2 =(P2&0x1F)|0x80;break;
		case ULN:
			P2 =(P2&0x1F)|0xA0;break;
   	case COM:
			P2 =(P2&0x1F)|0xC0;break;
	 	case ABC:
			P2 =(P2&0x1F)|0xE0;break;
		default:break;
	}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值