C51 单片机学习(二):定时器与中断系统

参考

  • 51单片机入门教程

1. 定时器

1.1 定时器定义

  • 51 单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成
    • C51 单片机学习(一):基础外设 讲的都是单片机的 IO 口控制的外设

1.2 定时器作用

  • 用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作
  • 替代长时间的 Delay,提高 CPU 的运行效率和处理速度
    • Delay() 时 CPU 干不了其它事,就会白白占用 CPU 的时间

1.3 STC89C52 定时器资源

  • 定时器个数:3个(T0、T1、T2),T0 和 T1 与传统的 51 单片机兼容,T2 是此型号单片机增加的资源

    注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0 和 T1 的操作方式是所有 51 单片机所共有的(T:Timer,计数器

1.4 定时器框图

  • 定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔 “一秒”,计数单元的数值就增加一,当计数单元数值增加到 “设定的闹钟提醒时间” 时,计数单元就会向中断系统发出中断申请,产生 “响铃提醒”,使程序跳转到中断服务函数中执行
    • 中断系统也是 51 单片机的内部资源,中断系统是为了使 CPU 具有外界紧急事件的实时处理能力而设置
      在这里插入图片描述

1.5 定时器工作模式

  • STC89C52 的 T0 和 T1 均有四种工作模式
    • 模式 0:13 位定时器/计数器
    • 模式 1:16 位定时器/计数器(常用)
    • 模式 2:8 位自动重装模式
    • 模式 3:两个 8 位计数器
      在这里插入图片描述

1.6 定时器时钟

  • SYSclk 系统时钟(下图左上部分):即晶振周期,本开发板上的晶振为 12MHz
    • MCU in 12T mode 进行 1MHZ 的一个分频,每隔 1us 进行一次计数,当它为最大值时就会产生一次中断
    • T0 pin:单片机外部的一个接口,时钟可以由系统时钟提供也可以由外部引脚提供
    • 中间是一个选择开关,C = Count(计数) ,T = Timer(计时器) ,C = 1、T = 0,如果这一位给 1 就链接到 T0 pin ,给 0 就是连接到 SYSclk
  • 计数/定时系统(下图左下部分):TL0(低字节)和 TH0(高字节),0 代表定时器 0,这是一个十六位的计数器,这两个字节计数范围 0~65535
    • 计数系统的左边的时钟给了它提供了一个脉冲(方波),每来一个脉冲它的定时器的值就会加 1,一直这样循环往复的话,当加到 65535 时,那么再下一个脉冲的时候它就会产生一个溢出,溢出时这个计数器就会到 0 的位置
    • 溢出标志位:TF0,负责向中断系统申请中断请求
    • TR0 控制定时器的启动是否暂停,当 TR0 = 1 时开始计数
      在这里插入图片描述

2. 中断系统

2.1 概述

在这里插入图片描述

2.2 中断程序流程

在这里插入图片描述

2.3 STC89C52 中断资源

  • 中断源个数:8 个(外部中断 0、定时器 0 中断、外部中断 1、定时器 1 中断、串口中断、定时器 2 中断、外部中断 2、外部中断 3)
    • 中断优先级个数:4 个
    • 中断号
      在这里插入图片描述

注意:中断的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的中断资源,例如中断源个数不同、中断优先级个数不同等等

3. 定时器和中断系统

3.1 连接框图

  • 中断源:INT0(外部中断 0)、INT1(外部中断 1)、T0(定时器 0)、T1(定时器 1)、RXD 和 TXD(同属串口中断)
    在这里插入图片描述

3.2 相关寄存器

  • 寄存器是连接软硬件的媒介,在单片机中寄存器就是一段特殊的 RAM 存储器

    • 一方面,寄存器可以存储和读取数据
    • 另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式
    • 单片机中两种寄存器:ROM 和 RAM
      在这里插入图片描述
  • 可位寻址/不可位寻址

    • 可位寻址可以单独的对一位寄存器进行赋值:如 P2 = 1; P2_1 = 1; 都可
    • 不可位寻址就是它的寄存器只能进行整体的进行赋值

3.3 寄存器配置

  • TMOD 配置

    • 1.5 小节提到模式 1 最常用,则 M1 = 0,M0 = 1
    • 选用 SYSclk 系统时钟,则 C/T(取反) = 0
    • GATE(门控端),GATE = 0
  • TCON 配置

    • TF0 中断溢出标志位,程序中可直接先给 TF0 = 0,因为一旦 TF0 = 1 就会产生中断
    • TR0 = 1 表示开始计数
    • IE0 和 IT0 用来控制外部中断引脚,但 GATE 门控端 = 0,所以不用配置这两个
    • TH0 = 64536/256; // 取出高 8 位
    • TL0 = 64536%256; // 取出低 8 位

3.4 中断配置

  • 参照 3.1 小节连接框图配置如下参数
    • ET0 = 1
    • EA = 1
    • PT0 = 0

3.3 代码示例

1、按键控制 LED 流水灯模式
  • Delay.h
#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif
  • Delay.c
void Delay(unsigned int xms) {
    unsigned char i, j;
    while (xms--) {
        i = 2;
        j = 239;
        do {
            while (--j);
        } while (--i);
    }
}
  • Key.h
#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key();

#endif
  • Key.c
#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  获取独立按键键码
  * @param  无
  * @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
  */
unsigned char Key() {
    unsigned char KeyNumber=0;
    
    if (P3_1 == 0) {Delay(20); while (P3_1 == 0); Delay(20); KeyNumber = 1;}
    if (P3_0 == 0) {Delay(20); while (P3_0 == 0); Delay(20); KeyNumber = 2;}
    if (P3_2 == 0) {Delay(20); while (P3_2 == 0); Delay(20); KeyNumber = 3;}
    if (P3_3 == 0) {Delay(20); while (P3_3 == 0); Delay(20); KeyNumber = 4;}
    
    return KeyNumber;
}
  • Timer0.h
#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0Init(void);

#endif
  • Timer0.c
#include <REGX52.H>

/**
  * @brief  定时器 0 初始化,1 毫秒 @12.000MHz
  * @param  无
  * @retval 无
  */
void Timer0Init(void) {
    TMOD &= 0xF0;      // 把 TMOD 低 4 位清零,高四位保持不变
    TMOD |= 0x01;      // 把 TMOD 最低位置零,高四位保持不变
    TL0 = 0x18;        // 设置定时初值,低 8 位
    TH0 = 0xFC;        // 设置定时初值,高 8 位
    TF0 = 0;           // 清除 TF0 标志
    TR0 = 1;           // 定时器 0 开始计时
    ET0 = 1;
    EA = 1;
    PT0 = 0;
}

/*定时器中断函数模板
void Timer0_Routine() interrupt 1 {
    static unsigned int T0Count;
    TL0 = 0x18;  // 设置定时初值
    TH0 = 0xFC;  // 设置定时初值
    T0Count++;
    if (T0Count >= 1000) {
        T0Count = 0;	
    }
}
*/
  • main.c
#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) {            // 如果按键按下
            if (KeyNum == 1) {   // 如果 K1 按键按下
                LEDMode++;       // 模式切换
                if (LEDMode >= 2)
                    LEDMode = 0;
            }
        }
    }
}

void Timer0_Routine() interrupt 1 {
    static unsigned int T0Count;
    TL0 = 0x18;    // 设置定时初值
    TH0 = 0xFC;    // 设置定时初值
    T0Count++;     // T0Count 计次,对中断频率进行分频
    if (T0Count >= 500) {    // 分频 500 次,500ms
        T0Count = 0;
        if (LEDMode == 0)      // 模式判断
            P2 = _crol_(P2, 1);   // LED 输出
        if (LEDMode == 1)
            P2 = _cror_(P2, 1);
    }
}
2、 定时器时钟
  • main.c
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"

unsigned char Sec=55,Min=59,Hour=23;

void main() {
    LCD_Init();
    Timer0Init();
    
    LCD_ShowString(1, 1, "Clock:");  // 上电显示静态字符串
    LCD_ShowString(2, 1, "  :  :");
    
    while (1) {
        LCD_ShowNum(2, 1, Hour, 2);	//显示时分秒
        LCD_ShowNum(2, 4, Min, 2);
        LCD_ShowNum(2, 7, Sec, 2);
    }
}

void Timer0_Routine() interrupt 1 {
    static unsigned int T0Count;
    TL0 = 0x18;    // 设置定时初值
    TH0 = 0xFC;    // 设置定时初值
    T0Count++;
    if (T0Count >= 1000) {  // 定时器分频,1s
        T0Count = 0;
        Sec++;          // 1 秒到,Sec 自增
        if (Sec >= 60) {
            Sec = 0;      // 60 秒到,Sec 清 0,Min 自增
            Min++;
            if (Min >= 60) {
                Min = 0;    // 60 分钟到,Min 清 0,Hour 自增
                Hour++;
                if (Hour >= 24) {
                    Hour = 0;  // 24 小时到,Hour 清 0
                }
            }
        }
    }
}

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

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

相关文章

Java算法---递归算法基础介绍

目录 一、递归算法 二、递归算法的典型例子 &#xff08;1&#xff09;阶乘 &#xff08;2&#xff09;二分查找 &#xff08;3&#xff09;冒泡排序 &#xff08;4&#xff09;插入排序 一、递归算法 计算机科学中&#xff0c;递归是一种解决计算问题的方法。其中解决方案…

yum指令——Linux的软件包管理器

. 个人主页&#xff1a;晓风飞 专栏&#xff1a;数据结构|Linux|C语言 路漫漫其修远兮&#xff0c;吾将上下而求索 文章目录 什么是软件包yum指令1.yum 是什么&#xff1f;2.Linux系统&#xff08;Centos&#xff09;的生态 3.yum的相关操作安装卸载yum的相关操作小结 软件源安…

Python判断语句——布尔类型和比较运算符

一、引言 在Python编程语言中&#xff0c;布尔类型和比较运算符是基础而又至关重要的概念。它们是构建逻辑和决策的核心要素&#xff0c;让程序能够理解“真”与“假”、以及各种数量和值之间的关系。理解并掌握这些概念&#xff0c;对于编写高效、准确的代码至关重要。在本文…

OpenHarmony—仅允许在表达式中使用typeof运算符

规则&#xff1a;arkts-no-type-query 级别&#xff1a;错误 ArkTS仅支持在表达式中使用typeof运算符&#xff0c;不允许使用typeof作为类型。 TypeScript let n1 42; let s1 foo; console.log(typeof n1); // number console.log(typeof s1); // string let n2: typeof …

【极数系列】Flink集成DataSource读取集合数据(07)

文章目录 01 引言02 简介概述03 基于集合读取数据3.1 集合创建数据流3.2 迭代器创建数据流3.3 给定对象创建数据流3.4 迭代并行器创建数据流3.5 基于时间间隔创建数据流3.6 自定义数据流 04 源码实战demo4.1 pom.xml依赖4.2 创建集合数据流作业4.3 运行结果日志 01 引言 源码地…

基于Python 爬虫的房地产数据可视化分析与实现

摘要&#xff1a; 过去&#xff0c;不管是翻阅书籍&#xff0c;还是通过手机&#xff0c;电脑等从互联网上手动点击搜索信息&#xff0c;视野受限&#xff0c;信息面太过于狭窄&#xff0c;且数据量大而杂乱&#xff0c;爆炸式信息的更新速度是快速且不定时的。要想手动获取到海…

OpenAI、斯坦福大学提出Meta-Prompting,有效提升语言模型的性能

为了研究如何提高语言模型的性能&#xff0c;使其更充分有效地输出对于提问的回答&#xff0c;来自斯坦福和 OpenAI 的学者强强联手&#xff0c;通过提出一种名为元提示&#xff08;meta-prompting&#xff09;的方法来深入探索。元提示通过让单个语言模型&#xff08;如 GPT-4…

【JavaScript基础入门】04 JavaScript基础语法(二)

JavaScript基础语法&#xff08;二&#xff09; 目录 JavaScript基础语法&#xff08;二&#xff09;变量变量是什么声明变量变量类型动态类型注释 数字与运算符数字类型算术运算符操作运算符比较运算符逻辑运算符运算符的优先级 变量 变量是什么 在计算机中&#xff0c;数据…

练习12.6_横向射击_Python编程:从入门到实践(第3版)

编写一个游戏&#xff0c;将一艘飞船放在屏幕左侧&#xff0c;并允许玩家上下移动飞船。在玩家按空格键时&#xff0c; 让飞船发射一颗在屏幕中向右飞行的子弹&#xff0c;并在子弹从屏幕中消失后将其删除。 ship_shooting.py import pygame import sys from leftship impor…

RabbitMQ基础编程模型及详细使用

目录 RabbitMQ基础编程模型 引入依赖 创建连接&#xff0c;获取Channel 声明Exchange-可选 声明queue 声明Exchange与Queue的绑定关系-可选 Producer根据应用场景发送消息到queue Consumer消费消息 Consumer主要有两种消费方式 1、被动消费模式 2、主动消费模式 完成…

sqli-labs闯关

目录 1.安装靶场2.了解几个sql常用知识2.1联合查询union用法2.2MySQL中的通配符&#xff1a;2.3常用函数2.4数据分组 3.mysql中重要的数据库和表4.开始闯关4.1 Less-14.1.1 首先进行一次常规的注入4.1.2 深入解析 1.安装靶场 1.首先推荐使用github下载靶场源码 https://githu…

内网安全:PTH PTK PTT

目录 实验所用网络拓朴图 网络环境说明​​​​​​​ LM认证 NTLM认证 NTLM Hash Kerberos认证 TGT票据 服务票据 Windows系统密码存储 域控制器 - 用户登录 域用户 本地用户 域用户和本地管理员 用户登录 Mimikatz抓取密码来源 域内一台主机上可以得到非本地用…

js实现贪吃蛇

文章目录 实现方法_11实现效果2 实现步骤2.1 移动场地2.2 游戏难度2.3 造蛇和食物2.4 蛇的移动2.5 产生食物的随机位置 3 全部代码 实现方法_21 实现效果2实现想法2.1 蛇的存储 实现方法_1 1实现效果 2 实现步骤 html部分忽略&#xff0c;布局写的太辣眼了 2.1 移动场地 用的表…

遥感的CCDC连续变化监测的qgis插件

简介 今天我逛GitHub的时候&#xff0c;看到一个比较有意思的插件:CCD-Plugin&#xff0c;记录一下。 CCD-Plugin是一个qgis插件&#xff0c;它使用 Google Earth Engine 获取 Landsat 或 Sentinel2 数据集&#xff0c;并运行连续变化检测 (CCDC) 算法来分析给定点的多年时间序…

【C++】一题掌握空指针

今天看见一道面试题&#xff0c;比较有意思&#xff0c;这一分享出来&#xff1a; 1.下面程序能编译通过吗&#xff1f; 2.下面程序会崩溃吗&#xff1f;在哪里崩溃 class A {public:void PrintA(){cout<<_a<<endl;}void Show(){cout<<"Show()"&…

(自用)learnOpenGL学习总结-高级OpenGL-模板测试

模板测试 模板测试简单来说就是一个mask&#xff0c;根据你的mask来保留或者丢弃片段。 那么可以用来显示什么功能呢&#xff1f;剪切&#xff0c;镂空、透明度等操作。 和深度缓冲的关系是&#xff1a; 先片段着色器&#xff0c;然后进入深度测试&#xff0c;最后加入模板测…

Linux第37步_解决“Boot interface 6 not supported”之问题

在使用USB OTG将“自己移植的固件”烧写到eMMC中时&#xff0c;串口会输出“Boot interface 6 not supported”&#xff0c;发现很多人踩坑&#xff0c;我也一样。 见下图&#xff1a; 解决办法&#xff1a; 1、打开终端 输入“ls回车”&#xff0c;列出当前目录下所有的文件…

Centos7 升级Docker 至最新版本

卸载旧版本的Docker yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine 安装需要的软件包 yum install -y yum-utils device-mapper-persistent-data lvm2 添加Docker的yum源 #yu…

防范[myers@airmail.cc].mkp攻击:解密[myers@airmail.cc].mkp勒索病毒的方法

引言&#xff1a; 随着科技的迅猛发展&#xff0c;网络安全问题日益突出&#xff0c;而勒索病毒也成为当前互联网威胁中的一大焦点。其中&#xff0c;[datastorecyberfear.com].mkp [hendersoncock.li].mkp [hudsonLcock.li].mkp[myersairmail.cc].mkp勒索病毒以其强大的加密能…

QT学习日记 | 初始QT

目录 一、创建QT文件 二、目录结构讲解 1、.pro文件 2、源文件与头文件 3、编译运行 4、界面文件 三、梦开始的地方&#xff08;Hello World&#xff01;&#xff09; 1、代码方式 2、拖拽方式 四、Qt中的“容器” 五、Qt的对象树机制 1、对象树的引入 2、对象树…