STC89C52之中断终结篇 ---- 自学笔记

2023-10-14 12:18

本文主要是介绍STC89C52之中断终结篇 ---- 自学笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、概述

1.1、五个中断

  • 外部中断0                                INT0
  • 定时器/计数器(C/T)中断0         T0
  • 外部中断1                                 INT1
  • 定时器中断1                              T1
  • 串行通信中断                             RX  and  TX

1.2、中断允许寄存器(IE)

       

 

1.3中断请求标志(TCON)

 

ITO(TCON.0):外部中断0触发控制位。

  •   当IT0=0时,为电平触发方式      低电平
  •   当IT0=1时,为边沿触发方式(下降沿有效)

IE0(TCON.1):外部中断0中断请求标志位。

IT1(TCON.2):外部中断1触发方式控制位。

IE1(TCON.3):外部中断1中断请求标志位。

TF0(TCON.5):定时/计数器T0溢出中断请求标志位。    置1溢出

TF1(TCON.7):定时/计数器T1溢出中断请求标志位。

1.4、控制寄存器(TCON)

1.5、工作方式寄存器(TMOD)

  • 方式0时,N=13(此为TH为8位,TL为5位)
  • 方式1时,N=16(此为TH为8位,TL为8位)
  • 方式2时,N=8(此为TH为8位,TL为0位)
  • 方式3时,N=8(此为TH为8位,TL为8位,只适用于T0,且T0被分成两个独立的8位计数器TH与TL)
     
12M的晶振   定时1ms
第一种  THx,TLx表达方式
定时=(2的13次方-计数初值)*12/晶振频率 = (8192-计数初值)*12/12= 8192-计数初值    ( 单位:微秒)计数初值 = T0 = 8192-定时 + 1 = 7193  = 0x1c19     TH0 = 0x1c   TL0 = 0x19
不知道第一种方式对不对,我设置成TH0=0x1c;TL0=0x19,这样LED能闪烁第二种  THx,TLx表达方式        此种方式网上摘抄
因为寄存器是13位的,高位8bit,低位5bit, 2^5=32
定时=5ms = 5000微秒
所以有: TH0 = (8192-定时)/32; TL0 = (8192-定时)%32TH0和TL0的赋值是定时器T0装填初值,TH0是高位,TL0是低位,连起来看就是定时器T0装填了初值。
除以32或者除以256是用来求高位的初值,同理取余就是求低位初值,
至于为什么有32和256是因为定时器工作方式不同,工作方式在之前的TMOD赋值的时候设定,256对应工作方式2,而32对应方式0

0000 0000                       TMOD |= 0x00               方式1           常用

0000 0001                        TMOD |=0x01               方式2            常用

0000 0010                        TMOD |=0x02              方式3            不常用

0000 0011                        TMOD |=0x03            方式4             不常用

 

二、代码

2.1、方式0

方式 0 为 13 位计数,由 TL0 的低 5 位(高 3 位未用)和 TH0 的 8 位组成。 TL0 的低 5 位溢出时向 TH0 进位,TH0 溢出时,置位 TCON 中的 TF0 标志,向 CPU 发出中断请求。

#include<reg52.h>
#define uchar unsigned char	     //  #define宏定义关键字
#define uint  unsigned int
/*typedef unsigned int u16;	     //  关键字 typedef 可以为类型起一个新的别名 
typedef unsigned char u8;*/
//  sbit led=P2^0;	    第一个led灯闪烁
//  sbit led = P2^1;	第二个led灯与DA1切换灯闪烁
//  sbit led = P2^2;	第三个led灯闪烁,数码管第一位与数码管第二位来回跳动
//  sbit led = P2^3;    第四个led灯闪烁,数码管第一位与数码管第三位来回跳动
//  sbit led = P2^4;    第五个led灯闪烁,数码管第一位与数码管第五位来回跳动 
//  sbit led = P2^5;    第六个led灯闪烁并且有滴答滴答的声音
//  sbit led = P2^6;    第七个led灯闪烁sbit led = P2^7;    // 第八个LED灯闪烁
uchar num;
// u8 num =0;void TIM0init()
{
/*
1、选择工作方式
TMOD |= 0x00;   工作方式0计数器是13位的,计数范围1~8192(2^13=8192)
定时=(2的13次方-计数初值)*12/晶振频率   = 2^16 -1000 +1 = 7193 = 0x1c19
T0  or T1  = 0x1c19                    
TH1 or TH0 = 0x1c	                      
TL1 or TL0 = 0x19工作方式0:寄存器为13为   THx为8位  TLx为5位(高三位未用)
除以32用来求高八位(THx)的初值,取余就是求低位初值
例子:方式0是13位定时器,其最大计数值是8192,51单片机定时器/计数器是加法计数,因此如果要计数1000个脉冲,定时器的初值应该是8192-1000 ,
如果要计数100个脉冲,定时器的初值应该是8192-100
该16位定时器又分成了高8 位和低8位,其中低8位只用了5位,最大装回值是31,超过32则装入高8 位,高8位的1代表32。
因此高8位装的是32的整数倍,低8位装32的余数,
上例的求模和求余就 是这个意思,很明显答上例设定的计数值是100个脉冲,
如果晶振是12M,一个脉冲是1us,那么定时时间就是100us。TMOD |= 0x01;	工作方式1
TMOD |= 0x10;   工作方式2
TMOD |= 0x11;   工作方式3
*/TMOD|=0x00;   
/*
2、选择定时器/计数器(C/T)
T1(16位C/T+1) = TH1(八位) + TL1(八位)
T0(C/T)  = TH0(高八位寄存器)   + TL0(低八位寄存器)
TH1 =
TH1 =*/         TH0= (8192-1000)/32;             //0x1c;//(8192-5000)/32;   //装入初值,怎么计算,下面分析TL0=  (8192-1000)%32;            //0x19;//(8192-5000)%32;    EA=1;    //开总中断ET0=1;   //开定时器中断TR0=1;   //启动定时器0
}
/*
interrupt 0  指明是外部中断0;
interrupt 1  定时器中断0; 
interrupt 2  外部中断1;
interrupt 3  定时器中断1;
interrupt 4  串行口中断;*/
void T0_time()  interrupt 1      
{TH0= 0x1c;        //(8192-5000)/32; //重装初值,如果不重装,中断只触发一次TL0= 0x19;       //(8192-5000)%32;num++;
}void main()
{TIM0init(); while(1){if(num==200)     //如果到了200,说明一秒时间到{num=0;led=~led;   //闪灯}}
}

计数初值与计数个数的关 系为:X=2(13)-N

方式0的例子

2.2、方式1

方式 1 的计数位数是 16 位,由 TL0 作为低 8 位,TH0 作为高 8 位,组成了 16 位加 1 计数器。


#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;sbit led=P2^0;	 //定义P20口是ledvoid Timer0Init()
{TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。TH0=0XFC;	//给定时器赋初值,定时1msTL0=0X18;	ET0=1;//打开定时器0中断允许EA=1;//打开总中断TR0=1;//打开定时器			
}/*******************************************************************************
* 函 数 名       : main
* 函数功能		 : 主函数
* 输    入       : 无
* 输    出    	 : 无
*******************************************************************************/
void main()
{	Timer0Init();  //定时器0初始化while(1);		
}void Timer0() interrupt 1
{static u16 i;TH0=0XFC;	//给定时器赋初值,定时1msTL0=0X18;i++;if(i==1000){i=0;led=~led;	}	
}

2.3、方式2

自动重装初值的 8 位计数方式。工作方式 2 特别适合于用作较精确的脉冲信号发生器

#include "reg52.h"			 //此文件中定义了单片机的一些特殊功能寄存器typedef unsigned int u16;	  //对数据类型进行声明定义
typedef unsigned char u8;u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
u8 n=0;void Timer1Init()
{//	TMOD   |=0X01;              速度快//选择为定时器1模式,工作方式1,仅用TR1打开启动。TMOD    |=0x02;// TMOD   |=0x00;//  TMOD  |= 0x03;TH1=0XFC;	//给定时器赋初值,定时1msTL1=0X18;	ET1=1;//打开定时器1中断允许EA=1;//打开总中断/***************************************************************
** * TCON的中断请求标志											      
** *																 
** *       位:	   7      6      5      4      3      2     1      0  
** *																  
** * 字节地址:	  TF1     TR1    TF0   TR0    IE1    IT1   IE0    ITO 
** *     说明:														  
** *ITO(TCON.0):外部中断0触发控制位。								  
** *    当IT0=0时,为电平触发方式   低电平						     
** *    当IT0=1时,为边沿触发方式(下降沿有效)						  
** *IE0(TCON.1):外部中断0中断请求标志位。							
** *IT1(TCON.2):外部中断1触发方式控制位。							  
** *IE1(TCON.3):外部中断1中断请求标志位。							  
** *TF0(TCON.5):定时/计数器T0溢出中断请求标志位。置1溢出			  
** *TF1(TCON.7):定时/计数器T1溢出中断请求标志位。					  
** ****************************************************************														  
** *																  
** *****************************************************************
** * 控制寄存器(TCON)														  ** * TCON的低四位用于控制外部中断,											  
** * TCON的高四位用于控制定时器\计数器的启动和中断							 
** *  																		   位:  7    6    5     4     3   2    1   0						   字节地址: TF1  TR1  TF0   TR0											   TF1(TCON.7):T1 溢出中断请求标志位。T1 计数溢出时由硬件自动置 TF1 为 1。 CPU 响应中断后 TF1 由硬件自动清 0。T1 工作时,CPU 可随时查询 TF1 的 状态。所以,TF1 可用作查询测试的标志。TF1 也可以用软件置 1 或清 0,同硬件置 1    或清 0 的效果一样。														  TR1(TCON.6):T1 运行控制位。TR1 置 1 时,T1 开始工作;TR1 置 0 时,	   T1 停止工作。TR1 由软件置 1 或清 0。所以,								   用软件可控制定时/计数器的启动 与停止。									   TF0(TCON.5):T0 溢出中断请求标志位,其功能与TF1相同。					   TR0(TCON.4):T0 运行控制位,其功能与TR1相同。							   ** ********************************************************************************/	TR1=1;//打开定时器			
}void main()
{	Timer1Init();  //定时器1初始化while(1);		
}void Timer1() interrupt 3
{static u16 i;TH1=0XFC;	//给定时器赋初值,定时1msTL1=0X18;i++;if(i==10000){i=0;P0=smgduan[n++];if(n==16)n=0;	}	
}
#include<reg52.h>#define uchar unsigned char
#define uint  unsigned intsbit led1=P2^0;
uint num;void TIM0init(void)
{TMOD|=0x02;    //设置定时器0为工作方式2/*TOMD=0x02,是定时器工作方式3,分为两个8位定时器,每个定时器计数最大值为255,计数到最大255,再加1,产生中断,相当于计数从0到256。晶振频率为12M,机器周期为1M,那么机器一周期时间为1/f=1/1M=1微秒。定时器的最大计数为255,最大的计数时间为256微秒想要以1秒闪烁,TH0=6;TL0=6;每次计数都是记(256-6=250)微秒,中断次数1秒除以250微秒*/TH0=6;   //装入初值TL0=6;    EA=1;    //开总中断ET0=1;   //开定时器中断TR0=1;   //启动定时器0
}void T0_time()  interrupt 1      
{//相比上面的方式0,这里不需要认为加入重装初值的代码num++;
}void main()
{TIM0init(); while(1){if(num==4000)     //如果到了4000,说明1秒时间到{num=0;led1=~led1;   //让发光管状态取反}}
}

2.4、方式3

#include<reg52.h>#define uchar unsigned char
#define uint  unsigned intsbit led1=P2^0;
sbit led2=P2^1;
uint num1,num2;void Tinit()
{TMOD|=0x03;  //设置定时器0为工作方式3	TH0=6;      //装初值TL0=6;EA=1;	     //开总中断ET0=1;      //开定时器0中断ET1=1;      //开定时器1中断TR0=1;	     //启动定时器0TR1=1;	     //启动定时器0的高8位计数器
}void TL0_time()  interrupt 1
{TL0=6;  //重装初值num1++;
}void TH0_time()  interrupt 3  //占用T1定时器的中断号
{TH0=6;  //重装初值num2++;
}void main()
{Tinit();while(1){if(num1>=4000)  //12*(1/12MHz)*(256-6)*4000=1s{						  num1=0;led1=~led1;}if(num2>=2000)  //12*(1/12MHz)*(256-6)*2000=0.5s{num2=0;led2=~led2 ;} }}

参考博客:https://blog.csdn.net/weixin_42653531/article/details/82530685

三、总结

一个初始化函数void   bb(){// 进行什么中断  T0?   T1?  RI? }一个操作函数void cc() interrupt 1{// 中断之后干啥    led闪烁?  数码管显示数字?}

 

这篇关于STC89C52之中断终结篇 ---- 自学笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/210442

相关文章

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear

数学建模笔记—— 非线性规划

数学建模笔记—— 非线性规划 非线性规划1. 模型原理1.1 非线性规划的标准型1.2 非线性规划求解的Matlab函数 2. 典型例题3. matlab代码求解3.1 例1 一个简单示例3.2 例2 选址问题1. 第一问 线性规划2. 第二问 非线性规划 非线性规划 非线性规划是一种求解目标函数或约束条件中有一个或几个非线性函数的最优化问题的方法。运筹学的一个重要分支。2

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

查看提交历史 —— Git 学习笔记 11

查看提交历史 查看提交历史 不带任何选项的git log-p选项--stat 选项--pretty=oneline选项--pretty=format选项git log常用选项列表参考资料 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史。 完成这个任务最简单而又有效的 工具是 git log 命令。 接下来的例子会用一个用于演示的 simplegit

记录每次更新到仓库 —— Git 学习笔记 10

记录每次更新到仓库 文章目录 文件的状态三个区域检查当前文件状态跟踪新文件取消跟踪(un-tracking)文件重新跟踪(re-tracking)文件暂存已修改文件忽略某些文件查看已暂存和未暂存的修改提交更新跳过暂存区删除文件移动文件参考资料 咱们接着很多天以前的 取得Git仓库 这篇文章继续说。 文件的状态 不管是通过哪种方法,现在我们已经有了一个仓库,并从这个仓

忽略某些文件 —— Git 学习笔记 05

忽略某些文件 忽略某些文件 通过.gitignore文件其他规则源如何选择规则源参考资料 对于某些文件,我们不希望把它们纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。通常它们都是些自动生成的文件,比如日志文件、编译过程中创建的临时文件等。 通过.gitignore文件 假设我们要忽略 lib.a 文件,那我们可以在 lib.a 所在目录下创建一个名为 .gi

取得 Git 仓库 —— Git 学习笔记 04

取得 Git 仓库 —— Git 学习笔记 04 我认为, Git 的学习分为两大块:一是工作区、索引、本地版本库之间的交互;二是本地版本库和远程版本库之间的交互。第一块是基础,第二块是难点。 下面,我们就围绕着第一部分内容来学习,先不考虑远程仓库,只考虑本地仓库。 怎样取得项目的 Git 仓库? 有两种取得 Git 项目仓库的方法。第一种是在本地创建一个新的仓库,第二种是把其他地方的某个