LQB04 定时器代码使用01,定时闪烁灯和定时框架。
创始人
2024-05-26 15:28:07
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.0592MHztypedef 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 0001choose573(LED);LEDbuf = LEDbuf ^ 0x01;P0= LEDbuf;choose573(0);	}if(cnt500msT0==500){cnt500msT0=0;//LED2取反;choose573(LED);  //0000 0010LEDbuf = 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 1100LEDbuf = LEDbuf ^ 0x0C;P0= LEDbuf;choose573(0);}}
//-----------------------------------------------
//中断服务程序
void t2int() interrupt 12           //中断入口
{cnt1msT2++;if(cnt1msT2==1000){cnt1msT2=0;//LED 取反choose573(LED);  //0011 0000LEDbuf = 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;}
}

相关内容

热门资讯

【NI Multisim 14...   目录 序言 一、工具栏 🍊1.“标准”工具栏 🍊 2.视图工具...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
Android|无法访问或保存... 这个问题可能是由于权限设置不正确导致的。您需要在应用程序清单文件中添加以下代码来请求适当的权限:此外...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
AsusVivobook无法开... 首先,我们可以尝试重置BIOS(Basic Input/Output System)来解决这个问题。...
ASM贪吃蛇游戏-解决错误的问... 要解决ASM贪吃蛇游戏中的错误问题,你可以按照以下步骤进行:首先,确定错误的具体表现和问题所在。在贪...
月入8000+的steam搬砖... 大家好,我是阿阳 今天要给大家介绍的是 steam 游戏搬砖项目,目前...