51之定时器与中断系统

目录

1.定时器与中断系统简介

1.1中断系统

1.2定时器

1.2.1定时器简介

1.2.2定时器大致原理及其配置

1.2.3定时器所需的所有配置总介

2.定时器0实现LED闪烁

3.使用软件生成定时器初始化程序


1.定时器与中断系统简介

1.1中断系统

        首先,我们需要来了解一下什么是中断系统:首先,中断系统指的是我们程序运行过程中由于中断指令而需要停下当前的动作去做中断所要求的事情,完成中断要求的事情之后才可以回来继续完成之前事情的一个规则。

        就好比我们正在吃饭,但是突然厨房的水烧开了,我们就不得不去先去处理烧开的水,处理完之后再回来继续吃饭。我们去处理厨房烧开的水这个动作就叫做我们的”中断“。

        中断分为三大类:外部中断,定时器中断和串口中断

        我们使用的STC89C5X系列单片机提供了 8个中断请求源,其中,外部中断有四个,分别是外部中断0(INT0)、外部中断 1(INT1)、外部中断 2(INT2)、外部中断 3(INT3);定时器中断有三个,分别是定时器 0中断(Timer0)、定时器 1中断(Timer1)、定时器 2中断(Timer2);串口中断一个,就叫串口中断(UART)

        中断和中断之间还是有”三六九等的“,就像我们需要做的事情是有一个优先级的,比方说我们正在吃饭,但是这个时候,厨房的水烧开了,我们去把这个水处理一下,但是我们不小心摔倒了,这个时候我们优先处理的事情应该是从”处理烧开的水“变成”先爬起来“,这个就叫做中断的嵌套,先处理优先级更高的那个。我们应该要去处理中断优先级更高的那件事,就算我们正在处理应该中断的过程中,我们还是要去先处理更高优先级的中断请求,这也是中断嵌套的基本规则。

        这里有一张表格,写的就是中断的优先级:

我们可以看到,中断优先级的基本排序是:外部中断0(INT0) > 定时器 0中断(Timer0)>外部中断 1(INT1) > 定时器 1中断(Timer1) > 串口中断(UART)>定时器 2中断(Timer2)>外部中断 2(INT2)>外部中断 3(INT3)

1.2定时器

1.2.1定时器简介

  • 最初始的51单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器。T0T1与传统的51单片机兼容,T2是此型号单片机增加的资源
  • 定时器/计数器和单片机的 CPU是相互独立的。定时器/计数器工作的过程是自动完成的,不需要 CPU的参与。
  • 51单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信号对寄存器中的数据加 1。

        有了定时器/计数器之后,可以增加单片机的效率,一些简单的重复加 1的工作可以交给定时器/计数器处理。CPU转而处理一些复杂的事情。同时可以实现精确定时作用。

        所以我们一般会使用定时器来代替之前的Delay,Delay的使用是对CPU执行的,在这段时间里,CPU都无法执行任何任务,而是在Delay函数中执行循环。所以我们现在可以采用定时器去把我们的Delay替换,转而把我们的CPU留出更多的时间去处理更加高效的事情。

1.2.2定时器大致原理及其配置

        大部分情况下,我们使用的最多的还是定时器0,这里是定时器的大致原理图

        我上图所示的C/T中T上有一个横线表示低电平有效,C表示高电平有效,C又是Clock的缩写,也就是说C/T = 1的话,我们使用的是计数器,如果C/T = 0,则说明我们使用的是计时器系统,这里的SYSclk叫做系统时钟,即晶振周期。我们一般使用的是12T mode运行。

        而则是一个控制开关,有这个小系统输出的值为高电平时,开关才会闭合,才会继续往后面执行操作。

        这里有必要介绍一下的是是非门电路,输入1则输出0,输入0则输出1;是或门,输入两个数有一个为1则输出1,都是0时才输出0;是与门,输入两个都是1时输出的才是1,否则输出的是0。

        这里我们需要反向推理一下,假设我们想要最终输出1,那么与门的两个输入口需要都是高电平1,所有这里TR0必须是1,然后就是这个或门的输出要是1,则说明这个门的输入只要有一个1就可以完成任务,或门连接的是 和,即门控端GATE取反值和外部中断0的值,我们要实现输出有一个为1即可,假如我们需要只靠外部中断0控制整个电路的通闭,那么我们就要把GATE设为1,即输出的为0,这样就只靠外部中断0实现控制电路,但是我们这里不需要依靠外部中断支配,所以我们这里直接把门控端GATE设为0就好了,这样无论外部中断0输出的是什么都不会影响我们的电路闭合。

        配置好了前面的部分,我们来配置一下后面的,这里要分成两部分,第一部分是 表示的是定时器/计数器0的计数数值,计数数值的高8bit位存在寄存器TH0中,后8bit位存在TL0中,最大可以表示到65535,每个单元一般时1us,直到超出了这个最大值,计数就会溢出,来到溢出标志位,这个就是一个判断定时器溢出的标志位,通过判断TF0来判断计数是否溢出,如果溢出,就会进入到中断中去。这就是上面的图的流程。

        我们配置的是定时器0,即T0的话,我们的流程就是这样的:

        经过刚刚的一系列计数,溢出,到达中断允许位,我们就来到了中断,这部分统称为IE,我们使用T0就要配置ET0为1,EA为1,才可以使这部分闭合,这部分也叫做“使能”,也就是这部分不闭合,我们就无法实现中断。然后就是到达IP选择PT0 = 1或者PT0 = 0,这就是选择高优先级和低优先级的,其实选择哪个都没有太大的影响,主要是完成前面的配置,保证电路通畅即可。

1.2.3定时器所需的所有配置总介

 

        这里写了两个寄存器列表,我们实现中断,所以从中断寄存器出发,我们必须要配置的是IE使能和IP/IPH的高低优先级选择。

        然后后面的进行分类,定时器T0和T1实现TCON的配置即可,我们实现T0定时器,就只要关关心TCON这个控制寄存器,然后我们需要实现的是T0,所以我们看到定时器0相关的寄存器列表中正好有TCON控制寄存器,然后我们还要实现TMOD模式寄存器的配置和TL0与TH0计数存放计数数值的初始化即可。

        总而言之,我们实现T0,需要配置IE使能(ET0和EA都配置为1),IP/IPH(即PT0)高低优先级选择,TCON控制寄存器,TMOD模式寄存器,TH0和TL0计数数值初始化。

        需要主要介绍的是TCON和TMOD这两个寄存器:

        这里TCON是“可位寻址”而TMOD是“不可位寻址”,意思就是TCON的每一位的配置可以单独配置,比如里面的IE0,IR0,而不用影响到IE1和IR1,但是TMOD就不一样,只能整体赋值,我们不能把里面的单个数拉出来赋值,只可以给一个十六进制的数把八位同时配置完成。

  TCON:   我们需要配置TCON,就只要让TR0 = 1让计数开始,IE0= 1使能让电路接通,IT0 = 1让

的控制只由TR0掌控。

        至于TF0标志位的置位和清零,可以说可有可无,初始置为0就好了,后面也不用再管。

TMOD:

        这里把IT0配置为1了,所以其实在TMOD中的门控端GATE是多少都不重要了

由于是不可位寻址,我们只能整体赋值,按照前面分析,我们操作定时器0的话需要把C/T = 0,GATE最好也设为0。

        M1和M0是模式的选择,主要的区别如下:

  • M1 = 0, M0 = 0: 13位定时/计数模式

    • 定时器/计数器0 使用 TH0 和 TL0 寄存器的所有位进行计数。
  • M1 = 0, M0 = 1: 16位定时/计数模式

    • 定时器/计数器0 使用 TH0 和 TL0 寄存器的所有位进行计数。
  • M1 = 1, M0 = 0: 8位自动重装定时/计数模式

    • 定时器/计数器0 先使用 TL0 寄存器计数,当 TL0 计数溢出时,自动从 TH0 中重新装载计数值,然后继续计数。
  • M1 = 1, M0 = 1: 2个8位定时/计数模式

    • 定时器/计数器0 分为两个独立的8位定时/计数器:T0 高位和 T0 低位。TH0 用作高8位计数器,TL0 用作低8位计数器。

我们一般默认选择两个8位的计数器,也就是M1 = 0, M0 = 1的16位定时/计数模式

所以综上所述,我们配置TMOD寄存器的最后四位,而且是配置为0001,前四位与定时器1有关,我们一般不作处理。

但是这里又只能整体赋值,所以TMOD的配置T0可以先把后四位清零,前四位不动,再把前四位不动,后四位变成0001,我们可以使用按位与(&)和按位或(|)两个操作符。

        先让TMOD &= 0xf0;就让前四位不变,后四位变成0000,再使用TMOD |= 0xf1;就让前四位不变,后四位变成0001,然后我们的TMOD配置就大功告成。

2.定时器0实现LED闪烁

        学习了配置定时器,我们就要学习怎么使用定时器,这里使用定时器配置间隔时长为1s的LED闪烁。

        这里我们就要写一个定时器初始化函数,把寄存器配置好,再使用中断实现功能。

        首先,我们需要配置模式寄存器TMOD,让TMOD选用定时器0并使用16位计时,所以我们就可以写出

TMOD &= 0xf0;
TMOD |= 0xf1;

然后是TCON寄存器

        这里主要是注意我们需要的是1s也就是1000*1000us,但是由于计数器限制,我们只能得到1ms的计时,就像Delay函数那样可以使用以1ms为基本单位的计时,累加起来就可以组成自己想要的时间

        这里就配置一个1000us,那么距离计数值溢出(65535)就相差1000,所以我们初始值为64535,TH0高四位为64535/256,TL0第四位为64535%256.

TL0 = 64535%256;	//设置定时初值
TH0 = 64535/256;//设置定时初值
TF0 = 0;		//清除TF0标志
TR0 = 1;		//定时器0开始计时
PT0 = 0;        //选择低优先级
ET0 = 1;        //使能配置
EA = 1;         //使能配置

这样就写完了我们的定时器0初始化程序:

void Timer0_Init()
{TMOD &= 0xf0;TMOD |= 0xf1;TL0 = 64535%256;	//设置定时初值TH0 = 64535/256;//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时PT0 = 0;        //选择低优先级ET0 = 1;        //使能配置EA = 1;         //使能配置
}

配置完初始化程序之后,我们就开始配置中断程序:

        中断程序的命名参照这张图:

具体的流程就是这样,我们在中断函数中实现一下我们的代码:

void Timer0_Rountine() interrupt 1
{static int count = 0;//只有函数第一次被调用的时候才会初始化count++;TL0 = 64535%256;TH0 = 64535/256;//重新设置时间,否则默认设置为0if(count >= 1000)//到达1s{count = 0;//归0P2_0 = ~P2_0;//开关灯}
}

这样我们的代码就完全写完了:

#include <REGX52.H>
void Timer0_Init()
{TMOD &= 0xf0;TMOD |= 0xf1;TL0 = 64535%256;TH0 = 64535/256;TF0 = 0;TR0 = 1;PT0 = 0;ET0 = 1; EA = 1; 
}void main()
{Timer0_Init();while(1){//主程序}
}void Timer0_Rountine() interrupt 1
{static int count = 0;//只有函数第一次被调用的时候才会初始化count++;TL0 = 64535%256;TH0 = 64535/256;//重新设置时间,否则默认设置为0if(count >= 1000)//到达1s{count = 0;//归0P2_0 = ~P2_0;//开关灯}
}

这里我们并没有需要使用CPU执行主程序,所以while循环中的程序就不写了,还有一个要注意的点,就是头文件#include <REGX52.H>中才有我们需要配置的寄存器的地址,所以要包含这个头文件我们才可以使用这个定时器并配置程序。

到这里我们的定时器实现LED闪烁就算结束了。

3.使用软件生成定时器初始化程序

        我们的一个软件中可以生成定时器初始化程序:

我们设置好之后就可以得到一个定时器的较为准确的一个代码:

void Timer0Init(void)		//1毫秒@11.0592MHz
{AUXR |= 0x80;		//定时器时钟1T模式TMOD &= 0xF0;		//设置定时器模式TL0 = 0xCD;		//设置定时初值TH0 = 0xD4;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时
}

我们的单片机上没有AUXR这个配置的选项,不需要配置它,然后就是这里还有一些代码我们需啊哟自己配置,比如IE使能和优先级选择。我们全部修改完成之后就是这样:

void Timer0Init(void)		//1毫秒@11.0592MHz
{TMOD &= 0xF0;		//设置定时器模式TL0 = 0xCD;		//设置定时初值TH0 = 0xD4;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时PT0 = 0;		//优先级配置 ET0 = 1; 		//使能配置 EA = 1; 		//使能配置 
}

然后我们就可以快乐地使用定时器了!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue项目中引入html页面(vue.js中引入echarts数据大屏html [静态非数据传递!] )

在项目原有vue&#xff08;例如首页&#xff09;基础上引入html页面 1、存放位置 vue3原有public文件夹下 我这边是新建一个static文件夹 专门存放要用到的html文件 复制拖拽过来 index为html的首页 2、更改路径引入到vue中 这里用到的是 iframe 方法 不同于vue的 component…

python爬虫获取豆瓣前top250的标题(简单)

今天是简略的一篇&#xff0c;简单小实验 import requests from bs4 import BeautifulSoup# 模拟浏览器的构成&#xff08;请求头&#xff09; headers {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Ch…

从零开始搭建后端信息管理系统(新手小白比如)

如果你是新手小白&#xff0c;首先我们要进行一些准备工作&#xff0c;安装一些基础软件&#xff0c; 备注一下&#xff1a;这里安装的vue环境的后台管理系统&#xff0c;不同的后台管理系统&#xff0c;需要安装不同的插件 准备工作&#xff1a; 安装 Visual Studio Code …

如何使用 Midjourney?2024年最新更新

一&#xff1a;基础篇 1&#xff1a;注册 首先&#xff0c;你需要注册一个 Discord 账号&#xff0c;然后加入 Midjourney 的 Discord 服务器。或者去 Midjourney 的官网点击右下角的 Join the Beta&#xff1a; ​ 2&#xff1a;在 Discord 公共服务器里使用 注册并进入到…

Unix 网络编程, Socket 以及bind(), listen(), accept(), connect(), read()write()五大函数简介

Unix网络编程是针对类Unix操作系统&#xff08;包括Linux、BSD以及其他遵循POSIX标准的操作系统&#xff09;进行网络通信开发的技术领域。网络编程涉及创建和管理网络连接、交换数据以及处理不同层次网络协议栈上的各种网络事件。在Unix环境中&#xff0c;网络编程通常涉及到以…

kubectl explain资源文档命令

学习并使用了一段时间的kubernetes&#xff0c;发现对k8s还是了解甚少&#xff0c;于是利用上下班通勤的时间又去B站看一些大佬的视频&#xff0c;又来重学巩固一遍知识&#xff0c;并做些记录。 之前在学习使用过程中未成了解过explain这个命令&#xff0c;因为自己部署的版本…

【开发、测试】接口规范与测试

接口测试基础 url 是互联网标准资源地址&#xff0c;称为统一资源定位符 组成&#xff1a;协议&#xff0c;服务器地址&#xff0c;端口号 HTTP协议 HTTP&#xff1a;超文本传输协议&#xff0c;基于请求与响应的应用层协议 作用&#xff1a;规定了客户端和服务器之间的信…

NoSQL之Redis配置

文章目录 NoSQL之Redis配置一、关系数据库和非关系数据库1、关系型数据库2、非关系型数据库3、非关系型数据库产生背景4、关系型数据库和非关系型数据库的区别4.1 数据存储方式不同4.2 扩展方式不同4.3 对事务性的支持不同 5、总结5.1 关系型数据库5.2 非关系型数据库 二、Redi…

Anaconda/Python快速安装jieba 【win/mac】

一、直接上命令 pip install -i https://pypi.tuna.tsinghua.edu.cn/simple jieba 我是在PyCharm里面的终端输进去。 之后就很快速的看到成功的下图。 二、官网 官网下载的速度太慢了——这是官网地址https://pypi.org/project/jieba/#files 点进去之后点击下载&#xff0c…

Star GAN论文解析

论文地址&#xff1a;https://arxiv.org/pdf/1912.01865v1.pdf https://openaccess.thecvf.com/content_cvpr_2018/papers/Choi_StarGAN_Unified_Generative_CVPR_2018_paper.pdf 源码&#xff1a;stargan项目实战及源码解读-CSDN博客 1. 概述 在传统方法中&#x…

练习14 Web [极客大挑战 2019]Upload

phtml格式绕过&#xff0c;burp修改content-type绕过&#xff0c;常见的文件上传存放目录名 题目就叫upload&#xff0c;打开靶机 直接上传一个图片格式的一句话木马&#xff0c;返回如下&#xff1a; 提交练习5和9中的两种可以执行图片格式php代码的文件&#xff0c;修改con…

全面解析找不到msvcr110.dll,无法继续执行代码的解决方法

MSVCR110.dll的丢失可能导致某些应用程序无法启动。当用户试图打开依赖于该特定版本DLL文件的软件时&#xff0c;可能会遭遇“找不到指定模块”的错误提示&#xff0c;使得程序启动进程戛然而止。这种突如其来的故障不仅打断了用户的正常工作流程&#xff0c;也可能导致重要数据…

[中级]软考_软件设计_计算机组成与体系结构_08_输入输出技术

输入输出技术 前言控制方式考点往年真题 前言 输入输出技术就是IO技术 控制方式 程序控制(查询)方式&#xff1a;分为无条件传送和程序查询方式两种。 方法简单&#xff0c;硬件开销小&#xff0c;但I/O能力不高&#xff0c;严重影响CPU的利用率。 程序中断方式&#xff1…

极简云验证 download.php 文件读取漏洞复现

0x01 产品简介 极简云验证是一款开源的网络验证系统&#xff0c;支持多应用卡密生成&#xff1a;卡密生成 单码卡密 次数卡密 会员卡密 积分卡密、卡密管理 卡密长度 卡密封禁 批量生成 批量导出 自定义卡密前缀等&#xff1b;支持多应用多用户管理&#xff1a;应用备注 应用版…

数学建模-最优包衣厚度终点判别法(主成分分析)

&#x1f49e;&#x1f49e; 前言 hello hello~ &#xff0c;这里是viperrrrrrr~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f4a5;个人主页&#xff…

armlinux-外部中断

s3c2440的中断框图 如果我们单纯配置一个按键的外部中断&#xff0c;就不存在子中断与优先级的问题。 由于是按键的外部中断&#xff0c;通过引脚的高低电平来触发。所以我们要先配置引脚的功能。 我们使用按键1&#xff0c;终端源为EINT8&#xff0c;对应引脚GPG0 通过用户手…

DBU-Net:用于乳腺超声图像中肿瘤分割的双分支U形网络

DBU-Net&#xff1a;用于乳腺超声图像中肿瘤分割的双分支U形网络 摘要引言材料和方法概述所提出的方法 DBU-Net Dual branch U-Net for tumor segmentation in breast ultrasound images 摘要 乳腺超声医学图像通常具有低成像质量沿着不清楚的目标边界。这些问题使得医生在诊断…

JS继承与原型、原型链

在 JavaScript 中&#xff0c;继承是实现代码复用和构建对象关系的重要概念。本文将讨论原型链继承、构造函数继承以及组合继承等几种常见的继承方式&#xff0c;并提供相应的示例代码&#xff0c;并分析它们的特点、优缺点以及适用场景。 在开始讲解 JavaScript 的继承方式之…

[java]网络编程

网络编程概述 计算机网络&#xff1a; 把分布在不同地理区域的具有独立功能的计算机,通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。 Java是 Internet 上的语言&#xff0c;它从语言级上提供了对网络应用程序的支持&#xff0c;程序…

wordpress全站开发指南-面向开发者及深度用户(全中文实操)--创建新主题

前言 你可以在wordpress里面下载使用人家打包好的主题&#xff0c;但可能不是很好用&#xff0c;接下来就自己做一个自己的主题。你需要先找到xampp文件夹–htdocs–wordpress(我给更名为wplocal)–wp-content–themes 进入该文件夹之后你可以看到你之前下载导入的所有主题文件…