• 【单片机基础】单片机中断和定时


    中断

    什么是中断?

    中断是为使单片机具有对外部或者内部随机发生的事件处理而设置的,中断的存在,很大程度提高了单片机处理外部或内部事件的能力。

    举个例子:当你在烧一壶水,然后去吃饭。当突然听到水壶发出水烧开的报警声,这是你会放下碗筷,立即去关掉火,然后将开水灌入暖水壶,灌完开水后,再继续吃饭。

    标准的51单片机有5个中断源,分别为2个外部中断,两个定时中断和1个串口中断。
    在这里插入图片描述

    中断IE寄存器

    中断IE寄存器在特殊功能寄存器(SFRs)地址、复位值等信息
    ——STC89C52参考芯片手册
    在这里插入图片描述
    在这里插入图片描述

    中断查询次序

    在这里插入图片描述

    例程

    示范程序,外部中断1

    //外部中断1初始化
    void int1Init()
    {
    	EA = 1;	//开总中断
    	EX1 = 1;//开外部中断1
    	IT1 = 1;//外部中断1下降沿触发	
    }
    
    //外部中断1处理函数
    void Int1_Routine() interrupt 2
    {
      //以下用户处理程序
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    定时器/计数器

    实现定时的方法?

    1. 软件定时:软件定时不占用硬件资源,但占用CPU时间,降低了CPU的利用率。例如:延时程序
    2. 采用时基电路电时:例如采用555电路,外接必要的元器件(电阻电容),可构成硬件定时电路。但是硬件连接好以后,定时器与定时范围不能用软件进行控制和修改,及不可编程,且定时时间容易漂移。
    3. 可编程定时器定时:最方便的办法是利用单片机内部的定时器/计数器。结合了软件定时精准和硬件定时器电路独立的特点。

    定时计数的概念

    大个比方,一杯水1000滴刚好装满,这时这杯水初始化已经装入500滴水了,那么问题来了:
    1、还需要滴入多少滴水才能将其装满?
    答:还需要滴入500滴水才能滴满,501滴水时溢出。
    滴入水比喻为计数

    2、如果每秒滴入1滴水,还需多长时间才能将其滴满?
    答:还需要500秒时间才能将其装满,501秒溢出。
    这时滴入水的时间就比喻为“定时”

    什么是单片机定时器/计数器?

    定时器,准确来说是“定时/计数器”
    通俗的说:定时器的本质就是计数器,CPU一旦开启定时功能后,定时器便在晶振的作用下自动开始计时。当定时器计数器满后,会产生中断,即通知CPU该如何处理。

    举个例子:CPU很忙,不停干活不能分心去看时间,这时可以设置一个闹钟每分钟提醒一下,这个闹钟就是定时器。要是开了中断,就是每分钟可以停下去中断里面干点其他事情。这样CPU工作效率就会提高。

    定时器/计数器内部结构

    定时器/计数器实质是加1计数器(16位),由高8位和低8位两个寄存器组成。TMOD是定时器/计数器的工作方式寄存器,确定工作方式和功能TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志。
    在这里插入图片描述

    定时器的相关寄存器

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    51单片机定时器初值计算方法详解

    定时:
    2 n = T / T c y + X 2^{n}= T/Tcy+X 2n=T/Tcy+X
    X = 2 n − T / T c y X=2^{n}-T/Tcy X=2nT/Tcy

    n计数器工作方式 :(方式0时,N=13;方式1时,N=16;方式2时,N=8)

    T定时器时长

    T c y Tcy Tcy机器周期

    X计数初值

    根据定时时间和工作方式,计算出时间常数X,把X转换成二进制,高8位给TH1,低八位给TH1

    这是举个例子:STC89C52单片机,设置晶振为12M,使用16位的定时器,那单片机定时器0的最大计数就是65536,那单片机的一个机器周期就是1us,定时器 0工作在方式1时最大定时65.536ms。
    定时器的定时时间T = (65536-X),单位是us;
    定时器初值X = 65536-T,
    假设定时时间T=10ms=10000us,
    那定时器初值X=65536-10000=55536us,也就是定时器0从55536开始递加到65536就是10ms,所以55536就是定时器的初值,55536转化为十六进制为0Xd8f0,所以定时器的初值为:
    TH0 = 0XD8;
    THL = 0XF0;

    例程

    示范例程,定时器0(第一种编程方式)

    //定时器0初始化
    void timer0Init()
    {
    	EA = 1;	//打开总中断
    	ET0 = 1;//打开定时器0中断
    	TR0 = 1;	 //启动定时器0
    	TMOD = 0X01; //定时器工作模式1,16位定时模式
    	TH0 = 0xD8;
    	TL0 = 0xF0; //定时10ms
    }
    
    //定时器0中断函数
    void timer0() interrupt 1
    {
    	TH0 = 0xD8;
    	TL0 = 0xF0; //定时5ms
    	//以下为用户处理程序	
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    示范例程,定时器0(第二种编程方式)

    //#define FOSC 11059200L //晶振设置,默认使用11.0592M Hz
    #define FOSC 12000000L //晶振设置,使用12M Hz
    //#define FOSC 24000000L //晶振设置,使用24M Hz
    
    #define TIME_MS 10 //设定定时时间 ms ,在11.0592M晶振下,不易超过60ms
    
    /*******************************************************************************
    * 函 数 名 :Timer0Init
    * 函数功能 :定时器0初始化
    * 输    入 :无
    * 输    出 :无
    *******************************************************************************/
    void Timer0Init()
    {
    	TMOD=0x01; //设置定时器0工作方式为1
    	TH0=(65536-FOSC/12/1000*TIME_MS)/256;
    	TL0=(65536-FOSC/12/1000*TIME_MS)%256;
    	ET0=1; //开启定时器0中断
    	TR0=1;	//开启定时器	
    	EA=1;  //打开总中断
    }
    
    /*******************************************************************************
    * 函 数 名 :Timer0Int
    * 函数功能 :定时器0中断函数 , 每隔TIME_MS ms进入
    * 输    入 :无
    * 输    出 :无
    *******************************************************************************/
    void Timer0Int() interrupt 1
    {
    	TH0=(65536-FOSC/12/1000*TIME_MS)/256;
    	TL0=(65536-FOSC/12/1000*TIME_MS)%256;
    	//以下为用户处理程序
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
  • 相关阅读:
    学习JDBC总结
    Hadoop对集群的一些操作的命令介绍
    【架构与设计】常见微服务分层架构的区别和落地实践
    负载均衡原理分析与源码解读
    【leetcode】往完全二叉树添加节点
    【Vue3】第十四部分 父子组件传参
    阿里云服务器更换公网IP地址的方法流程
    优选商机+沃视获客+外呼系统+智能CRM
    mmsegmentation 添加L1Loss
    『PyQt5-Qt Designer篇』| 10 Qt Designer中控件的尺寸相关设置(sizePolicy策略)
  • 原文地址:https://blog.csdn.net/lzxiaotu/article/details/117426072