单片机第一季:零基础7——定时器和计时器

news2024/11/22 23:51:26

目录

1,单片机定时器原理

2,51单片机定时器/计数器结构

3,定时器配置 

4,示例代码-通过定时器控制LED灯间隔1s闪烁 


51 单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器。

定时器/计数器和单片机的CPU 是相互独立的。定时器/计数器工作的过程是自动完成的,不需要CPU 的参与。

51 单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信号对寄存器中的数据加1。

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

譬如外部12MHz晶振,单片机工作在12T模式下,则内部时钟频率是1MHz,则时钟脉冲宽度为1us(1/1MHz = 1us)。如果单片机工作在6T模式下,则内部时钟频率是2MHz,则时钟脉冲宽度为0.5us(1/2MHz = 0.5us)

1,单片机定时器原理

STC89C5X 单片机内有两个可编程的定时/计数器T0、T1 和一个特殊功能定时器T2。定时/计数器的实质是加1 计数器(16 位),由高8 位和低8 位两个寄存器THx 和TLx 组成(x代表0/1/2)。它随着计数器的输入脉冲进行自加1,也就是每来一个脉冲,计数器就自动加1,当加到计数器为全1 时,再输入一个脉冲就使计数器回零,且计数器的溢出使相应的中断标志位置1,向CPU 发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。可见,由溢出时计数器的值减去计数初值才是加1 计数器的计数值。

2,51单片机定时器/计数器结构

上图中的T0 和T1 引脚对应的是单片机P3.4 和P3.5 管脚。51 单片机定时/计数器的工作由两个特殊功能寄存器控制。TMOD 是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON 是控制寄存器,控制T0、T1 的启动和停止及设置溢出标志。

工作方式寄存器TMOD 用于设置定时/计数器的工作方式,低四位用于T0,高四位用于T1。其格式如下:

GATE 是门控位, GATE=0 时,用于控制定时器的启动是否受外部中断源信号的影响。只要用软件使TCON 中的TR0 或TR1 为1,就可以启动定时/计数器工作;GATA=1 时,要用软件使TR0 或TR1 为1,同时外部中断引脚INT0/1 也为高电平时,才能启动定时/计数器工作。即此时定时器的启动条件,加上了INT0/1 引脚为高电平这一条件。

C/T :定时/计数模式选择位。C/T =0 为定时模式;C/T =1 为计数模式。

M1M0:工作方式设置位。定时/计数器有四种工作方式。

TCON 的低4 位用于控制外部中断,已在前面介绍。TCON 的高4 位用于控制定时/计数器的启动和中断申请。其格式如下: 

TF1(TCON.7):T1 溢出中断请求标志位。T1 计数溢出时由硬件自动置TF1为1。CPU 响应中断后TF1 由硬件自动清0。T1 工作时,CPU 可随时查询TF1 的状态。所以,TF1 可用作查询测试的标志。TF1 也可以用软件置1 或清0,同硬件置1 或清0 的效果一样。
TR1(TCON.6):T1 运行控制位。TR1 置1 时,T1 开始工作;TR1 置0 时,T1 停止工作。TR1 由软件置1 或清0。所以,用软件可控制定时/计数器的启动与停止。
TF0(TCON.5):T0 溢出中断请求标志位,其功能与TF1 类同。
TR0(TCON.4):T0 运行控制位,其功能与TR1 类同。 

 以方式0为例介绍单片机的工作方式:

方式0 为13 位计数,由TL0 的低5 位(高3 位未用)和TH0 的8 位组成。TL0 的低5 位溢出时向TH0 进位,TH0 溢出时,置位TCON 中的TF0 标志,向CPU发出中断请求。其结构图如下所示:

门控位GATE 具有特殊的作用。当GATE=0 时,经反相后使或门输出为1,此时仅由TR0 控制与门的开启,与门输出1 时,控制开关接通,计数开始;当GATE=1时,由外中断引脚信号控制或门的输出,此时控制与门的开启由外中断引脚信号和TR0 共同控制。当TR0=1 时,外中断引脚信号引脚的高电平启动计数,外中断引脚信号引脚的低电平停止计数。这种方式常用来测量外中断引脚上正脉冲的宽度。计数模式时,计数脉冲是T0 引脚上的外部脉冲。计数初值与计数个数的关系为:X=213-N。 

3,定时器配置 

在使用定时器时,应该如何配置使其工作?其步骤如下(各步骤顺序可任意):
①对TMOD 赋值,以确定T0 和T1 的工作方式,如果使用定时器0 即对T0 配置,如果使用定时器1 即对T1 配置。

②根据所要定时的时间计算初值,并将其写入TH0、TL0 或TH1、TL1。

③如果使用中断,则对EA 赋值,开放定时器中断。

④使TR0 或TR1 置位,启动定时/计数器定时或计数。上述中有一个定时/计数器初值的计算,下面我们来看下如何计算定时/计数器初值。

前面我们介绍过机器周期的概念,它是CPU 完成一个基本操作所需要的时间。其计算公式是:机器周期=1/单片机的时钟频率。51 单片机内部时钟频率是外部时钟的12 分频,也就是说当外部晶振的频率输入到单片机里面的时候要进行12分频。比如说你用的是12MHZ 晶振,那么单片机内部的时钟频率就是12/12MHZ,当你使用12MHZ 的外部晶振的时候,机器周期=1/1M=1us。如果我们想定时1ms的初值是多少呢?1ms/1us=1000。也就是要计数1000 个,初值=65535-1000+1(因为实际上计数器计数到65536(2 的16 次方)才溢出,所以后面要加1)=64536=FC18H,所以初值即为THx=0XFC,TLx=0X18。知道了如何计算定时/计数器初值,那么想定时多长时间都可以计算出,当然由于定时计数器位数有限,我们不可能直接通过初值定时很长时间,如果要实现很长时间的定时,比如定时1 秒钟。可以通过初值设置定时1ms,每当定时1ms结束后又重新赋初值,并且设定一个全局变量累计定时1ms 的次数,当累计到1000 次,表示已经定时1 秒了。需要其他定时时间类似操作,这样我们就可以使用定时器来实现精确延时来替代之前的delay 函数。这里以定时器0 为例介绍配置定时器工作方式1、设定1ms 初值,开启定时器计数功能以及总中断,如下: 

void time0_init(void)
{
    TMOD|=0X01;//选择为定时器0 模式,工作方式1
    TH0=0XFC; //给定时器赋初值,定时1ms
    TL0=0X18;
    ET0=1;//打开定时器0 中断允许
    EA=1;//打开总中断
    TR0=1;//打开定时器
}

其中ET0和EA的设置是在中断允许寄存器IE中:

CPU 对中断系统所有中断以及某个中断源的开放和屏蔽是由中断允许寄存器IE 控制的。 

EA (IE.7), CPU 中断允许(总允许)位。

ET0(IE.1),定时/计数器T0 中断允许位。

4,示例代码-通过定时器控制LED灯间隔1s闪烁 

#include <reg51.h>

//使用T0定时器控制LED灯间隔1s闪烁
unsigned int u16 = 0;  //计数初始值
sbit led = P0^0;

void time0_ini()
{
	TMOD = 0x01; //T0工作在定时模式,工作方式1:16位定时/计数器
	TR0 = 1;     //T0 运行控制位,TR0 置1 时,T0 开始工作
	TH0 = 0xfc;
	TL0 = 0x18;		 //按一秒时间计时,先计算1ms的对应的初值65535 - 1000 + 1 = 64536
				     //对应16进制 0xFBB4
	EA = 1;		     //中断总开关
	ET0 = 1;         //T0中断开关

}

void time0_isr() interrupt 1  //定时器0中断处理程序
{
	u16++;
	TH0 = 0xfc;
	TL0 = 0x18;

	if(u16 == 1000)
	{
	  u16 = 0;
	  led = !led;
	}


}

void main()
{
	time0_ini();  //调用定时器配置函数,即打开定时器和允许定时器的中断

    while(1);   //主程序
}

内部时钟频率是1MHz,时钟周期是1us。最多能定65535(16位定时器),也就是说最大定时时间为65535*1us=65535us=65.535ms。
如果要定比较长的时间(譬如2s),定时器直接是不能满足的,解决办法是多次定时后加起来构成一个长时间。

实验目的:
(1)使用定时器来完成LED闪烁;
(2)原来实现闪烁时中间的延迟是用delay函数实现的,在delay的过程中CPU要一直耗在这里不能去做别的事情。这是之前的缺点;
(3)本节用定时器来定一个时间(譬如1s),在这个定时器定时时间内CPU还可以去做主任务,定时时间到产生中断,在中断处理程序isr中让LED闪烁即可。 

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

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

相关文章

JPA实现多对多关系

本文已收录于专栏 《Java》 目录 概念说明优势利弊实现方式通过两个ManyToMany注解实现类图代码 通过OneToMany和ManyToOne注解实现类图代码 总结提升 概念说明 多对多关系是指两个实体之间存在多对多的关联关系。在数据库中&#xff0c;多对多关系无法直接表示&#xff0c;需要…

javascript截取两个符号之间的字符串(2):lastIndexOf匹配和正则表达式匹配

lastIndexOf匹配和正则表达式匹配 项目需求1.规范的字符串2.不规范的字符串3-1.万能封装3-2.ChatGPT的优化写法4.正则表达式的用法5.补充知识&#xff1a;lastIndexOf的用法 项目需求 javascript中截取字符串中最后一个“/”和“?”之间的内容。 1.规范的字符串 https://tes…

100天精通Python(可视化篇)——第96天:Pyecharts绘制多种炫酷箱形图参数说明+代码实战

文章目录 专栏导读1. 箱形图介绍1&#xff09;箱形图介绍2&#xff09;怎么看箱型图&#xff1f;3&#xff09;解释说明 2. 普通箱型图3. 水平箱型图4. 群组箱型图5. 带异常点的箱型图 专栏导读 &#x1f525;&#x1f525;本文已收录于《100天精通Python从入门到就业》&#…

Docker实战总结

Docker 官方文档地址:https://www.docker.com/get-started 中文参考手册:https://docker_practice.gitee.io/zh-cn/ 1.什么是 Docker 1.1 官方定义 最新官网首页 # 1.官方介绍 - We have a complete container solution for you - no matter who you are and where you are…

线性回归--波士顿房屋价格预测

一、波士顿房屋价格预测代码 import sysimport pandas as pd import numpy as np from sklearn.linear_model import LinearRegression import matplotlib.pyplot as plt import matplotlib as mpt from sklearn.model_selection import train_test_split##加载数据 datapd.re…

Druid工作原理

Druid工作原理-连接池初始化流程 标题 Druid工作原理-获取连接流程&#xff1a; 连接回收:

类定义练习

运行代码&#xff1a; //类定义练习 #include"std_lib_facilities.h" #include"GUI/Simple_window.h" #include"GUI/GUI.h" #include"GUI/Graph.h" #include"GUI/Point.h" //定义类 class Person { private:string first_n…

直流有刷驱动板电流电压采集

直流有刷驱动板电流电压采集 电流采集会涉及到电流环的使用。 #include "./adc/bsp_adc.h" #include ".\motor_control\bsp_motor_control.h" #include "./led/bsp_led.h" #include "./usart/bsp_debug_usart.h"__IO uint16_t…

vue-element-admin深入系列-数据Mock

本文介绍 vue-element-admin 如何使用 MockJS 实现数据Mock,毕竟对于一个合格的前端来讲,自己能Mock数据是必须的: 自给自足,不用依赖服务端接口。毕竟环境问题是个大问题,更何况环境不稳定是常态,再加上偶尔服务端的数据格式变化,问题就更复杂。 数据复杂,页面复杂时。…

HackTheBox - 学院【CPTS】复习6 - Active Directory

ACTIVE DIRECTORY ENUMERATION & ATTACKS 这个模块其实与thm的AD教程相比&#xff0c;还是thm更适合刚开始接触AD以及学习从枚举到持久化的全阶段&#xff08;红队&#xff09;。而htb学院这个模块更注重于枚举和各种攻击手段&#xff0c;有点纯渗透的风格&#xff0c;弱化…

通过动态IP解决网络数据采集问题

动态地址的作用 说到Python网络爬虫&#xff0c;很多人都会遇到困难。最常见的就是爬取过程中IP地址被屏蔽。虽然大部分都是几个小时内自动解封的&#xff0c;但这对于分秒必争的python网络爬虫来说&#xff0c;是一个关键性的打击&#xff01;当一个爬虫被阻塞时&#xff0c;…

Java内部类笔记

1.为什么使用内部类? 使用内部类最吸引人的原因是&#xff1a;每个内部类都能独立地继承一个&#xff08;接口的&#xff09;实现&#xff0c;所以无论外围类是否已经继承了某个&#xff08;接口的&#xff09;实现&#xff0c; 对于内部类都没有影响 1.1.使用内部类最大的优点…

TCP/IP基础知识笔记

应用层&#xff1a;为用户提供应用功能&#xff0c;比如 HTTP、FTP、Telnet、DNS、SMTP等。 应用层是工作在操作系统中的用户态&#xff0c;传输层及以下则工作在内核态。 传输层&#xff1a;为应用层提供网络支持。 *TCP包含众多特性比如流量控制、超时重传、拥塞控制等因此可…

pytorch深度学习逻辑回归 logistic regression

# logistic regression 二分类 # 导入pytorch 和 torchvision import numpy as np import torch import torchvision from torch.autograd import Variable import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import matplotlib.pyplot as …

(简单)剑指Offer II 056. 二叉搜索树中两个节点的和 Java

方法一&#xff1a;深度优先搜索哈希表 使用深度优先搜索的方式遍历整棵树&#xff0c;用哈希表记录遍历过的节点的值 对于一个值为x的节点&#xff0c;检查哈希表中是否存在k-x即可。如果存在对应的元素&#xff0c;那么我们就可以在该树上找到两个节点的和为k&#xff1b;否…

河流垃圾检测Y8S

【免费】河流垃圾检测Y8M&#xff0c;只需要OPENCV资源-CSDN文库 采用YOLOV8训练&#xff0c;得到PT模型&#xff0c;然后直接转ONNX&#xff0c;使用OPENCV的DNN&#xff0c;不需要其他依赖&#xff0c;支持C/PYTHON

Hadoop 之 分布式集群配置与使用(三)

Hadoop 之 分布式集群 一.集群实例创建二.配置1.创建三个虚拟机&#xff08;Anolis&#xff09;1.修改 HostName2.配置免密登录&#xff0c;配置前 2.配置命名节点1.在 nd1 / nd2 部署 hadoop2.配置 3.查看集群信息 三.测试 一.集群实例创建 以三个 Hadoop 实例创建集群&#…

对战五子棋——网页版

目录 一、项目简介 二、用户模块 1、创建用户实体类 2、编写userMapper接口文件 3、实现userMapper.xml文件 4、对用户密码进行加密 5、实现用户登录功能 6、实现用户注册功能 三、实现用户匹配模块 1、展示用户个人信息 2、匹配请求类 3、匹配响应类 4、创…

郭东白的架构课学习笔笔记(1)

1.架构师的品质 自信和勇气&#xff08;正确的废话&#xff09;拥有战略意图&#xff0c;所谓战略意图&#xff0c;就是拥有与其资源和能力极不相称的雄心壮志。使用演绎法寻找架构原理&#xff0c;而不是归纳法。 2.如何提升自己的架构能力 向身边比自己厉害的优秀架构师或…

【网络安全带你练爬虫-100练】第14练:文件内容的读取、取出

目录 一、目标1&#xff1a;把文件内容遍历取出 二、目标2&#xff1a;把文件内容全部取出 三、网络安全O 一、目标1&#xff1a;把文件内容遍历取出 &#xff08;1&#xff09;如果文件脚本在不同目录 file_path "path/to/your/file.txt" # 替换为你的文件路径…