51单片机基础05 定时器
目录
一、为什么要定时器
二、定时器中断
1、定时器中断参数
2、定时器中断程序
3、定时器计数
一、为什么要定时器
前文提到,比如进行流水灯等操作,都是直接写了delay_ms这类操作。
但是在51单片机中,其一般就是靠双for进行的循环时延,单片机会浪费这部分时间而不能做其他的事;
其次如果程序很多的情况下,就得根据其他代码执行的时间来调整时延,这非常麻烦。
那有没有既可以定时、又不影响其他程序的进行呢?
比如,通过两个按键控制,按下按键后两个LED延时1s切换状态,如果通过以下代码进行,那么在延时的时候,按键按下另一个KEY就会完全没有反应。
if(KEY0==0)
{delay_ms(10);if(KEY0==0){delay_ms(1000);LED0=~LED0;}
}
if(KEY1==0)
{delay_ms(10);if(KEY1==0){delay_ms(1000);LED1=~LED1;}
}
二、定时器中断
1、定时器中断参数
中断编号 | 中断名 | 中断源 |
1 | 定时器0溢出中断 | TF0 |
3 | 定时器1溢出中断 | TF1 |
可以看到定时器0和定时器1的中断编号分别为1、3,因此T1的中断优先级没有T0高。
中断寄存器 | 功能 | 实现 |
ET0 | 定时器/计数器T0的溢出中断允许控制位 | 1:允许T0中断 0:禁止T0中断 |
ET1 | 定时器/计数器T1的溢出中断允许控制位 | 1:允许T1中断 0:禁止T1中断 |
该寄存器控制了是否允许中断。
中断触发控制位 | 功能 | 实现 |
TF0 | 定时/计数器T0溢出中断请求标志位 | 1:进入T0中断 0:未进入T0中断 |
TF1 | 定时/计数器T1溢出中断请求标志位 | 1:进入T1中断 0:未进入T1中断 |
该寄存器在计数溢出后自动置位为1并进入中断服务函数,需要用户手动清零。
定时器开关控制 | 功能 | 实现 |
TR0 | 打开或关闭定时器T0 | 1:打开 0:关闭 |
TR1 | 打开或关闭定时器T1 | 1:打开 0:关闭 |
配套初始化。
如下为TMOD的控制,其中D0~D3为定时器0配置,D4~D7为定时器1配置。
D3 | D2 | D1 | D0 |
GATE | C/T | M1 | M0 |
0:仅要求TR0=1开启定时器 1:同时要求T0引脚为高电平才可以开启定时器 | 0:定时 1:计数 | 00:13位计数器8192 01:16位计数器65536 10:8位计数器256,可自动重新装载 11:两组独立8位计时器256,不可同时用 |
TMOD寄存器,必须直接对整个地址操作,而不像TCON,其可以单位操作。
定时时间TH0、TL0控制,以定时器01模式为例
TH0=(65536-XX)/256
TL0=(65536-XX)%256
其中XX表示多少us,例如XX=50000,就是50ms,由此可以看出,单次定时时间最大为65536ms,最小为1us。
2、定时器中断程序
举例,还以上面按键控制LED闪烁为例
unsigned int count0=0;
unsigned int count1=0;
char flag0 = 0;
char flag1 = 0;
void main()
{EA=1; //开启总中断TMOD =0x01;TH0=(65536-50000)/256; //50msTL0=(65536-50000)%256;TR0=1; //打开定时器T0ET0=1; //允许中断while(1){if(key0==0){delay_ms(10)if(key0==0) flag0=1;}if(key1==0){delay_ms(10)if(key1==0) flag1=1;}}
}
void time0() interrupt 1
{TF0=0; //清除触发位,实现再次计数TH0=(65536-50000)/256; //50ms 装初值TL0=(65536-50000)%256;if(flag0==1)count0+=1;if(count0>=20){led0=~led0;count0=0;}if(flag1==1)count1+=1;if(count1>=20){led1=~led1;count1=0;}}
可以看到定时器50ms的中断,判断到按键按下后,在中断额外进行计数,达到20,说明达到了1秒,从而进行LED反转,不影响main内的有关代码执行。
3、定时器计数
前文提到,T0引脚是定时器的引脚,但是前面的定时代码怎么都和T0无关呢。
当51单片机的定时器工作在计数模式时,它会通过外部引脚(如T0或T1引脚)接收外部输入的脉冲信号。这时,I/O口就有直接关系了。外部设备产生的脉冲通过这些引脚输入到单片机,定时器/计数器累加这些脉冲来实现计数功能。举例来说,假如你需要用定时器0来测量输入信号的频率,你可以将信号输入到T0引脚,然后配置定时器0为计数模式,它会根据输入脉冲增加计数值。
计数模式C/T=1,16位M1M0=01,即TMOD=0101=0X05;
#include <reg51.h>// 定义定时器的控制位
sbit T0_PIN = P3^4; // T0口作为输入信号(定时器0外部输入)// 定义全局变量
unsigned int count = 0; // 计数器计数值
unsigned long frequency = 0; // 测得的频率值void Timer1_Init(void) {TMOD |= 0x10; // 设置定时器1为模式1(16位定时模式)TH1 = 0x3C; // 高字节初值(1秒定时器)TL1 = 0xB0; // 低字节初值ET1 = 1; // 使能定时器1中断EA = 1; // 总中断使能TR1 = 1; // 启动定时器1
}void Timer0_Init(void) {TMOD |= 0x05; // 设置定时器0为模式5(16位计数模式)TR0 = 1; // 启动计数器0
}void Timer1_ISR(void) interrupt 3 {TR1 = 0; // 关闭定时器1// 计算频率count = (TH0 << 8) | TL0; // 读取定时器0的计数值TH0 = 0; // 清零高字节TL0 = 0; // 清零低字节frequency = count;count = 0; // 计数值清零// 重装载定时器1初值TH1 = 0x3C;TL1 = 0xB0;TR1 = 1; // 重启定时器1
}void main(void) {Timer0_Init(); // 初始化定时器0(计数器模式)Timer1_Init(); // 初始化定时器1(定时器模式)while (1) {// 这里可以添加代码来显示频率值frequency,如通过串口输出}
}
注意:中断服务函数理应不要放太多的代码,尤其是延时是要完全避免的,否则会影响相关的精度。
相关文章:
51单片机基础05 定时器
目录 一、为什么要定时器 二、定时器中断 1、定时器中断参数 2、定时器中断程序 3、定时器计数 一、为什么要定时器 前文提到,比如进行流水灯等操作,都是直接写了delay_ms这类操作。 但是在51单片机中,其一般就是靠双for进行的循环时延&…...
tdengine学习笔记实战-jdbc连接tdengine数据库
先上代码,里面有两种获取连接的方式,一个单例,一个连接池 package com.tdengine.utils;import com.alibaba.druid.pool.DruidDataSource;import java.sql.*; import java.util.Properties;public class TDConnectUtils {// 单例对象private …...
vue3项目执行npm install下载依赖报错问题排查方法
1、检查当前node与npm的版本 nodejs 和 npm 的版本是有适配的,具体可以看官网:nodejs 和 npm 的版本是有适配的 若是版本不兼容,修改node或者npm的版本即可,建议使用nvm版本管理工具,切换方便; 2、清除缓…...
【vue】项目迭代部署后 自动清除浏览器缓存
前言: vue项目打包部署上线后,因浏览器缓存问题,导致用户访问的依旧是上个迭代批次的旧资源,需要用户手动清除缓存才能更新至最新版本,影响用户体验。 解决方法: html根文件添加以下标签 <meta http-eq…...
Leetcode(滑动窗口习题思路总结,持续更新。。。)
讲解题目:长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target ,找出该数组中满足其和 ≥ target 的长度最小的连续子数组。如果不存在符合条件的连续子数组,返回 0。示例: 输入: target 7, nums [2,3,1,2,4,3] 输出: 2 解…...
【UNIAPP】uniapp版图片压缩工具
二次封装的uniapp版本图片压缩、上传工具,支持全端(H5、小程序、APP) 新建文件:file-util.js class FileUtil {/*** [文件上传]* param {[object]} fileObj [图片地址]* param {[object]} formData [参数]* param {[str…...

PaddlePaddle 开源产业级文档印章识别PaddleX-Pipeline “seal_recognition”模型 开箱即用篇(一)
AI时代到来,各行各业都在追求细分领域垂直类深度学习模型,今天给大家介绍一个PaddlePaddle旗下,基于PaddleX Pipeline 来完成印章识别的模型“seal_recognition”。 官方地址:https://github.com/PaddlePaddle/PaddleX/blob/relea…...

Vue3 + Vite 项目引入 Typescript
文章目录 一、TypeScript简介二、TypeScript 开发环境搭建三、编译方式1. 自动编译单个文件2. 自动编译整个项目 四、配置文件1. compilerOptions基本选项严格模式相关选项(启用 strict 后自动包含这些)模块与导入相关选项 2. include 和 excludeinclude…...
微信小程序实战篇-分类页面制作
一、项目背景与目标 在微信小程序开发中,分类页面是一个常见且重要的功能模块。它能够帮助用户快速定位和浏览不同类别的商品或信息,提升用户体验和操作效率。今天,我们将深入探讨如何制作一个实用的微信小程序分类页面,先来看一下…...
第三十七章 如何清理docker 日志
如何清理docker 日志 目标 掌握docker 日志设置掌握docker日志的清理办法背景 在现代软件开发和部署环境中,Docker 容器技术因其轻量级、可移植性和高效资源利用的特点,已成为许多企业和开发团队的首选。Docker 容器在运行过程中会产生大量的日志信息,这些日志对于监控容器…...
二刷代码随想录第七天
454. 四数相加 II 先用map记录前两个数的和num1 num2的值出现了多少次再在后两个数组里找0 - (num1 num2),找到后就累加map中的次数 class Solution { public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3…...
1.tree of thought (使用LangChain解决4x4数独问题)
本教程将介绍如何使用LangChain库和chatglm API来解决一个4x4的数独问题。我们将通过以下步骤实现这一目标: 初始化chatglm 的聊天模型。定义数独问题和解决方案。创建一个自定义的检查器来验证每一步的思考。使用ToTChain来运行整个思考过程。 1. 初始化chatglm4…...

网络基础(4)IP协议
经过之前的学习对传输协议的学习,对于传输协议从系统底层到应用层对于socket套接字的学习已经有了一套完整的理论。 对于网络的层状结构,现在已经学习到了应用层和传输层: 在之前的学习中,通信的双方都只考虑了双方的传输层的东西࿰…...

124. 二叉树中的最大路径和【 力扣(LeetCode) 】
文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 124. 二叉树中的最大路径和 一、题目描述 二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径…...
echarts:简单实现默认显示两柱子折线,点击按钮后显示新的柱子
问: 用echarts实现:默认显示两柱子折线,点击“税率”按钮,显示税率柱子,之前的两柱子折线消失 回答: <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8…...

视频里的音频怎么提取出来成单独文件?音频提取照着这些方法做
在数字时代,视频与音频的分离与重组已成为日常需求之一。无论是出于制作背景音乐、保存讲座内容,还是编辑播客素材,提取视频中的音频并将其保存为单独文件都显得尤为重要。视频里的音频怎么提取出来成单独文件?本文将详细介绍几种…...

Excel——宏教程(精简版)
一、宏的简介 1、什么是宏? Excel宏是一种自动化工具,它允许用户录制一系列操作并将其转换为VBA(Visual Basic for Applications)代码。这样,用户可以在需要时执行这些操作,以自动化Excel任务。 2、宏的优点 我们可以利用宏来…...
C++中的std::tuple和std::pair
在C标准库中,std::tuple和std::pair是两种极具实用性的数据结构,它们都具备存储多个元素的功能,但各自有其独特的适用环境和特性。本文旨在深入探讨这两者之间的区别,并阐述在不同应用场景下应如何合理选择使用。 一、基本概念 s…...

引力搜索算法
引力搜索算法过程,包括了初始化、适应度评估、质量计算、加速度计算、更新速度和位置的一些步骤。 import numpy as np import random as rd from math import exp, sqrt import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D from matplotli…...

【时间之外】IT人求职和创业应知【35】-RTE三进宫
目录 新闻一:京东工业发布11.11战报,多项倍增数据体现工业经济信心提升 新闻二:阿里云100万核算力支撑天猫双11,弹性计算规模刷新纪录 新闻三:声网CEO赵斌:RTE将成为生成式AI时代AI Infra的关键部分 认知…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
爬虫基础学习day2
# 爬虫设计领域 工商:企查查、天眼查短视频:抖音、快手、西瓜 ---> 飞瓜电商:京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空:抓取所有航空公司价格 ---> 去哪儿自媒体:采集自媒体数据进…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...