蓝桥杯模块学习8——定时器中断(深夜学习——单片机)

目录

一、定时器工作过程:

二、中断过程:(具体参考上一节)

三、定时器相关寄存器:

1、TCON(Timer Control)定时器控制寄存器:

2、TMOD(Timer Mode)定时器模式控制寄存器:(不可位寻址)

3、IE(Interrrupt Enable)中断允许寄存器:

4、AUXR(auxiliary)辅助寄存器:

四、计算定时器初值:

五、定时器实验: 

1、代码思路:

2、宏定义:

3、主函数:


一、定时器工作过程:

        系统时钟或者外部传入脉冲信号给定时计数器,定时器就会加一,而定时计数器TX分为高八位THX,低八位TLX即十六位,假设这十六位都用上就有65536位,当定时计数器计数到65535次,下一次就会溢出,导致系统发生中断,也就是定时器中断。

        其中12分频的意思是系统产生12次脉冲才传给定时计数器1次

二、中断过程:(具体参考上一节)

蓝桥杯模块学习7——外部中断(深夜学习——单片机)_佛科院深夜学习的博客-CSDN博客https://blog.csdn.net/weixin_63568691/article/details/128498447?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22128498447%22%2C%22source%22%3A%22weixin_63568691%22%7D

三、定时器相关寄存器:

1、TCON(Timer Control)定时器控制寄存器:

(1)TF0、TF1:定时器溢出标志位,由硬件自动置“1”“0”,我们不用管。

(2)TR0、TR1:定时器运行控制位:当GATE=0时,置“1”开始计数。(还有另一种情况我们没用到,详情看手册)

2、TMOD(Timer Mode)定时器模式控制寄存器:(不可位寻址)

(1)GATE:没用到,置“0”就行

(2)C/T:Clock/Timer,计数器/定时器,置“1”为计数器

(2)M1、M2:设置四种不同的工作模式,这里我们选择模式0,即00,16位自动重装载模式,当溢出时RL_THx、RL_TLx存放的自动装入TH1、TL1

3、IE(Interrrupt Enable)中断允许寄存器:

(1)ET0、ET1:定时器0、1溢出中断允许位,“1”为允许

(2)EA:总中断允许位,"1"为允许,相当于总闸

4、AUXR(auxiliary)辅助寄存器:

 (1)T0x12、T1x12:定时器速度选择位:置“0”,12T;置“1”,1T模式;置“0”,12T模式(晶振振动12次单片机完成1个机器周期即计数1次)

四、计算定时器初值:

        我们知道定时器是从0一直累加到65535直到溢出,一共计数65536次,每记一次数就相当于晶振振动12次(12T模式),假设晶振频率为12MHZ,也就是每振动相当于1/12us,由此我们可以得到定时器最大计时时间:65536*12*1/12=65536us。

        而我们如果要每次计时1ms怎么办呢?这时候就要设置定时器初值使技术次数减少,1ms=1000us,每计数一次就相当于1us,即初值要为(65536-1000),让定时器计数1000次就溢出。

        根据第一大点我们可以知道,定时器是用THx高八位,TLx低八位存储16位数的,所以

THx=(65536-计时次数)/ 256,THx=(65536-计时次数)% 256

(如果晶振频率为12MHZ,计时次数=计时多少微秒)

        特别的:由于模式0采用16位自动重装载模式,所以我们不需要每次重新载入初值,只需要载入一次就行

五、定时器实验: 

        实现功能:利用定时器T0的模式0实现间隔定时,每隔1秒L1闪烁一下,也就是亮0.5秒,灭0.5秒; 每隔10秒L8闪烁一下

1、代码思路:

        首先配置和开启定时器0,编写中断服务函数控制灯的亮灭

2、宏定义:

#ifndef _PUBLIC_H
#define _PUBLIC_H

#include "STC15F2K60S2.H" 

#define u8 unsigned char
#define u16 unsigned int

void Delay_1ms(u16 num);
void Close_All(void);
void Delay_10us(u16 num);
#endif
#include "Public.h"
// 延时函数(最小约1ms@12MHz)
void Delay_1ms(u16 num)
{
  unsigned int i;
  while(num--)
    for(i=0; i<628; i++);
}


/*
	输入变量:无
	输出变量:无
	功能:关闭蜂鸣器和继电器
*/
void Close_All(void)
{
	//关闭蜂鸣器和继电器
	P0 = 0x00;
	P2 = (P2 & 0x1f) | 0xA0;
	P2 &= 0x1f;
	//关闭LED灯
	P0 = 0xff;
	P2 = (P2 & 0x1F) | 0x80;
	P2 &= 0x1f;	
}

void Delay_10us(u16 num)
{
  u16 i;
  while(num--)
    for(i=0; i<3; i++);
}

3、主函数:

// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "Public.h"

sbit L1 = P0^0;
sbit L8 = P0^7;
u16 count;
u8 sign1,sign2;

void Timer_0_Init(u16 time);
// 主函数
void main(void)
{
	Close_All();	
	Timer_0_Init(50000);//50ms
	//默认为开灯
	L1 = 0;
	L8 = 0; 
  while(1)
  { 
		if(sign1 == 1)
		{
			L1 = !L1;
			P2 = (P2 & 0x1f) | 0x80;
			P2 &= 0x1f;
			sign1 = 0;
		}
		if(sign2 == 1)
		{
			L8 = !L8;
			P2 = (P2 & 0x1f) | 0x80;
			P2 &= 0x1f;
			sign2 = 0;
		}
  }
}

/*
	输入变量:定时时长___us
	输出变量:无
	功能:配置并开启定时器0
*/
void Timer_0_Init(u16 time)
{
	//12T模式
	AUXR &= 0x7f;
	//定时器0 模式0
	TMOD &= 0xf0;
	//设置初值
	TH0 = (65536-time)/256;
	TL0 = (65536-time)%256;
	//打开中断
	ET0 = 1;
	EA = 1;
	//开始计数
	TR0 = 1;
}

void Timer_0_IT(void) interrupt 1
{
	count++;
	if(count%10 == 0)
		sign1 = 1;
	if(count%100 == 0)
		sign2 = 1;
	if(count == 200)
		count = 0;
}

更新:对LED代码进行更新

4、主函数:(优化)

// 使用程序前,将J13调整为IO模式(2-3脚短接)
#include "Public.h"


u16 count;
u8 sign,last_led = 0xff;

void Timer_0_Init(u16 time);
void LED_ON_Lx(u8 L_X);
// 主函数
void main(void)
{
	Close_All();	
	Timer_0_Init(50000);//50ms
	//默认为开灯
	LED_ON_Lx(1);
	LED_ON_Lx(8);
  while(1)
  { 
		if(sign == 1)
		{
			LED_ON_Lx(1);
			sign = 0;
		}
		if(sign == 2)
		{
			LED_ON_Lx(8);
			sign = 0;
		}
  }
}
/*****************定时器**********************/
/*
	输入变量:定时时长___us
	输出变量:无
	功能:配置并开启定时器0
*/
void Timer_0_Init(u16 time)
{
	//12T模式
	AUXR &= 0x7f;
	//定时器0 模式0
	TMOD &= 0xf0;
	//设置初值
	TH0 = (65536-time)/256;
	TL0 = (65536-time)%256;
	//打开中断
	ET0 = 1;
	EA = 1;
	//开始计数
	TR0 = 1;
}

void Timer_0_IT(void) interrupt 1
{
	count++;
	if(count%10 == 0)
		sign = 1;
	if(count%100 == 0)
		sign = 2;
	if(count == 200)
		count = 0;
}

/*****************LED**********************/

/*
	输入变量:Lx灯翻转
	输出变量:无
	功能:选择相应的锁存器后,通过P0口控制某个LED灯翻转,但不影响其他LED灯
	注意:使用前要对u8 last_led = oxff进行宏定义
*/
void LED_ON_Lx(u8 L_X)
{
	//由于P0口是公用的口,我们要对每次点灯的数据进行记录,不然会受其他操作的影响
	P0 = last_led ^ (0x01<<(L_X-1));
	last_led = P0;
	P2 = (P2 & 0x1f) | 0x80;
	P2 &= 0x1f;
}

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值