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

news2024/11/19 19:28:27

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()主函数

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

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

相关文章

AD6120 60V降压芯片 2A的电流 适用于48V降12/5v 高效率转换

AD6120是一款电流模式单片降压开关稳压器,输入电压范围为5V~60V,可在宽输入电压范围内提供2A的连续输出电流,具有优异的负载和线路调节能力。在轻负载下,该稳压器以低频率运行,以保持高效率和低输出纹波 。电流模式控制…

性能测试-jmeter连接数据库(十七)...

百度服务器域名:www.baidu.com 百度的IP:110.242.68.3(使用ping www.baidu.com) jdbc:mysql://211.103.136.244:7061/test_db: mysql是数据库类型211.103.136.244是服务器IP7061是服务器端口号test_db是服务器的数据库 一、为…

Vite项目中的懒加载介绍

概述 import.meta 元属性将特定上下文的元数据暴露给 JavaScript 模块。它包含了这个模块的信息,例如这个模块的 URL。在vue3项目中,用的比较多的是通过import.meta.env来获取环境变量。而本文将要介绍的import.meta.glob和import.meta.env都是vite提供…

【零基础学习CAPL】——CRC值监控测试

🙋‍♂️【零基础学习CAPL】系列💁‍♂️点击跳转 ——————————————————————————————————–—— 从0开始学习CANoe使用 从0开始学习车载车身 相信时间的力量 星光不负赶路者,时光不负有心人。 目录 1.概述2.需求介绍3.算法4.逻辑判断5.测…

VS2022中文字符输出为乱码的解决

一、问题 vs2022输出中文时,出现乱码现象 二、解决方案 把文件的字符编码格式改为utf-8格式 选择工具,点击自定义 选择命令,点击添加命令 选择文件,点击高级保存选项,然后点击确定 点击高级保存选项 选择utf-8编…

Android10源码刷入Pixel2以及整合GMS

一、ASOP源码下载 具体可以参考我之前发布的文章 二、下载相关驱动包 这一步很关键,关系到编译后的镜像能否刷入后运行 下载链接:Nexus 和 Pixel 设备的驱动程序二进制文件 如下图所示,将两个驱动程序上传到Ubuntu服务器,并进行解压,得到两个脚本: 下载解压后会有两…

华为SMU02B1智能通信电源监控单元模块简介

华为SMU02B1是一款智能通信电源监控单元模块,专为5G嵌入式机框设计,它在通信电源管理领域扮演着重要角色。以下是对该产品的详细介绍: 一、产品概述 主要功能:华为SMU02B1能够监控和管理通信电源系统,提供站点监控功能…

QLExpress规则引擎简述;字符串公式/脚本运算

概述 在业务中会遇到一些场景的运算方式不是固定的,而且内容不是有规律的,无法落库到表中(强行落库后也需要针对该内容硬编码写一段特殊的查询方式); 这个时候将这部分计算抽取出来,用一个动态的脚本去执…

Spring web mvc入门练习

对于Spring方面的知识重在多练习 目录 一、计算器 1、前端界面 2、约定前后端交互接口 3、服务器代码 二、用户登录 前端代码 服务器代码 三、留言板 后端代码 前端代码 一、计算器 我们需要通过前后端的交互最终完成这样的界面以及完成需求 1、前端界面 因为主要…

windows系统离线搭建darknet

没有网的情况下采用将安装包全部都下载下来,再安装的方式。darknet在windows上编译问题比较多,经历了3天的踩坑,终于搭建好。。。下面简单记录一下安装过程。 1.下载cuda,cudnn,anaconda,opencv,opencv_python,vs。安装顺序&…

[Redis] Redis中的Hash类型和List类型

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…

CISP-PTE CMS sqlgun靶场渗透测试

1.打开靶场 2.在搜索框尝试xss <script>alert(1)</script> 发现此处存在xss漏洞 3.在搜索框尝试sql注入 -1 union select 1,2,3# 发现页面有回显 4.查询数据库名 -1 union select 1,database(),3# 5.查询数据库的所有表 -1 union select 1,(select group_conc…

Matlab做二阶函数

关于解答&#xff1a; >> % Expert PID Control % 二阶传递函数的阶跃响应 % 位置式 clc; clear all; close all;n500; % 设置离散点的个数 Ts0.001; % 设置离散的采样时间 epsilon0.001; …

剪辑视频怎么放慢速度?6种方法可以轻易做到

在这个快节奏的短视频时代&#xff0c;视频编辑中的慢动作效果往往能吸引观众的眼球&#xff0c;赋予画面以独特的艺术感和情感深度。但是很多小伙伴不知道该怎么将视频播放速度放缓&#xff0c;今天&#xff0c;给大家分享6种剪辑视频放慢速度的高效方法&#xff0c;一起来学习…

【物理编程】解决物理压力的正确画法

这里写自定义目录标题 压力的画法 压力的画法 该程序是一个交互式的教育工具&#xff0c;它通过可视化的方式帮助学生和教师理解多边形的几何特性以及力的表示方法。以下是该程序的一些优点和对教师的帮助&#xff0c;用专业的语言进行总结&#xff1a; 增强理解力&#xff1a…

98、RS485全自动收发电路入坑笔记

因为RS485采用叉分信号&#xff0c;只支持半双工。正常的RS485芯片驱动电路是需要GPIO来切换发送和接收模式。如下图所示&#xff0c;一般的RS485电平转换芯片都有RE/DE脚&#xff0c;用来切换收发模式。 例如这篇推荐&#xff1a;芯片RS485自动收发电路常见问题与应对策略 但…

【kubernetes】Ingress和Ingress-Controller介绍,高可用应用案例

一&#xff0c;Ingress介绍 Ingress是k8s中一种重要的资源对象&#xff0c;它主要用于定义从集群外部到集群内部服务的HTTP(S)路由规则。用于管理代理 Ingress-Controller的配置文件。 kubectl explain ingress二&#xff0c;Ingress-Controller介绍 Ingress Controller 是 …

[ESP32]:如何在micropython中添加C库

[ESP32]&#xff1a;如何在micropython中添加C库 本文将描述如何在micropython中添加一个基于c语言的led模块。 1.编写c驱动 选择一个目录&#xff1a;examples/usercmodule&#xff0c;建立对应的驱动文件hw_led&#xff1a; . ├── cexample │ ├── examplemodule…

RAG 在企业应用中落地的难点与创新分享

在2024稀土开发者大会-AI Agent与应用创新分会上&#xff0c;我有幸分享了我们团队在企业应用中实施RAG&#xff08;检索增强生成&#xff09;的难点与创新。希望通过这篇文章&#xff0c;与大家探讨我们在实践中遇到的问题和解决方案&#xff0c;为从事相关工作的朋友提供一些…

Spring2-入门

目录 入门案例 案例分析 Log4j2日志框架 Log4j2日志概述 引入依赖 加入日志配置文件 使用日志 入门案例 1.引入依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi&qu…