51单片机--定时器与按键控制流水灯模式

news2024/11/16 19:44:28

文章目录

  • 定时器
    • 定时器的介绍
    • 定时器的作用
    • 定时器框图
    • 定时器的工作模式
    • 计数器原理图:
  • 中断系统
    • 中断程序流程
    • STC89C52的中断资源
    • 定时器和中断系统
  • 定时器的相关寄存器
    • TCON
    • TMOD
    • TH与TL
    • 有关中断的寄存器
  • 按键控制流水灯模式

定时器

定时器的介绍

51单片机上的定时器是一种硬件模块,用于计时和生成特定的时间延迟。它的电路和运转都在单片机内完成,它是嵌入在单片机内部的一个功能模块,具有多种工作模式和功能。
定时器在该芯片里头

在51单片机中,通常有两个定时器/计数器:定时器0(Timer 0)和定时器1(Timer 1)。每个定时器都有一个相应的控制寄存器,用于设置相关参数和配置工作模式。在我们这款STC89C52上还多一个T2的定时器;

定时器的作用

1.用于计时系统,可以实现软件计时,或者使程序每隔一定的时间就完成一项任务;
2.替代长时间的Delay,提高CPU运行效率和处理速度;

我们在前面学习了用Delay函数进行延迟,但对于Delay函数来说,我们在完成一件任务时,当它开始延迟时,我们需要停下我们CPU的手上所有的运行,等他延迟之后我们才可以继续操作,因为对于所有子函数来说,我们都需要在主函数(main)中完成,当发生Delay时,就没有办法完成其他操作,所以Delay无法实现多任务线程的工作,例如下面的一边流水灯,一边用按键控制;而对于定时器来说,恰好解决了这一难题。

定时器框图

定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号(脉冲),每隔一段时间,那么计数单元的数值就会加一,当计数单元达到最大值后,那么计数单元就会向中断系统发出申请,让他开始执行中断服务函数。
在这里插入图片描述

定时器的工作模式

对于定时器来说,是有多种模式可以选择的,不只是会让计数单元一直加一加一,也可以是加十加十,这就相当于我们选择了另外一种模式;
对于STC89C52的T0和T1来说,都有四种工作模式:

模式0:13位定时器/计数器
模式1:16位定时器/计数器(常用)
模式2:8位自动重装模式
模式3:两个8位计数器

在这里,对于我们来说,模式1是我们这篇文章要讲的,其他的像模式0和模式3,一般情况我们是用不到的,而模式2:8位自动重装模式,主要用于串口通信产生波特率进行调节;

在这里插入图片描述
在这里,我们按照上面的框图分为时钟系统,计数系统,中断:
在这里插入图片描述

计数器原理图:

时钟系统:
在这里插入图片描述

SYSclk:system clock系统时钟,它具有晶振周期,在本开发板上晶振为11.0592MHz,是一个非常大的数字,换算成时间的话就约为9ns左右(T=1/f),可以产生脉冲,将脉冲传入计数系统,然后系统时钟可以有两种模式选择分频,也就是将频率降低;在这里,我们选择的是12T;T0 Pin是外接口引脚,可以由外接口连上一个计时器,每个一个周期脉冲就会加1,那么计时器也就可以变为计数器,通过计算脉冲来达到计数效果;也就是将C/T=0;

计数系统:
在这里插入图片描述

TR0,是计时器T0的运行控制位,相当于一个启动器(按钮),只有TR0启动之后,那么技术系统才会开始计数;TL0和TH0分别表示低位和高位,用来计算脉冲传过来的次数,每一次的脉冲过来就加一,这两个加起来总共有16bit位,那么就表示计数系统可以计算0~65535(2^16-1)次,当计数达到最大值时,就会向中断系统发出中断请求

中断:
在这里插入图片描述

TF0也就是中断溢出的标志位,简单的来说就是消息提醒,向CPU告知需要中断了,中断就需要进入中断系统;

中断系统

介绍:

单片机的中断系统是指单片机处理外部事件或者内部事件时的一种机制。在单片机执行程序的过程中,可能会遇到一些特殊情况,比如定时时间到、有外部设备的输入信号等。这时,CPU需要临时停止当前的程序,转去执行相应的中断处理程序,待处理完该事件后再返回原先的程序继续执行。这个定义很好理解,就像睡觉一半被闹钟叫醒去读书一样,闹钟在你睡觉途中打断你的睡觉,让你该去读书了,这个过程就是中断;

组成部分:

中断源:指引起中断的事件或信号源,可以是外部设备产生的输入信号,也可以是定时器的时间到达等。
中断控制器:负责对各个中断源的优先级进行管理和调度,确定哪个中断请求能够被CPU响应。
中断向量表:用于存储每个中断类型对应的中断处理程序的入口地址。
中断处理程序:是指处理具体中断事件的程序代码,根据中断类型执行相应的操作,处理完后返回到原先的程序继续执行.

作用:

实时性:中断系统可以及时响应外部事件,提高系统的实时性能。
节约CPU资源:通过使用中断系统,CPU不再需要不断地轮询外部设备状 态,而是在需要处理事件时才会被中断,节约了CPU的资源。
提高系统效率:使用中断系统可以使单片机在处理外部事件时不需要等待,减少了等待时间,提高了系统的效率。
灵活性:通过中断系统,可以方便地处理不同类型的事件,增加了系统的灵活性和扩展性。

中断程序流程

在这里插入图片描述

在我们的认知里,一般都会在主函数中执行程序,但如果有中断函数存在的话,当主程序发出中断请求时,程序就会停止主程序,优先处理中断函数中的程序,处理完再返回主程序,这就是中断程序的流程,在下面的代码中将会有进一步加深印象;

STC89C52的中断资源

在STC89C52中有8个中断资源:外部中断、定时器0中断、外部中断1、定时器1中断、串口中断、外部中断2、外部中断3;
中断的优先级个数有4个;
在这里插入图片描述
在这里i,函数后面的nterrupt+序列号就是表示不同的中断资源,当中断请求向CPU发出后中断系统响应后,那么就会执行这个中断程序;

定时器和中断系统

在这里插入图片描述

这里的中断系统实际上是简化的了,但对于原理来说,其实是一致的,为了方便对初学者的了解,才使用该原理图;

这个就是定时器连接着中断系统了。当我们计数系统满的时候,就会向TF0标志位告知,让它发出中断请求,接着就是ETO得闭合,允许T0中断,然后就是PT0选择0,选择好定时器的优先级;
在这里插入图片描述

定时器的相关寄存器

在前面几篇文章,我们使用的寄存器相对来说是比较少的,对于定时器来说,它有以下的相关寄存器:
在这里插入图片描述
在这里插入图片描述
我们可以看到对于计时器和中断系统的寄存器来说,还是相当多的,对于中断寄存器的,我们只挑出相关定时器的寄存器来讲;

TCON

在这里插入图片描述

寄存器都会有相应的地址,程序会通过指针指向的地址来找到对应的寄存器位置,寄存器一般有8个bit位,这里的可位寻址,表示根据它的bit位来寻找对应的地址;

首先T1和T0对应的bit位功能基本相同,所以这里只对T0展开论述;

TF0:定时器T0溢出中断标志(Timer Flag)。 T0开始计数后,但计数达到最大值后,开始产生溢出,TF0会由硬件置“1”,向CPU发出请求中断,CPU响应后,TF0才由硬件置“0”。
TR0:定时器T0控制位(Timer Run); 当GATE(一个开关)=0,TR0=1 T0开始计数,TR0=0禁止T0计数;
IE0:外部中断0请求源标志(Interrupt Enable);IE0=1外部中断0向CPU请求中断,CPU响应后,外部中断0由硬件清‘0’IE0;
IT0:外部中断0触发方式控制位(Interrupt Trigger);IT0=0时,外部中断0为低电平触发方式,输入低电平时,置位IE0。当IT1=0时,则外部中断0端口由“1”->"0"下降沿跳变,激活中断请求标志位IE0,向主机请求中断处理。

TMOD

在这里插入图片描述

这里不可位寻址就是不能利用TMOD的bit位来寻找对应的地址,必须使用TMOD寄存器,直接对它赋值

GATE与C/T这里不涉及就不再讲,M1和M0时选择定时器的模式:
在这里插入图片描述

这里由于是不可位寻址,我们用到了一种巧妙的方式——按位运算,对于我们要实现定时器0模式1 那么我们可以先对TMOD按位与0xF0,使TMOD定时器0都保持为0,接着用按位或的按位运算,将它或上0x01,这种做的目的是不用管TMOD的初始状态是什么,与上1就是1;

TH与TL

TH与TL后面跟0就表示定时器0的计数,后面跟1就表示定时器1的计数。

有关中断的寄存器

在这里,我们跟着原理图的走向,列出相关的寄存器;

==EA:CPU的中断允许控制位(Interrupt All);==这是一个总的中断控制,当EA=0,CPU将会屏蔽所有的中断申请;EA=1才允许申请。
ET0:T0的溢出中断允许位;ET0=1,允许T0中断;
PT0: 一个特殊位申请,当PT0=0,为中断优先级;PT0=1时为高级优先权。

按键控制流水灯模式

这里我们需要对定时器进行初始化
Timer0.h

#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0Init();

#endif

Timer0.c:

#include <REGX52.H>
void Timer0Init()		//1毫秒@11.0592MHz
{
	TMOD &= 0xF0;
	TMOD |= 0x01; //设置定时器模式
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=1;     //允许T0中断
	EA=1;       //CPU开放中断
	PT0=0;      //定时器0中断优先级
}

这里初始化的是可以走1ms的定时器,首先需要对定时器0模式选择为1,然后设置定时的初值,根据每一个计数到下一个计数的时间差,从65535向前推算需要多少个计数,进行对应的高低位初始化;那么1ms后就会向TF0发出中断请求;TF0初始化为0;TR0选择1,让计时器计时,ET0选择1允许T0中断,EA为总中断控制位,选择1为打开,PT0选择0为低级中断优先级

接着我们写一个按键选择函数:
Delay.h:

#ifndef __DELAY_H__
#define __DELAY_H__

void Delayms(unsigned int x);

#endif

Delay.c

oid Delayms(unsigned int x)		//@11.0592MHz
{
	unsigned char i, j;

	while(x--)
	{
	
		i = 2;
		j = 199;
		do
		{
			while (--j);
		} while (--i);
	}
}

Key.h

#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key();

#endif

Key.c

include "Delay.h"
#include <REGX52.H>

/**
  * @brief 获取独立按键键码
  * @param 无
	* @reval 按下按键的键码,范围0~4,无按键按下时返回值为0
  */
unsigned char Key()
{
		unsigned char KeyNumber=0;
		if(P3_1==0){Delayms(20);while(P3_1==0);Delayms(20);KeyNumber=1;}
		if(P3_0==0){Delayms(20);while(P3_0==0);Delayms(20);KeyNumber=2;}
		if(P3_2==0){Delayms(20);while(P3_2==0);Delayms(20);KeyNumber=3;}
		if(P3_3==0){Delayms(20);while(P3_3==0);Delayms(20);KeyNumber=4;}
		
		return KeyNumber;
}

最后写上主函数:

#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>
unsigned char KeyNum,LEDMode;
void main()
{
	P2=0xFE;
	Timer0Init();
	while(1)
	{
		KeyNum=Key();
		if(KeyNum==1)
		{
					LEDMode++;
					LEDMode%=2;
		}
	}
}
	

void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x66;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if(T0Count>=500)
	{
		T0Count=0;
		if(LEDMode==0)
				P2=_crol_(P2,1);
		if(LEDMode==1)
				P2=_cror_(P2,1);
	}
}

在主函数里,先对P2和定时器进行初始化,然后在循环里面走独立按键的程序,每当按一次按键1,LEDCode就会在0和1依次循环选择;
然后是中断函数,1表示是计时器的中断程序,每当计时器计数溢出时,那么我们就开始中断主程序,对中断函数开始执行,先重新对计时器初始化,便于下一次计时,这里ToCount表示多少毫秒走一次LED灯,当LEDMode为0时,向左跑流水灯,LEDMode为1时向右跑流水灯;这里的 crol()是一个LED流水灯函数,第二个参数表示每一次跨越的灯数,1也就是表示跨越一个灯数,就会形成我们的流水灯。

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

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

相关文章

率先布局 RWA 赛道,PoseiSwap 成为最具先进性的 DEX

RWA 全称为现实资产通证化&#xff0c;比如股票、期货、美债甚至房产等传统资产。RWA 正在成为加密行业发展的一个全新叙事方向&#xff0c;除了传统商业巨头比如高盛、西门子等开始向该领域深入布局外&#xff0c;以 MakerDAO、Binance、Aave、Maple Finance 等为代表的 Web3 …

MySQL_2

目录 一、函数 1、字符串函数 2、数值函数 3、日期函数 4、流程控制函数 二、约束 1、概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 2、目的&#xff1a;保证数据库中数据的正确、有效性和完整性。 3、分类 4、外键约束 4…

命名管道使用示例

用命名管道实现client和server端进行通信 【实现步骤】 创建两个没有关系的进程--》编写client和server源文件&#xff0c;并分别编译成可执行程序&#xff1b;创建命名管道文件&#xff0c;用函数int mkfifo(const char *filename,mode_t mode);client端以写的方式打开管道文…

日志消息直接发送到kafka设计

背景&#xff1a; 日常工作中&#xff0c;我们一般都有需要分析业务日志的需求&#xff0c;有些业务日志记录了用户点击或者用户购买行为等有用的信息&#xff0c;所以我们一般都需要基于这些日志进行分析&#xff0c;本文我们就来看一下这种日志消息的流转图 技术方案&#…

阿里云ECS扩容硬盘空间及文件系统

一.通过阿里云控制台扩容硬盘 前往ECS实例详情页面的云盘页签。 登录ECS管理控制台。在左侧导航栏&#xff0c;选择实例与镜像 > 实例。在顶部菜单栏处&#xff0c;选择目标ECS实例所在地域。找到待扩容云盘所在的实例&#xff0c;单击实例ID。在实例详情页面&#xff0c;单…

一起来探索录音转文字哪个软件好用

在数字时代&#xff0c;录音转文字技术成为了一种不可或缺的工具&#xff0c;通过将语音内容转化为可编辑和搜索的文字&#xff0c;从而为我们带来了许多便利。那本文将探讨录音转文字的好处&#xff0c;并分享一些实际案例以及录音转文字软件。那么如果你还不知道录音转文字哪…

想做软件测试工程师,这7件事你必须先知道

目录 一、“开发者测试” 就是“开发者来测试” 二、没有什么测试不可以“自动化测试” 三、开发者测试”利在当下“&#xff0c;”赢得未来“ 四、TDD不是必须先写测试代码 五、UT覆盖率100%真的很不好 六、用测试来驱动架构和代码质量 七、从“我要写测试依赖代码”到“…

在iPad上轻松做笔记和绘画,西圣Pencil上手

触控笔是一种提高工作学习效率的方便工具&#xff0c;尤其是和平板搭配使用。但是iPad的Apple Pencil价格昂贵&#xff0c;不适合学生等经济条件有限的用户&#xff0c;所以他们需要寻找一些性价比高的国产替代品。我最近用了一支国产的电容触控笔&#xff0c;叫做西圣Pencil触…

[C++] C++11新特性分析介绍(1): 列表初始化、右值引用、完美转发、移动语义...

文章目录 [toc] C11介绍统一的列表初始化 {}initializer_list新的声明autodecltypenullptr 范围for智能指针STL 新容器**右值引用 ****容器中 另外的右值引用 **万能引用与完美转发 ****新的类功能新默认成员函数强制生成默认函数的关键字 default禁止生成默认函数的关键字 del…

【网络安全】带你了解什么是【黑客】

文章目录 背景定义分类白帽黑客&#xff08;White Hat Hacker&#xff09;黑帽黑客&#xff08;Black Hat Hacker&#xff09;灰帽黑客&#xff08;Gray Hat Hacker&#xff09; 黑客文化伦理问题黑客常用的攻击手段黑客攻击用户的常用策略有以下这些&#xff1a;防御黑客攻击的…

[Android 13]Binder系列--获取服务

获取服务 hongxi.zhu 2023-7-8 一、客户端发起获取服务 以SurfaceFlinger进程中获取InputFlinger服务为例 frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp sp<IBinder> input(defaultServiceManager()->getService(String16("inputflinger"…

Redis+IDEA极速了解和实现单机锁和分布式锁

单机下&#xff1a; 只适用于单机环境下&#xff08;单个JVM&#xff09;&#xff0c;多个客户端访问同一个服务器 1.synchronized package com.cloud.SR.controller;import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.cor…

跟我一起从零开始学python(六)数据库编程:MongoDB数据库

前言 回顾之前讲了python语法编程 &#xff0c;必修入门基础和网络编程&#xff0c;多线程/多进程/协程等方面的内容&#xff0c;昨天和今天讲到了数据库编程篇MySQL&#xff0c;Redis今天第三篇MongoDB篇&#xff0c;前面没看的也不用往前翻&#xff0c;系列文已经整理好了&a…

多线程与并发编程【线程对象锁、死锁及解决方案、线程并发协作、生产者与消费者模式】(四)-全面详解(学习总结---从入门到深化)

目录 使用Class作为线程对象锁 使用自定义对象作为线程对象锁 死锁及解决方案 线程并发协作(生产者/消费者模式) 实现生产者与消费者模式 使用Class作为线程对象锁 语法结构&#xff1a; synchronized(XX.class){//同步代码} 或 synchronized public static void access…

【大语言模型】LLM应用程序的新兴体系结构

LLM应用程序的新兴体系结构 LLM应用栈设计模式&#xff1a;In-context learningData Preprocessing/EmbeddingPrompt Construction/RetrievalPrompt Execution/Inference What about agents?展望参考资料 大型语言模型是构建软件的强大新基元。但由于它们非常新颖且与常规计算…

css写法、颜色显示方式

一、什么是css 二、css的几种写法 1、行内样式 css写在标签的style属性上&#xff0c;优先级非常高&#xff0c;但是有多个标签具有相同样式代码重复高 2、页面样式 此时写在head&#xff08;不可见&#xff09;中&#xff0c;用style标签 3、外联样式 css样式也可以导入 一…

C++primer(第五版)第十六章(模板与泛型编程)

16.1定义模板 关于模板,第一个要提的点就是,这个字念mu模板而不是mo(一开始打字就发现拼音错了,突然觉得自己要会小学深造一下). 模板就是将一个特定场合使用的东西变成可以在多个场合使用的东西. 16.1.1函数模板 template<typename T> bool bijiao(T &a,T &…

了解 IPNS:我们可以使用 4EVERLAND IPNS Manager 做什么?

关键词&#xff1a;4EVERLAND、IPNS、4EVERLAND IPNS 管理器、去中心化内容 IPNS 是星际名称系统的缩写&#xff0c;是一个允许我们在 IPFS&#xff08;星际文件系统&#xff09;内创建可变指针以及名称和地址内容的系统。IPFS 使用内容标识符 (CID) 作为唯一文件标识符&#…

Photoshop制作Alphas(没有显卡好痛苦,两个MAYA交替弄)

做个选区&#xff0c;选白色 擦除背景 在把背景填充上白色

【PyGIS】GDAL及Rasterio多线程转换NC格式文件为TIFF

汇总 【GIS】使用cdsapi下载ERA5和ERA5_land逐小时数据 NC格式介绍 说明 NC文件读取使用netCDF4,NC文件转换为TIF使用rasterio或者GDAL。 一些细节: 格点数据转换为TIFF文件时候,计算六参数时候,应该要考虑,格点数据存储的坐标属于栅格中心点的位置,转换为TIFF时候,…