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

发布者:beta12最新更新时间:2022-01-12 来源: eefocus关键字: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-定时)%32

 

 

TH0和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

#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口是led

 

 

void Timer0Init()

{

TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。

 

TH0=0XFC; //给定时器赋初值,定时1ms

TL0=0X18;

ET0=1;//打开定时器0中断允许

EA=1;//打开总中断

TR0=1;//打开定时器

}

 

/*******************************************************************************

* 函 数 名       : main

* 函数功能 : 主函数

* 输    入       : 无

* 输    出    : 无

*******************************************************************************/

void main()

{

Timer0Init();  //定时器0初始化

while(1);

}

 

 

void Timer0() interrupt 1

{

static u16 i;

TH0=0XFC; //给定时器赋初值,定时1ms

TL0=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; //给定时器赋初值,定时1ms

TL1=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; //给定时器赋初值,定时1ms

TL1=0X18;

i++;

if(i==10000)

{

i=0;

P0=smgduan[n++];

if(n==16)n=0;

}

}

#include

 

#define uchar unsigned char

#define uint  unsigned int

 

sbit led1=P2^0;

uint num;

 

void TIM0init(void)

{

     TMOD|=0x02;    //设置定时器0为工作方式2

/*

TOMD=0x02,是定时器工作方式3,分为两个8位定时器,每个定时器计数最大值为255,

[1] [2]
关键字:STC89C52  中断  寄存器 引用地址:STC89C52之中断终结篇 ---- 自学笔记

上一篇:51单片机之串口通信 ---- 自学笔记
下一篇:51单片机12分频 ----- 学习笔记

推荐阅读最新更新时间:2024-11-09 14:50

利用定时中断接收不定长度的串口数据
在使用串口时,通常会遇到一些功能,如在TFT屏幕上显示串口收到的字符串,这些字符串直接是对方printf过来的,没有任何协议,此时为了保证显示内容是一整个句子(通常句子发送会有间隔),这是我们可以用定时器进行判断是否接收完成。 以stm32f4为例,代码基于正点原子的例程,为了阅读方便,删除了部分注释。 我们需要用到定时器和串口两部分: timer.h进行定时器初始化函数的声明。 #ifndef _TIMER_H #define _TIMER_H #include sys.h void TIM7_Int_Init(u16 arr,u16 psc); #endif timer.c进行定时器的定义及中断函数说明
[单片机]
学习笔记之-51单片机中断
1.中断的概念 通俗的讲,中断就是cup正在工作的时候,突然外部来了某一请求,要求cpu转去处理请求的事件,当事情做完之后cup再回来继续它的工作。这一过程称为中断 。 单片机中断响应可以分为以下几个步骤: 1、停止主程序运行。当前指令执行完后立即终止现行程序的运行; 2、保护断点。把程序计数器PC 的当前值压入堆栈,保存终止的地址(即断点地址),以便从中断服务程序返回时能继续执行该程序; 3、寻找中断入口; 4、执行中断处理程序; 5、中断返回。执行完中断处理程序后,就从中断处返回到主程序,继续往下执行。 流程图如下:     中断技术不仅解决了快速主机与慢速I/O设备的数据传送问题,而且还具有如下优点: 分时操作:CP
[单片机]
学习笔记之-51单片机<font color='red'>中断</font>
单片机中断子程序注意事项
跟我之前一样,对中断,定时器了解的不够透彻,被老师训了之后查资料搞实验后终于搞清楚了,下面说说我的看法:千万不要在中断函数中做多余的事!!!只能做最基本的操作,比如置标志位,让一个数加一等,与延时有关的操作千万不要做!你10ms进一次中断,在里面又扫描按键,又显示液晶,这里面花的时间远远地超过10ms,它肯定死在中断里出不来啊,因为你不关闭中断的话它一直10ms进去,最好在中断里设置几个标志位,进中断就让标志位置1,然后出中断,在主循环里判断标志位,如果标志位置1了,就清零标志位,然后做其他的动作。好好想一想,思路一定要清晰! 如果中断子程序进去就关闭中断使能位,就可以有延时等操作了,不用再担心频繁中断,导致死循环在中断子程序
[单片机]
Linux驱动之中断处理体系结构简析
S3C2440中的中断处理最终是通过IRQ实现的,在Linux驱动之异常处理体系结构简析已经介绍了IRQ异常的处理过程,最终分析到了一个C函数asm_do_IRQ,接下来继续分析asm_do_IRQ,目标是推导出中断的处理过程。 看到asm_do_irq函数,它位于archarmkernelIrq.c中。它先根据irq中断号从irq_desc 数组中取出这个中断对应的desc结构体,irq中断号是根据INTOFFSET寄存器的值来确定的,这个寄存器里的值根据中断的来源不同会置位相应的位,它在调用C函数asm_do_IRQ之前被存放在r0中,在C函数中即是irq。 asmlinkage void __exception as
[单片机]
STM32中按键中断分析(附源码)
  在按键学习中,我们有用到查询的方法来判断按键事件是否发生,这种查询按键事件适用于程序工作量较少的情况下,一旦程序中工作量较大较多,则势必影响程序运行的效率,为了简化程序中控制的功能模块的执行时间,引入中断控制就很有必要,,一旦有中断时间发生,则程序立马跳转到中断向量的执行程序中,执行完成后就恢复到正常的程序状态。   在STM32F中采用中断控制器NVIC来设定中断。按照中断初始化配置的结构体文件,我们需要在NVIC初始化结构体配置如下:   void EXti_PB12_Config(void)   {   //定义结构体   GPIO_InitTypeDef GPIO_InitStructure;   EXTI_I
[单片机]
S3C2440 点灯
点亮开发板上的led灯,需先查看原理图,找到对应引脚,以及搞清楚原理图,如何电路上灯会亮。 1、看原理图 JZ2440v2_sch.pdf 找到对应的引脚 nLED_1 对应 GPF4 nLED_2 对应 GPF5 nLED_4 对应 GPF6 2、看芯片手册 S3C2440A_UserManual_Rev13.pdf 设置对应 I/O 寄存器 CPFCON 控制寄存器 GPFCON 数据寄存器 将引脚对应控制寄存器设置为输出,数据寄存器设置为0(表示输出低电平),即可点亮对应LED灯 汇编点亮nLED_1代码如下: .global _start _start: LDR R0,=0x560000
[单片机]
lesson3 数码管静态显示及定时器和中断应用
1、电容帮助晶振起振。 2、发光二极管LED(Light Emitting Diode),液晶LCD(Liquid Crystal Display)。 3、数码管原理: 4、中断系统:中断发生——中断响应和中断服务——中断返回。(中断嵌套) 5、优点:1.分时操作;2.实时响应;3.可靠性高。 6、80C51单片机的中断优先级有三条原则:CPU同时接收到几个中断时,首先响应优先级别最高的中断请求。 正在进行的中断过程不能被新的同级或低优先级的中断请求所中断。 正在进行的低优先级中断服务,能被高优先级中断请求所中断。 为了实现上述后两条原则,中断系统内部设有两个用户不能寻址的优先级状态触发器。其中一个置1,表示正在响应高优先级的
[单片机]
lesson3 数码管静态显示及定时器和<font color='red'>中断</font>应用
STM32D单片机退出睡眠模式在外设控制寄存器中使能一个中断
STM32D单片机退出睡眠模式在外设控制寄存器中使能一个中断,而不是在NVIC(嵌套向量中断控制器)中使能区别引发的中断过程步骤整理 这两个使能的区别?前者是中断线EXTI_Init(),后者是NVIC_Init(),两者通道中断通道号联系起来,例如中断线11配置中断引脚源GPIO_EXTILineConfig()寄存器是AFIO- EXTICR;EXTI_Line11属于EXTI15_10_IRQn外部中断通道号
[单片机]
STM32D单片机退出睡眠模式在外设控制<font color='red'>寄存器</font>中使能一个<font color='red'>中断</font>

推荐帖子

模电怎么学
模电到底要怎么学,毕业十年了,对模电都没有个概念 工作是真难找 模电怎么学毕业十年了,还能想起有模电这回事没有概念的东西,估计更没兴趣 首先,从基础概念开始复习,如半导体器件(二极管、三极管)、放大器原理、反馈电路、振荡电路、滤波电路等。这些基础知识是后续学习的基石。 可以参考一些经典的教材,如《模拟电子技术基础》(童诗白、华成英编著),这本书在国内高校中被广泛使用,内容全面且深入浅出学习一门技术一项技能,一个是个人的兴趣爱好,自己喜欢模电,大部分
中央上 模拟电子
单片机实用汇编教程下载
单片机实用汇编教程下载单片机实用汇编教程下载汇编教程越来越多了汇编还是很难的。。。。好好研究一下呜呜学习的是汇编语言,并且考试,看看谢谢分享下载了,谢谢分享学资料,对学习汇编有用。
keenjon 51单片机
请教一个RF SWITCH
请大家推荐一款T/RSwitch用在433Mhz频段发射功率大概33dBmRF芯片是CC1020,我查到有网上的RF模块中有像H226,S193类似的射频开关,6脚的,但没有找到DATASHEET,谁有这方面的资料分享一下啊~~~或是指点一下怎么搜索也行~~~~先谢谢了buythem@163.com请教一个RFSWITCHAS179看能不能用,这颗料便宜好买,回复楼主xiaochuan610的帖子非常感谢~~非常感谢
xiaochuan610 RF/无线
发现 micropython 的构建脚本里面将 .py 文件转化为 c 文件后编译。
发现micropython的构建脚本将py脚本先转换为.mpy文件,然后转化为c文件然后编译,真是大开眼界。此内容由EEWORLD论坛网友zy459994202原创,如需转载或用于商业用途需征得作者同意并注明出处发现micropython的构建脚本里面将.py文件转化为c文件后编译。这样就不怕直接反编译了。可能更重要的是效率也有保证{:1_103:}{:1_103:}{:1_103:}{:1_103:}{:1_103:}{:1_103:}{
zy459994202 MicroPython开源版块
6410平台上, IO口 GPN8(EINT8) 是一个复用的PIN, 如何从这个IO口(PIN)上得到中断后,再取得数据?
以下方法不行,总是Bit8=1.请指正.g_pGPIOReg-GPNCON&=~(316);//clearGPN8g_pGPIOReg-GPNCON&=~(316);//setGPN8toinputg_pGPIOReg-GPNDAT&=0;Sleep(10);if(g_pGPIOReg-GPNDAT&(18)){//为1NKDbgPrintfW(L.......
zhouzhaofu 嵌入式系统
《RISC-V开放架构设计之道》-RV32CV+特权架构+可扩展选项
#RV32V向量!(/data/attachment/forum/202411/05/005002gt10xo2krdcu0psy.jpg.thumb.jpg?rand=5372.011770651946)向量操作主要用于数据级并行,最著名的数据级并行架构是SIMD,她将64位寄存器划分成了多个8位,16位或32位的片段,然后并行的计算他们,但是RISC-V使用向量架构进行实现前面章节提到的每一条整数和浮点计算都有对应的向量版本RV32V添加了32个名称以V开头的向量寄存器,但是
rtyu789 编程基础
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved