51单片机快速入门之定时器和计数器

51单片机快速入门之定时

断开外部输入

晶振振荡 假设为 12MHz

12分频之后,为1MHz 当其从0-65536 时,需要65536μs 微秒 也就是65.536ms 毫秒

溢出(值>=65536 时)>中断>执行中断操作

假设需要1ms后产生溢出,则需要设置初始值为64536

此时定时器会从  64536 开始计数 (1000μs 微秒 = 1 ms 毫秒 )    

51单片机快速入门之计数器

计算外部输入的脉冲信号
假设设置其为16位计数器,其最大计数值为 2^16=65536
溢出(值>=65536 时)>中断>执行中断操作

假设需要100个脉冲后产生溢出,则需要设置初始值为65436

此时计数器会从  65436 开始计数   

结构原理

由 两个8位 计数器构成的  16位 计数器
TCON 寄存器 控制 开(1) / 关(0)
TMOD 寄存器 设置 工作方式 (定时还是计数)

TMOD寄存器

以下图片来源于stc89c52官方数据手册:

 这个GATE用于IO口控制 定时器  使用(1) / 不使用(0)  如果需要IO口控制 需设置其为 1

C/T 设置是 定时器 断开引脚输入 还是 计数器 从引脚输入

M1 M0 为模式选择,有不同的搭配

0   0 时 为13位 模式 (由 两个8位 计数器构成的  16位 计数器)  一计数器低5位 | 二计数器全8位

低五位计数器溢出时,它会向高八位计数器提供一个进位信号,这个信号会使高八位计数器的值加1。此时,低五位计数器会自动复位为其最小值(通常为0)


低 5 位”通常是指一个二进制数的最右边的 5 个比特位 从右向左数

举例:16位二进制数 1010 1100 0101 1001 低五位 就为 10011


0  1 时 为16位 两个8位全用

1  0 时  为8位自动重载 第一个计数器溢出之后,先转移当前值到 第二个计数器中,再复位为0

每次溢出时,第二个计数器的值就会增加(或减少,取决于计数方向)

1   1 时 停止计数(暂停)

这里要注意数据手册上标注 当M1 M0 都为 1 时  定时器 0 的工作方式

第一个计数器可以设置成   8位定时器/计数器 受 定时器 0 控制

但是 第二个计数器 只能是 8位定时器 受 定时器 1 控制

TCON寄存器 

以下图片来源于stc89c52官方数据手册: 

 定时器1

TF1 溢出标志位 (溢出时其为 1 ,会向CPU 请求中断 ,CPU响应后 0) 可手动设置

TR1 运行控制位 (控制开/关 ) 这里要注意TMOD中 GATE 的设置


 定时器0

 TF0 溢出标志位 (溢出时其为 1 ,会向CPU 请求中断 ,CPU响应后 0) 可手动设置

 TR0 运行控制位 (控制开/关 ) 这里要注意TMOD中 GATE 的设置


IE1 / IE0  分别为 外部中断1 / 外部中断0 请求标志位

有请求时为1 处理后  由硬件自动清0(默认为0)


IT1 / IT0 分别为外部中断1 / 外部中断 0 触发方式控制位 为0 是低电平触发

程序设计时:在中断服务例程(ISR)的开始部分直接控制IO拉高(低电平触发时)

假设设置为 低电平 触发

低电平时 IE0或IE1 会被置位,即设置为1 表示有一个中断请求待处理

中断请求来时,以下步骤会发生:

  1. 中断请求使IE0或IE1置位(设置为1)。
  2. CPU响应中断请求,暂停当前的任务,并跳转到中断服务例程(ISR)。
  3. 在ISR中,你处理中断请求,完成相应的任务。
  4. 在ISR结束之前,你需要手动或自动 清零IE0或IE1,以表示中断请求已经被处理完毕。

定时器 程序设计 

例子:产生1kHz方波信号  时钟频率12MHz
分析:
        信号周期T=1/f  T=1/1000 =1ms 
        高低电平设计为0.5ms(500μs)
        定时初始值计算公式:2^16-定时值=2^16-500=65036
第一计数器 A 存储 初值 高八位,第二计数器 B 存储 初值 低八位

在计算机科学中,一个字节由8位二进制数字组成。这8位数字可以分为高四位和低四位,也可以称为高四位和低四位。

  • 高八位:指的是这个字节中最左边的8位,也就是最高位的那一部分。
  • 低八位:指的是这个字节中最右边的8位,也就是最低位的那一部分。

65036(10进制)转换成16进制为 0xFE0C   A存储FE  B存储0C

因 65036 数过大,计算比较费劲 所以要适当 缩小 

65036/256=取商得到  254

计数器值常需除以256,因计算机处理数据以字节为单位,每字节8位,可表256个值(0-255)。此操作适用于字节操作、防止溢出、图像处理中表示颜色深度、遵循数据格式及简化数学计算。

在计算机科学和电子工程中,计数器的值经常需要  除以256,这通常是因为以下几个原因:

1. 字节操作:

        计算机中的数据通常以字节(byte)为单位处理,而一个字节等于8位(bit)。由于256等于2的8次方(2^8),它刚好是一个字节可以表示的最大整数值(从0到255)。因此,当处理字节或进行位操作时,256是一个关键的参考点。


2. 溢出和模运算:

        计数器在增加过程中可能会超过其最大表示范围,导致溢出。如果一个计数器是用一个字节表示的,那么当它的值超过255时,就会从0开始循环。这种现象可以用模运算(即取余数)来描述,而模数通常是256。


3. 颜色深度:

        在图形和图像处理中,每个像素的颜色可能由若干个字节表示,比如RGB色彩模型中,每个颜色分量(红、绿、蓝)通常用一个字节表示,因此有256种可能的强度级别。


4. 协议和数据格式:

        某些通信协议或数据格式可能规定了特定的字段长度或计数范围,这时候使用256作为基数可以帮助确保兼容性和标准化。


5. 数学和算法:

        在一些数学算法和数据结构中,256因其与二进制系统的紧密关系,常常被用作基数或除数,以简化计算和逻辑操作。

总的来说,除以256的操作反映了计算机系统中对字节边界和模运算的常见需求。

65036%256=取余数 12

在计算机科学和数学中,取余数(模运算)是一种非常常见的操作。当我们对一个数进行除法运算时,余数是除不尽的部分。取余数的操作可以帮助我们解决以下几类问题:

  1. 溢出处理:在某些系统中,例如基于字节的操作,我们需要确保数值不会超过某个范围(如0到255)。通过取余数,我们可以使数值“循环”回这个范围内,避免溢出。

  2. 周期性事件:如果我们想要跟踪每隔一定数量的事件发生的情况(比如每256个事件),取余数可以帮助我们确定是否到达了这个周期的某个特定点。

  3. 密码学:在密码学中,模运算是基础操作之一,用于创建和解密密码系统。

  4. 数据校验和压缩:在数据传输和存储中,模运算可以用于生成和验证校验和,以检测错误。在某些压缩算法中,它也被用来减少数据的大小。

  5. 数学算法:许多数学算法和公式中会用到模运算,因为它可以简化计算,特别是在处理大数时。

对于65036除以256的情况,取余数的操作可以告诉我们65036在256的倍数之间的“剩余”部分是多少。

 定时器 程序代码

设置工作模式 :第一计数器 A 存储 初值 高八位,第二计数器 B 存储 初值 低八位

TMOD=0X01;
//0x01 是一个十六进制数,它代表的二进制数是 0000 0001
A=65036/256;//存储高八位
B=65036%256;//存储低八位
EA=1;//打开总中断
ET0=1;//允许定时器0中断
TR0=1;//打开定时器0

定时器 中断函数代码 

 void T0(void) interrupt 1 using 1

{

A=65036/256;//存储高八位   复位
B=65036%256;//存储低八位 复位

这里放入中断后需要做的操作

}

 代码解释:
  1. void T0(void):这是一个函数声明,表明函数 T0 不接受任何参数,并且不返回任何值。
  2. interrupt 1:这是关键字和参数,用于指定这个函数是一个中断服务例程,其中 1 表示中断号。不同的中断号对应不同的中断源.
  3. using 1:这是另一个关键字和参数,用于指定该中断服务例程使用的工作寄存器组。在一些微控制器中,允许程序员在中断服务例程中使用不同的工作寄存器组,以避免与主程序中的寄存器冲突。这里的 1 表示使用第1个工作寄存器组。
中断号解释:  interrupt
  1. 外部中断0 (INT0)         中断号0
  2. 定时器/计数器0 (T0)    中断号1
  3. 外部中断1 (INT1)         中断号2
  4. 定时器/计数器1 (T1)    中断号3
  5. 串行口中断 (串行I/O)   中断号4
寄存器组解释: using 参考链接icon-default.png?t=O83Ahttps://blog.csdn.net/cssdl/article/details/41674095?sharetype=blogdetail&sharerId=41674095&sharerefer=PC&sharesource=qq_43422073&sharefrom=from_link

R0-R7在数据存储器里的实际地址是由特殊功能寄存器PSW里的RS1、RS0位决定的。

using 0时
        设置 RS1=0,RS0 =0,用第0组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。R0(00H)....R7(07H)


using 1时
        设置 RS1=0,RS0 =1,用第1组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。R0(08H)....R7(0FH)


using 2时
        设置 RS1=1,RS0 =0,用第2组寄存器,R0--R7的在数据存储区里的实际地址是08H-0FH。R0(10H)....R7(17H)


using 3时
        设置 RS1=1,RS0 =1,用第3组寄存器,R0--R7的在数据存储区里的实际地址是00H-07H。R0(18H)....R7(1FH)

计数器为什么要复位 :

在单片机编程中,特别是涉及到定时器/计数器的中断服务例程时,经常会看到这样的情况:在中断服务例程的开始部分,会将一些寄存器的值重新赋值给计数器。

1. 防止溢出:

        定时器/计数器在达到最大值后会溢出并从零开始计数。如果不重新赋值,计数器可能会继续从溢出点开始计数,导致不正确的结果。通过在中断服务例程中重新赋值,可以确保计数器从预期的值开始计数。


2. 实现精确的定时:

        在一些应用中,需要实现非常精确的定时。通过在中断服务例程中重新赋值计数器,可以调整定时器的计数值,从而实现更精确的定时。


3. 初始化计数器:

        在中断服务例程中,可能需要对计数器进行初始化,以便从一个已知的状态开始。这在处理复杂的定时任务或多任务环境中尤为常见。


4. 实现周期性任务:

        如果中断服务例程需要周期性地执行某些任务,可以通过重新赋值计数器来实现这一点。例如,如果中断服务例程每1毫秒执行一次,可以在中断服务例程的开始部分将计数器设置为一个适当的值,以确保下次中断发生在1毫秒后。


5. 处理中断嵌套:

        在多中断环境下,可能会出现中断嵌套的情况。在这种情况下,需要确保每次中断服务例程执行时,计数器的值是正确的。通过在中断服务例程中重新赋值计数器,可以确保这一点。


中断相关资料 

EX0:EX0=1,允许外部中断0中断;EX0=0,禁止中断
ET0:ET0=1,允许T0中断;ET0=0,禁止中断
EX1:EX1=1,允许外部中断1中断;EX1=0,禁止中断
ET1:ET1=1,允许T1中断;ET1=0,禁止中断
ES:ES=1,允许串行口中断;ES=0,禁止中断

EA:EA=1,CPU开放中断;EA=0,CPU禁止所有的中断请求

中断相关 参考链接icon-default.png?t=O83Ahttps://blog.csdn.net/weixin_43398418/article/details/121916218?sharetype=blogdetail&sharerId=121916218&sharerefer=PC&sharesource=qq_43422073&sharefrom=from_link


 TMOD=0X01;
//0x01 是一个十六进制数,它代表的二进制数是 0000 0001

 这里操作的是 定时器0  按位带入以下图片中 可以知道定时器0 的 M1=0 M0=1

M1=0 M0=1 时 为16位 两个8位全用


计数器程序代码 

例子: 50kHz方波信号  时钟频率12MHz

TMOD=0X20;
//0X20 是二进制 0010000 控制的是定时器1
//结合上图M1=1 M0=0为8位自动重载 第一个计数器A1溢出之后,先转移当前值到 第二个计数器B1中,再复位为0
A1=246;//设置初始值 溢出相关
B1=246;//设置初始值
//246-256 需要10μs 
EA=1;//打开总中断
ET1=1;//打开定时器1中断
TR1=1;//启动定时器1
void T1(void) interrupt 3 using 1
{
//因为是8位重载所以不用初始化计数器
//这里放入需要做的操作

}

注意:以上代码省略了main()主函数

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

掌握 JavaScript ES6+:现代编程技巧与模块化实践

掌握 JavaScript ES6:现代编程技巧与模块化实践 一 . 变量声明 let二 . 声明常量 const三 . 模板字符串四 . 函数的参数默认值五 . 箭头函数六 . 对象初始化七 . 解构7.1 接收 JSON 对象7.2 接收数组 八 . 延展操作符九 . 导入和导出9.1 方式一9.2 方式二 这篇文章我…

Android视频编辑:利用FFmpeg实现高级功能

在移动设备上进行视频编辑的需求日益增长,用户期望能够在智能手机或平板电脑上轻松地编辑视频,以满足社交媒体分享或个人存档的需求。Android平台因其广泛的用户基础和开放的生态系统,成为视频编辑应用的理想选择。FFmpeg,作为一个…

Maven入门学习笔记

一、maven介绍 Maven是一款自动化构建工具,专注服务于JAVA平台的项目构建和依赖管理。在javaEE开发的历史上构建工具的发展也经历了一系列的演化和变迁。 管理jar包 当我们使用SSM之后我们就需要使用非常多的jar包 没有maven找jar包非常的麻烦。 使用maven下载…

简单了解 JVM

目录 ♫什么是JVM ♫JVM的运行流程 ♫JVM运行时数据区 ♪虚拟机栈 ♪本地方法栈 ♪堆 ♪程序计数器 ♪方法区/元数据区 ♫类加载的过程 ♫双亲委派模型 ♫垃圾回收机制 ♫什么是JVM JVM 是 Java Virtual Machine 的简称,意为 Java虚拟机。 虚拟机是指通过软件模…

WPF DataGrid 列表中,DataGrid.Columns 列根据不同的值显示不同内容

需求&#xff1a;在WPF DataGrid 控件中&#xff0c;有以下列&#xff0c;绑定了一个LogType&#xff0c;值分别是0,1,2&#xff0c;根据不同的值&#xff0c;显示不同的内容以及背景 <DataGrid ItemsSource"{Binding EventLog}"><DataGrid.Columns><…

代码管理工具——git及阿里云云效的使用(包含git的使用及云效自动化部署)

1、做项目开发时都会用到代码管理工具,像是我之前使用过gitHub,Visual Studio等一些代码管理工具&#xff0c;这里介绍的是阿里云云效的使用。 2、首先登录阿里云云效&#xff0c;登录进去之后会看到公司给你开放的一个仓库。 3、进入仓库&#xff0c;点击克隆/下载&#xff0…

Google大数据架构技术栈

数据存储层 Colossus Colossus作为Google下一代GFS&#xff08;Google File System&#xff09;。 GFS本身存在一些不足 单主瓶颈 GFS 依赖单个主节点进行元数据管理&#xff0c;随着数据量和访问请求的增长&#xff0c;出现了可扩展性瓶颈。想象一下&#xff0c;只有一位…

网红酒店|基于java的网红酒店预定系统(源码+数据库+文档)

酒店预定|网红酒店|网红酒店预定系统 目录 基于java的网红酒店预定系统 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&am…

R语言统计分析——功效分析(比例、卡方检验)

参考资料&#xff1a;R语言实战【第2版】 1、比例检验 当比较两个比例时&#xff0c;可使用pwr.2p.test()函数进行功效分析。格式为&#xff1a; pwr.2p.test(h, n, sig.level, power, alternative) 其中&#xff0c;h是效应值&#xff0c;n是各相同的样本量。效应值h的定义如…

智能头盔语音识别声控芯片,AI离线语音识别ic方案,NRK3301

头盔是交通事故中保护电动车车主安全的最后一道屏障。为了增加骑行用户的安全保护&#xff0c;改善骑行用户的出行体验&#xff0c;让用户从被动使用头盔到主动佩戴头盔&#xff0c;头盔厂家与九芯电子合作&#xff0c;推出了语音智能头盔&#xff0c;它具备首家骑行专用的智能…

C++核心编程和桌面应用开发 第三天(C和C++的封装)

目录 1.封装 1.1C语言封装缺陷 1.2C下的封装 1.3封装的访问权限 2.C中struct和class的区别&#xff1a; 1.封装 1.1C语言封装缺陷 1.2C下的封装 优点1&#xff1a;将属性和行为作为整体&#xff0c;表现生活中的事务 优点2&#xff1a;将属性和行为加以访问权限控制 1…

vue的路由

v2用3版本&#xff0c;v3用4版本 import Vue from vue import VueRouter from vue-router Vue.use(VueRouter) const routes [] const router new VueRouter({ routes }) export default router import Vue from vue import App from ./App.vue import router from /router V…

kkFileView PDF Image Mode Preview BUG

kkFileView PDF & Image Mode Preview BUG lazyload.js officePicture.ftl pdf.ftl kkFileView getCorsFile?urlPath 会触发SSRF漏洞 kkFileView SSRF-CSDN博客 commonHeader.ftl initWaterMark() 修改代码的工作量&#xff0c;主要是先部署项目&#xff0c;解…

微信小程序开发——比较两个数字大小

在这里我们使用的工具是 需要自行安装和配置。 在微信小程序中比较两个数字大小有以下几种方式&#xff1a; 一、普通条件判断 在小程序的.js 文件中&#xff0c;先定义两个数字&#xff0c;如let num1 5; let num2 3;。通过if - else if - else语句&#xff0c;根据num1与…

Machine Learning: A Probabilistic Perspective 机器学习:概率视角 PDF免费分享

下载链接在博客最底部&#xff01;&#xff01; 之前需要参考这本书&#xff0c;但是大多数博客都是收费才能下载本书。 在网上找了好久才找到免费的资源&#xff0c;浪费了不少时间&#xff0c;在此分享以节约大家的时间。 链接: https://pan.baidu.com/s/1erFsMcVR0A_xT4fx…

TypeScript:泛型

一、简介 软件工程中&#xff0c;我们不仅要创建一致的定义良好的API&#xff0c;同时也要考虑可重用性。 组件不仅能够支持当前的数据类型&#xff0c;同时也能支持未来的数据类型&#xff0c;这在创建大型系统时为你提供了十分灵活的功能。 在像C#和Java这样的语言中&#x…

银河麒麟桌面系统卸载应用报错快速解决

银河麒麟桌面系统卸载应用报错快速解决 1、问题简述2、解决方案步骤 1: 删除dpkg信息步骤 2: 强制卸载步骤 3: 验证与清理 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、问题简述 在银河麒麟桌面系统中卸载应用时&#xff0c;可能会遇…

16 训练自己语言模型

在很多场景下下&#xff0c;可能微调模型并不能带来一个较好的效果。因为特定领域场景下&#xff0c;通用话模型过于通用&#xff0c;出现多而不精。样样通样样松&#xff1b;本章主要介绍如何在特定的数据上对模型进行预训练&#xff1b; 训练自己的语言模型&#xff08;从头开…

DSLogic 逻辑分析仪的使用-I2C协议

一、I2C IIC-BUS&#xff08;Inter-IntegratedCircuit Bus&#xff09;最早是由PHilip半导体&#xff08;现在被NXP收购&#xff09;于1982年开发。 主要是用来方便微控制器与外围器件的数据传输。 它是一种半双工&#xff0c;由SDA&#xff08;数据&#xff09;和SCL&#xf…

USBCANFD卡再汽车电子行业中得应用

随着汽车电子的高速发展&#xff0c;车内信息的急剧增多&#xff0c;传统的CAN总线的数据传输能力已经很难满足车辆ECU的数据传输需求了&#xff0c;此时CANFD就应运而生了。 CANFD和CAN最主要的区别就是CANFD的ID段和数据段能够以不同的速率传输数据&#xff0c;这就保证了即使…