51单片机——定时器中断实验,小白讲解,相互学习

news2024/11/14 14:09:34

定时器介绍

1,CPU时序的有关知识

  1. 震荡周期:为单片机提供定时信号的震荡源的周期(晶振周期或外加震荡周期)。
  2. 状态周期:2个震荡周期为1个状态周期,用S表示。震荡周期又称S周期或时钟周期。
  3. 机器周期:1个机器周期含6个状态周期,12个震荡周期
  4. 指令周期:完成1条指令所占用的全部时间,他以机器周期为单位。
  • 例如:外界晶振为12MHz时,51单片机相关周期的具体值为:
  • 震荡周期=1/12us
  • 状态周期=1/6us
  • 机器周期=1us
  • 指令周期=1~4us

2,学习定时器前需要明白的几点

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

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

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

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

51单片机的定时原理

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

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

51单片机定时器/计数器内部结构图如下:

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

 1,工作方式寄存器TMOD

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

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

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

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

2,控制寄存器TCON

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类同。

51单片机定时/计数器的工作方式

1,方式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=2^13- N。

2,方式1

         方式1的计数位数是16位,由TL0作为低8位,TH0作为高8位,组成了16位加 1 计数器。其结构图如下所示:

计数初值与计数个数的关系为:X=2^16-N

3,方式2

        方式2位自动重装初值的8位计数方式。工作方式2特别适合用作较精确的脉冲信号发生器。其结构图如下所示:

计数初值与计数个数的关系为:X=2^-N

4,方式3

        方式3只适用于定时/计数器T0,定时器T1处于方式3时相当于TR1=0,停止计数。工作方式3将T0分成为两个独立的8为计数器TL0和TH0。其结构如下所示:

         这几种工作方式中应用较多的是方式1和方式2.定时器中通常适用定时器方式1,串口通信中通常适用方式2.

定时器配置

在适用定时器时,应该如何配置使其工作?其步骤如下(各步骤顺序可任意):

①对TMOD赋值,以确定T0和T1的工作方式,如果适用定时器0即对T0配置,如果使用定时器1即对T1配置。

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

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

④适用TR0 或 TR1 置位,启动定时/计数器定时或计数。

        上述中有一个定时/计数器初值的计算,下面我们来看如何计算定时/计数器初值。

        前面我们介绍过机器周期的概念,它是CPU完成的一个基本操作所需要的时间。其计算公式是:机器周期=1/单片机的时钟频率。51单片机内部时钟频率是外部时钟的12分频,也就是说当外部晶振的频率输入到单片机里面的时候要进行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的次数,表示已经定时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;//打开定时器
}

         对于定时器 1 的使用方法是一样的,只是将上述的0变为1即可,具体可参考我们定时器1实验例程。

软件设计

本章所要实现的功能是:通过定时器0中断控制D1指示灯间隔1秒闪烁.

/**********************************************************************************
****
实验名称:定时器 0 实验
接线说明:
实验现象:下载程序后,当按下 D1 指示灯间隔 1s 闪烁
注意事项:
***********************************************************************************
****/
#include "reg52.h"
typedef unsigned int u16;//对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义 LED1 管脚
sbit LED1=P2^0;
/*******************************************************************************
* 函 数 名 : delay_10us
* 函数功能 : 延时函数,ten_us=1 时,大约延时 10us
* 输 入 : ten_us
* 输 出 : 无
*******************************************************************************/
void delay_10us(u16 ten_us)
{
    while(ten_us--);
}
/*******************************************************************************
* 函 数 名 : time0_init
* 函数功能 : 定时器 0 中断配置函数,通过设置 TH 和 TL 即可确定定时时间
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void time0_init(void)
{
    TMOD|=0X01;//选择为定时器 0 模式,工作方式 1
    TH0=0XFC; //给定时器赋初值,定时 1ms
    TL0=0X18;
    ET0=1;//打开定时器 0 中断允许
    EA=1;//打开总中断
    TR0=1;//打开定时器
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
void main()
{
    time0_init();//定时器 0 中断配置
    while(1)
    {
    }
}
void time0() interrupt 1 //定时器 0 中断函数
{
    static u16 i;//定义静态变量 i
    TH0=0XFC; //给定时器赋初值,定时 1ms
    TL0=0X18;
    i++;
    if(i==1000)
    {
        i=0;
        LED1=!LED1;
    }
}

        首先定义LED1指示灯控制管脚,然后定义定时器0中断配置函数 time0_init,该函数配置内容就按照前面介绍的配置方法所写,即选择定时器工作模式0,工作方式1,设置定时1ms初值,打开定时器计数功能和开启总中断功能。然后进入while 循环,在循环体内没有执行任何功能程序。当定时时间达到即会进入定时器0中断,在中断服务函数内,重新赋初值准备下次计数,并且定义一个静态变量来累计定时 1ms 次数,当变量等于1000 时,表示定时时间达 1秒,然后清零变量以及控制LED状态翻转。执行完成后退出中断返回住函数,当时间到达又进入中断,如此循环。

        为什么要适用关键字static将i定义为静态变量呢?我们希望每次进入中断函数时,i保存的是上次累加值,使用了static 关键字,就可以让变量 i 实现这种功能,即不会每次进入中断函数后被初始化为0。假如去掉static 关键字,那么变量 i 就是一个局部变量,每次进入中断函数后,变量 i 初始值都是0,也就是说它的值永远不会递增到1000,从而实现不了1s定时。可以这样理解,使用了 static 关键字就相当于将i 变成了全局变量功能。

        对于定时器 1 的使用方法是一样的,只是将上述的 0 变为 1 即可,具体可参考我们定时器 1 实验例程

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

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

相关文章

Java-多线程并发-线程的实现、调度和状态转换

线程的实现 线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源( 内存地址、文件I/O等 ),又可以独立调度( 线程是CPU调度的基本单位 )。 Java语言则提供了在不…

300行代码手写spring初体验v1.0版本

70%猜想30%验证 spring:IOC 、DI、AOP、MVC MVC作为入口 web.xml 内部依赖一个DispathcheServlet这样一个接口 先来说一下springMVC的一些基础知识 整体的一个思路: 在web.xml里面进行了一个核心servlet的一个配置 核心就是这个DispatcherServlet …

用列表y表示序列x中每个元素是否被选中 根据列表y返回序列x中被选中的元素 itertools.compress(x,y)

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 用列表y表示序列x中每个元素是否被选中 根据列表y返回序列x中被选中的元素 itertools.compress(x,y) [太阳]选择题 以下关于python代码表述错误的一项是? from itertools import compress …

2022年全国职业院校技能大赛(中职组)网络安全竞赛试题A模块(4)

目录 二、竞赛注意事项 (本模块20分) 一、项目和任务描述: 二、服务器环境说明 三、具体任务(每个任务得分以电子答题卡为准) A-1任务一 登录安全加固(Windows) 1.密码策略 a.更改或创建…

未来的城市:智慧城市定义、特征、应用、场景

智慧城市是通过连接一个地区的物理、经济和社会基础设施,以创新、有效和高效的方式应用和实施技术来发展城市的概念,以改善服务并实现更好的生活质量。智慧城市是一个将信息和通信技术融入日常治理的城市区域,旨在实现效率、改善公共服务、增…

Kafka优化篇-压测和性能调优

简介 Kafka的配置详尽、复杂,想要进行全面的性能调优需要掌握大量信息,这里只记录一下我在日常工作使用中走过的坑和经验来对kafka集群进行优化常用的几点。 Kafka性能调优和参数调优 性能调优 JVM的优化 java相关系统自然离不开JVM的优化。首先想到…

消息队列(kafka简单使用)

Dubbo远程调用的性能问题Dubbo调用普遍存在于我们的微服务项目中这些Dubbo调用全部是同步的操作这里的"同步"指:消费者A调用生产者B之后,A的线程会进入阻塞状态,等待生产者B运行结束返回之后,A才能运行之后的代码Dubbo消费者发送调用后进入阻塞状态,这个状态表示该线…

再学C语言39:指针操作(2)

在编写处理int这样的基本类型的函数时,可以向函数传递int数值,也可以传递指向int的指针 通常直接传递int数值,只有需要在函数中修改该值时,才传递指针 对于处理数组的函数,只能传递指针,这样能使程序效率…

如何运行YOLOv6的代码实现目标识别?

YOLOv6是由美团视觉团队开发的1.环境配置我们先把YOLOv6的代码clone下来git clone https://github.com/meituan/YOLOv6.git安装一些必要的包pip install pycocotools2.0作者要求pytorch的版本是1.8.0,我的环境是1.7.0,也是可以正常运行的pip install -r requirement…

C#服务号推送微信公众号模板消息

一、准备工作微信公众平台:https://mp.weixin.qq.com/申请测试账号:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?actionshowinfo&tsandbox/index微信推送消息模板不需要发布服务器,也不需要填写授权回调域名,只需要…

【Vagrant】下载安装与基本操作

文章目录概述软件安装安装VirtualBox安装Vagrant配置环境用Vagrant创建一个VMVagrantfile文件配置常用命令概述 Vagrant是一个创建虚拟机的技术,是用来创建和管理虚拟机的工具,本身自己并不能创建管理虚拟机。创建和管理虚拟机必须依赖于其他的虚拟化技…

11 OpenCV图像识别之人脸识别

文章目录1 Eigenfaces1.1 建模流程1.2 示例代码2 Fisherfaces2.1 建模流程2.2 示例代码3 Local Binary Histogram3.1 建模流程3.2 示例代码OpenCV 提供了三种人脸识别方法:Eigenfaces Eigenfaces是一种基于PCA(Principal Component Analysis&#xff0c…

多城市二手车买卖发布管理小程序开发

多城市二手车买卖发布管理小程序开发 功能特性: 为你介绍二手车微信小程序的功能特性。 车辆分类搜索,支持按品牌、售价、年龄、上牌时间、排量等筛选。 车源发布,支持用户一键发布二手车,平台审核上线,发布可编辑、删除等操作。…

【结构体版】通讯录

👦个人主页:Weraphael ✍🏻作者简介:目前是C语言学习者 ✈️专栏:项目 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&#x…

扬帆优配|五千亿巨头一度涨停! 4天3倍,港股又现“狂飙”股!

周一,A股三大指数走势分化。到午间收盘,沪指震荡走高涨近1%,深证成指涨0.75%,创业板指继续弱势调整。 盘面上,钢铁、煤炭、大金融等权重板块团体走强,三大通讯运营商一同拉升,其间我国电信盘中一…

合作协议书合同怎么写?

合作协议书合同怎么写?以品牌推广的合作协议书合同为例,参考内容如下:业务合作协议甲方(项目方):乙方(客户推荐方):甲乙双方本着平等自愿、互惠互利原则,就结…

(十五)docker安装sentinel,客户端配置规则本地持久化

一、简介 操作系统:Linux CentOS 7.3 64位 docker版本:19.03.8 sentinel版本:1.8.0 二、实践 1、拉取镜像 docker pull bladex/sentinel-dashboard:1.8.0 2、运行容器 docker run --name sentinel \ -p 8858:8858 \ --privilegedtrue …

django项目实战三(django+bootstrap实现增删改查)进阶分页

目录 一、分页 1、修改case_list.html页面 2、修改views.py的case_list方法(分页未封装) 二、分页封装 1、新建类Pagination 2、修改views.py的case_list方法 三、再优化,实现搜索分页qing情况 四、优化其他查询页面实现分页和查询 五…

如何寻找SAP中的增强

文章目录0 简介1 寻找一代增强2 寻找二代增强2.2 在包里也可以看到2.3 在出口对象里输入包的名字也可以找到2.4 通过以下函数可以发现已有的增强2.5 也可以在cmod里直接找2.6 总结3 寻找第三代增强0 简介 在SAP中,对原代码的修改最不容易的是找增强,以下…

Springboot 整合 分布式定时任务 XXL-JOB

起因 恰逢周末, 最近公司接入了分布式定时任务,我是负责接入这块的,正好在网上想起了之前看过的分布式任务的文章,然后学习一下 各路框架发现看了很多框架比如 elasticjob 跟xxl-job不同的是,elasticjob是采用zookeepe…