定时器中断

news2024/9/9 0:48:39

背景:使用动态数码管读取光电传感器的值并且显示,因此要使用到定时器,每隔一个阶段进行一次检测并进行中断。

51单片机里的关于中断的寄存器如下:

IE – 中断允许控制寄存器
IP – 中断优先级控制寄存器
TMOD – 定时器工作方式寄存器
TCON – 定时器控制寄存器
SCON – 串口控制寄存器
THx/TLx – 定时器初值寄存器

在定时器中断中,需要设置的有TMOD、THx/TLx、TCON、IE。 

1、中断允许控制寄存器 IE

该寄存器的主要功能是控制中断的开启与关闭,共7个有效位,包含一个全局中断控制位和6个中断源的控制位。

EA 全局中断允许位,当此位是1时中断可用。(重要)
ET2 定时器/计数器2中断允许位
ES 串口中断允许位
ET1 定时器/计数器1中断允许位
EX1 外部中断1允许位
ET0 定时器/计数器0中断允许位 (重要)
EX0 外部中断0允许位
要使用定时器中断,需要将IE寄存器中的EA位设置为1,以及需要将ETx(x = 0,1,2)设置为1
 

2、 定时器工作方式寄存器 TMOD

该寄存器的主要功能是设置定时器/计数器中断的工作方式。

 说明:
GATE 定时器/计数器的开关控制选项。常将该位置0,即定时器/计数器的开关控制仅由TCON寄存器中的TRx(x = 0,1)控制。(见2.2.3的TRx)
C/T 定时器模式和计数器模式选择位,将该位置0则为定时器模式。
M1M0 设置定时器/计数器工作方式,常将该两位设置为0 1,

即定时器常见的工作方式为0x01,即00000001,GATE为0(开),C/T为0(定时器模式),M1M2为01(16为计数)

3、定时器控制寄存器 TCON

该寄存器用于控制中断,如控制定时器的启动,停止、判断定时器的溢出和中断情况。

 TF1 定时器1溢出标志位
TR1 定时器1运行控制位,将该位置1时启动定时器1
TF0 定时器0溢出标志位
TR0 定时器0运行控制位,将该位置1时启动定时器0 
IE1 外部中断1请求标志
IT1 外部中断1触发方式选择位
IE0 外部中断0请求标志
IT0 外部中断0触发方式选择位

主要是设置运行控制位(TR1,0)其次是选择中断方式

若选择的是定时器1则TR1=1,若选择的是定时器0则TR0=0。

 4、定时器初值寄存器 THx/TLx

以定时器T0为例,其的工作原理是,每当晶振产生一次脉冲,就将该寄存器TL0加一,当TL0加满溢出后,将TL0清空,TH0加一,TH0计满后产生定时中断。即TH0与TL0组成了一个16位的计数器,这个计数器可以从0x0000(0)加到0xffff(65535)。
以12Mhz的晶振、定时10ms为例:
51单片机为12分频单片机,因此执行一条指令的时间是12×(1/12M) s,即计数器每1us加一。
若定时10ms,则共需要加10000次。
因此将TH0、TL0设置从(65536-10000)= 55536开始计数。55536 的16进制为0xD8F0。因此将TH0设置为0xD8,TL0 设置为0xF0。

综上:定时器的写法为

设置中断允许控制器---->设置工作模式---->控制定时器寄存器---->设置初值

对于初值寄存器THx/TLx的理解:

首先51单片机为12分频单片机,执行一条指令为12x12M/s,即1us,若要计时10ms,则10ms=10000us,其中寄存器TH0加满后(0xffff 65535)进行定时中断 ,则初值应为65535-10000=55536,即应该从55536us(0xD8F0)开始加,每执行一次加1us,当加到65535时候进行中断操作。又因为TH/TL分别为8位共16位,所以其值分别为TH = 0xD8,TL = 0xF0。

5、定时器程序写法

首先要初始化定时器,即将命令写入以上的寄存器。 假设使用定时器T0

步骤为设置定时器工作模式、设置定时时长、打开允许的中断开关、打开定时器开关(使定时器开始计数)
首先设置定时器工作模式TMOD:GATE设置为0;C/T位设置为0使其工作在定时器模式下;M1M0设置为01,使用16位计数。

  1. 设置定时器的工作方式:TMOD = 0x01 (基本都是这个值)设置开关、定时器模式(CT=0)、定时器工作方式(M0,M1=0,1)
  2. 设置定时时长TH0,TL0 16为计算公式为0x(65536-定时时间(单位us)),TH为前8位,TL0为后8位
  3. 打开允许中断的总开关

即将ET0、EA设置为 1,(ET为定时器中断,INT为外部中断),因为我们选择的是定时器0,所以也对应了中断的ET0。

        4.打开定时器开关:若选择的是定时器1则TR1=1,若选择的是定时器0则TR0=0。

        5.定时器中断服务函数:

              中断服务函数要写在主函数后面,且不需要声明 。
              中断服务函数无返回值,所以用void
              函数名可以随便起
              interrupt后的中断号由下表的重点服务号确定

void t0Intr() interrupt 1
{
  //执行到此时,计数器已经达到65535,寄存器清零,所以要重新赋值
   //55536 = 0xD8F0
  TH0 = 0xD8;    //65536-10000
  TL0 = 0xF0;    //55536
  
  //下面写需要执行的操作
}

其中 interrupt 1要特别注意,当前我们使用的是T0定时器中断,所以其服务号为1,而不是外部中断0。!!!!!!!!!!!!!!!!!!!!!!!!

根据上述学习:

        定时器中断只不过是中断的一种类型,同外部中断一样,都是中断。只不过定时器中断具有自检测功能,当到一定时间后就开始执行中断,(类似与闹钟),而外部中断只有当外界的信号输入,才开始执行中断。

功能上定时器中断更偏向于单片机内部,而外部中断更偏于外部,即当按键按下时,或其他效果。

更加直观的理解为定时器中断类似于js的setTimeout( ),到达指定时间就会运行。而外部中断类似于onclick事件等,等待外来的信号才开始执行服务。

 

中断程序:可以简述为,设置定时器工作模式(TCON),“开两个中断位(ET0、EA)”,“设置两个时间(TH0,TL0)”,开启定时器中断(TR)。

二、程序实验

 测试光电传感器,将值使用8号数码管显示,并用定时器0,50ms检测一次

#include "reg52.h"
#include "public.h"
#define SMG_A_DP_PORT	P0	//使用宏定义数码管段码口
sbit LED1=P2^0;	//将P2.0管脚定义为LED1
sbit sensor_light = P3^2;
sbit motor = P1^3;
//数码管译码器
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
u8 gsmg_code[3]={0x3f,0x06};
/*******************************************************************************
* 函 数 名       : time0_init
* 函数功能		 : 测试光电传感器,将值使用8号数码管显示,定时器0 50ms检测一次
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void time0_init(void)
{
	TMOD|=0X01;//选择为定时器0模式,工作方式1
	//FC18 = 64536,即定时时间为65535-64536 = 999 = 1ms
	TH0=0XFC;	//给定时器赋初值,定时1ms
	TL0=0X18;	
	ET0=1;//打开定时器0中断允许
	EA=1;//打开总中断
	TR0=1;//打开定时器		
}


u16 numbr_verson(void)
{
	//8号位
	LSA = 0;
	LSB = 0;
	LSC = 0;
	if(sensor_light==1) return 1;	
	else  return 0;
}


//定时器中断服务函数
void time0() interrupt 1 
{
	//执行到此时,计数器已经达到65535,寄存器清零,所以要重新赋值
	static u16 i;
	TH0 = 0xFC;
	TL0 = 0x18;
	i++;
	if(i==50)//每50ms检测一次
	{
		i = 0;
		SMG_A_DP_PORT = gsmg_code[numbr_verson()];
	}
}



void main()
{
	time0_init();
	while(1)
	{
		
	}
}

一定要注意函数的参数在服务程序中作用域的问题!!!!!!!!!!!!!

效果:

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/736983.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

操作系统12:I/O系统的功能、模型、接口及 I/O 设备和设备控制器

目录 1、I/O系统的功能、模型和接口 (1)I/O系统的基本功能 1.1 - 隐藏物理设备的细节 1.2 - 与设备的无关性 1.3 - 提高处理机和I/O设备的利用率 1.4 - 对 I/O 设备进行控制 1.5 - 确保对设备的正确共享 1.6 - 错误处理 (2&#xff…

浅谈用于配电室的内部环境监控系统设计

摘要:配电室是配电系统的重要组成部分,影响着电力用户的用电需求,需要保障其安全、可靠运行。针对配电室内部环境进行了深入分析,设计了一种内部环境监控系统。通过该系统可以采集配电室内部的温度、湿度、液位、SF6气体和烟雾&am…

Unity游戏开发智能巡逻兵

完整资料进入【数字空间】查看——baidu搜索"writebug" 1.1 游戏设计要求: 创建一个地图和若干巡逻兵(使用动画); 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置…

STM32单片机不同型号之间的HAL库代码移植浅谈(代码解析)

在嵌入式系统开发中,STM32HAL库是一种常用的软件开发工具,用于开发STM32系列微控制器的应用程序。由于不同型号的芯片具有不同的硬件架构和外设,因此在将代码移植到不同类型的芯片上时,需要进行一些适配和调整。 首先,…

wps中excel如何实现模糊搜索匹配的内容(可以匹配想要的各种格式)

1,在某一列进行搜索-筛选搜索-如包含“XXX信息XX公司XX”这种格式的。 输入 :信息*公司 (1)选择第一种搜索方式代表寻找符合条件: 包含信息和公司两个关键字, 且信息在前公司在后, 且两个词语之…

SIP 抓包后获取媒体内容备忘(解析RTP)

SIP呼叫并抓包 从网上找免费的sip 软中端, 两个转中端建立呼叫且抓包 详情可以参考 https://blog.csdn.net/liuxingrui4p/article/details/96709136?spm1001.2014.3001.5502 使用wireshark检查SIP flow: 点击Telephony > SIP Flows 打开页面如下…

下一代边缘计算技术在哪里?

扫描文末二维码,立刻免费报名 云网一体,超大规模流量下 边缘云的架构与技术揭秘 伴随超高清视频时代的开启,热点赛事、晚会直播等特殊场景的巨大流量对业务的带宽储备、节点资源、流量调度和安全保障能力提出了新的挑战。 火山引擎边缘云基于…

JUC之十一:CompletableFuture用法详解

JUC之十一:CompletableFuture用法详解 文章目录 JUC之十一:CompletableFuture用法详解一、前言二、CompletableFuture类简介三、功能分类3.1、获取结果3.2、依赖关系3.3、and聚合关系3.4、or聚合关系3.5、并行执行3.6、结果处理 四、方法详解4.1、结果转…

【JavaScript】ES6新特性(5)

16. Promise Promise 是异步编程的一种解决方案,比传统的解决方案回调函数, 更合理和更强大 ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象 指定回调函数方式更灵活易懂解决异步 回调地狱 的问题 16.1 回调地狱 当一个回调函数…

Linux 进程管理与调度

一、前言 本篇文章是对Liunx的进程管理调度的实验过程记录,读者可以通过这篇文章加深对Liunx中进程管理和调度的理解,本文所使用的操作系统为RHEL 8.0版本,为在Vmware workstation中运行的虚拟机。 二、实验目的 ① 掌握linux进程相关操作 ②…

RabbitMQ学习笔记9 TTL死信队列+延迟队列实战

我们去新建一个交换机: 然后我们再用这种方法直接创建一个队列: 点击bind这样我们的交换机和队列就绑定到一起了。 然后我们要新建普通队列,设置过期时间,指定死信交换机。 发布一条消息。 它会把队列传递到死信队列中去。

Openlayers实战:overlay上播放视频

在企业或者城市等的宣传上,视频能很好的传达出一些信息。 那么在openlayer中如何展示视频呢, 可以通过overlay的方式,点击某一个点,弹出overlay层,展示出视频,并自动播放。下面的实战就能够达到这种效果。 效果图 源代码 /* * @Author: 大剑师兰特(xiaozhuanlan),还…

记忆——记忆宫殿——数字编码

数字编码 数字编码相对简单,与乘法口诀的工作量类似。如果想要达到高手的水平,熟练程度也需要达到乘法口诀的程度。 数字编码的方式是直接创造出数字与形象的唯一的对应关系,然后熟记。 0-9,00-99是什么 最常用的编码是将0-9和…

【C++11】lambda表达式 的定义、性质和用法

定义 Lambda表达式是C11引入的一种函数对象的匿名表示方法。它可以用于定义轻量级的、临时的、内联的函数对象,通常用于函数式编程的场景。 语法结构 Lambda表达式的 基本语法 如下: lambda表达式书写格式:[capture-list] (parameters) m…

java8 新特性 —— Lambda 表达式

我们来看一段老版本的示例代码,其对一个含有字符串的集合进行排序:(示例代码创建了一个匿名内部类作为入参。) // Collections 工具类提供了静态方法 sort 方法,入参是一个 List 集合,和一个 Comparator 比…

C++栈和队列(详解+刷题)

👂 爱要坦荡荡 - 萧潇 - 单曲 - 网易云音乐 👂 武侯祠 - 闫东炜 - 单曲 - 网易云音乐 👂 You Are My Sunshine - Angelika Vee - 单曲 - 网易云音乐 (๑•̀ㅂ•́)و✧ O(∩_∩)O (ง •_•)ง (~﹃~)~zZ …

微鳄三六五软件,企业实现数字化转型仅需2万

关键词:OA办公系统、知识管理系统、群晖NAS 编者按: 疫情对全球经济有着巨大冲击,有调查表明80%的中小企业营收下滑,有30%的中小企业营收减半。天翎特此推出万元即可实现数字化管理方案,为企业提供办公管理、项目管理、…

Canvas.arcTo() 的使用,画一条带圆角的线段,画一个思维导图一基础

Canvas.arcTo() 的使用,画一条带圆角的线段,画一个思维导图一基础 一、方法定义 canvas.arcTo 这个方法还是比较难理解的。因为它不是直观的绘制路径,而是间接的。 它的参数是这样的。 canvas.arcTo(ax,ay,bx,by,radius)它是由两个点和一个…

密码学学习笔记(十):Digital Signatures - 数字签名1

什么是数字签名? 想象一下一下情景: Alice生成两个密钥:一个公钥𝑃𝐾𝐴 & 对应的密钥𝑆𝐾𝐴, 发布公钥,保留密钥然后Alice使用𝑆&#x1d4…

ARG DEBIAN_FRONTEND=noninteractive作用说明

使用 在Dockerfile中使用ARG指令定义变量并为其指定一个默认值。ARG指令用于在构建过程中传递变量的值。 对于DEBIAN_FRONTENDnoninteractive,它定义了一个名为DEBIAN_FRONTEND的变量,并将其默认值设置为noninteractive。在这个上下文中,no…