51单片机-定时器/计数器和中断系统 学习笔记(详解)

最近在B站学江协的51单片机教程,其中 [7-1] 定时器 一节看了一遍完全没懂,后来又去找了些其他视频和书籍,最终算是知道怎么用定时器了。

本篇内容即为我在这部分的学习笔记。

 

 

 

参考的学习资源:

        [1] B站相关视频教程 (这个是我觉得讲的很详细的,看完后基本就懂了)

        [2] STC89C52RC pdf资料

        [3] 《51单片机 原理及应用 (第4版) 》

 

 

 

目录

一、定时器 / 计数器

        1.原理

        2.编程步骤

        总结

二、中断系统

        1.概念及编程步骤

总结

        2.中断优先级

 

 

 

一、定时器 / 计数器

        用于定时或计数的寄存器。使用时同一时刻内只能使用其中一种功能。

        51单片机共有两个16位定时/计数器,叫T0和T1。T0又由两个8位寄存器TH0和TL0构成,同理,T1也由两个8位寄存器TH1和TL1构成。

 

 

        1.原理

源自 pdf手册

 

        刚才说一个定时器由俩寄存器构成。单片机上电后,两个寄存器的初始值都为0x00。定时器启动后,每隔一个机器周期,寄存器值会自动加1,顺序是先加TL低位寄存器(Timer Low),低位加满后自动进位到TH高位寄存器(Timer High)。由于两寄存器总共16位,所以加到65535后,再加就会导致数值溢出(进位),从而使TH和TL都清零。一次溢出代表一次定时的结束(定时时间就通过溢出来判断)。

51单片机中,一个机器周期固定由12个时钟周期组成。因此,如果使用6MHz的时钟频率,一个机器周期为2μs;如果使用12MHz的时钟频率,一个机器周期就为1μs

        怎么限定一次定时的时长呢:修改寄存器初值。以12MHz频率为例,一次溢出需要65536个机器周期,也就是65.536ms。因为溢出才能代表定时的结束,所以两寄存器的末值只能是65535。那么我们就只能通过修改寄存器初始值来规定定时时长。

        比如要设置一个50ms的定时器,我们在初始化定时器时可以赋寄存器初值为15536(转16进制为3cb0),这样从初到末,总共经过的时长就为50000个机器周期,也就是50毫秒。

 

 

        2.编程步骤(以定时器为例)

        使用定时器的步骤有:

        报备定时器 → 赋初始值 → 启动定时器 → 等待溢出 → 溢出后重置初值→ 清溢出

(1) 报备

        定时器报备,其实就是设置定时器的功能。有一个专门的寄存器TMOD(定时模式寄存器)用于设置这些功能。此寄存器每4位控制一个定时器。

        GATE:设置启动方式

                        置0时,只需要TR(第(3)步有说明)为1时就可以启动定时器。

                        置1时,需要TR和外部中断源INT(之后中断系统有说明)均为1时才能启动。

        C/T:设置功能为定时或计数。置0时为定时器,置1为计数器。

        M1&M0:模式选择。具体如下(以定时器0的设置为例):

                        一般常用16位定时器/计数器模式,即M1置0,M0置1。

例如,设置一个定时器0,不使用外部中断源,使用16位模式:

    TMOD = 0x01;

 

(2) 赋初值

        赋TH和TL寄存器的初始值,也就是规定定时时长。比如刚才提到的50ms定时器的设置:

    TH0 = 0x3c; //二进制0011 1100
    TL0 = 0xb0; //二进制1011 0000
    //00111100 10110000 = 十进制15536

        这样做就给定时器赋了个15536的初始值。

 

(3) 启动

        位于TCON(定时器/计数器控制寄存器,可按位寻址)中的TR位用于控制定时/计数器的启停。(由于TCON更多与中断相关,其他TCON寄存器的信息,在之后中断系统部分有说明)

    TR0 = 1; //打开定时器0的开关

 

(4) 等待

        同样位于TCON的TF位用于记录定时器是否溢出。当定时器溢出后,TF位会自动变为1。我们只需要在代码中检测TF位是否为1,就可以确定定时时间是否已到。需注意:在TF变为1后,需要手动将TF重置为0,保证下次正常定时。

 

(5) 重置初值

        若需要定时较长时间,比如想定1秒的时间,但每次定时周期只有50ms,这时就需要连续(循环)定时20次。而每次50ms结束时,需要重置寄存器的初值,保证下次定时还为50ms(而不是溢出后变回0x0000,65.536ms)。所以每循环一次要为TH和TL重置初值。

 

(6) 清溢出

        即刚才说的,每次溢出后,需要将TF手动重置为0。其实置0的操作可以不用显式地写“TF0 = 0;”来清除。若使TH0和TL0重新赋值,这个操作就已经隐式地清除了TF0。

所以,虽然有些代码中没有显式地写TF0 = 0;来清除TF0,但是通过重新赋值TH0和TL0的操作,TF0已经被清除了。这是51中断处理的一个常见做法,可以简化代码并提高效率。

 

 

        总结:

        基本概念:51单片机有两个16位的定时/计数器T0和T1,每个由两个8位寄存器(TH和TL)组成。这些寄存器用于定时或计数,同一时刻只能使用其中一种功能。

        工作原理:上电后,寄存器初始值为0。定时器启动后,每隔一个机器周期,寄存器值自动加1,直到溢出(从65535回到0),表示一次定时结束。通过修改寄存器的初始值可以设定定时时长。

        编程步骤

                报备:通过TMOD寄存器设置定时器功能,包括启动方式(GATE)、功能选择(C/T)和模式选择(M1和M0)

                赋初值:设置TH和TL寄存器的初始值,确定定时时长

                启动:通过TCON寄存器中的TR位控制定时器的启动

                等待:通过TCON寄存器中的TF位检测定时器是否溢出

                重置初值:需要连续定时时,每次定时结束后需要重置TH和TL寄存器的初值

                清溢出:每次溢出后,需要手动将TF位重置为0,以保证下次正常定时

 

 

二、中断系统

        中断就是在正常执行主程序时因某些中断条件触发,导致CPU停止当前运行的程序,转去执行中断条件下的程序,执行完后再返回刚才主程序中断的位置。以下是中断的运行原理和步骤:

 

 

        1.概念及编程步骤

(1) 中断源

        要让中断发生需要中断源。共有5种情况(中断源)可中断CPU当前执行的程序,分别如下:

        外部中断INT0(P3.2口),外部中断INT1(P3.3口),定时器T0,定时器T1,串口中断源

 

 

(2) 中断允许

        用于规定哪些中断源可以触发中断。中断允许是使用专门的中断允许寄存器IE设置的,IE的每个位如下:

        IE就相当于各中断源的开关,哪位为1,其对应的中断允许就打开。

 

 

(3) 中断请求

        每个中断源对应了一个中断请求的形式和中断请求标志。在达到特定条件后,中断源会向CPU发出中断请求,同时改变中断请求标志的状态。CPU就根据中断请求标志的状态来判断是否有中断。不同中断源的请求形式如下:

中断源请求形式
外部中断INT0P3.2口低电平或下降沿
定时器T0溢出
外部中断INT1P3.3口低电平或下降沿
定时器T1溢出
串口总线接受/发送数据结束

        中断请求标志则是存放在TCON寄存器内的B7/B5/B3/B1位。比如定时器T0的溢出,同时会带动TF0自动置1,代表中断请求发出了。

        关于外部中断源,分为两种请求形式:下降沿(由高电平转低电平)触发和低电平触发。这两种触发方式也由TCON来设置。例如要设置INT0的请求形式为下降沿触发,则需要把TCON的IT0设置为1。

        TCON的信息如下:

 

 

(4) 中断处理

        在某中断源发出中断请求(中断请求标志位变成1)后,CPU首先会保存当前的断点(当前正执行的语句位置),然后开始执行中断服务程序。中断服务程序的格式如下:

函数返回类型 函数名(参数) interrupt 中断号 {
    函数内容
}

e.g.
void timer0() interrupt 1 {
    /*...content...*/
}

        可以看出中断服务程序的格式除了普通函数有的之外,还有一个表示这是中断程序的单词interrupt,以及一个中断号(中断查询次序号)。

        在普通程序中,我们要执行一个函数,就是直接在代码行中加入函数名来跳转。而在中断程序中,中断函数的跳转不需要在代码行中写出,而是中断请求发出后,自动根据中断号跳转到对应中断程序。每个中断源对应的中断号如下:

中断源中断号
外部中断INT00
定时器T01
外部中断INT12
定时器T13
串口4

         完成中断程序的执行后,CPU重新找到断点的地址,然后返回到原程序继续向下执行。

 

 

总结:

        中断源:中断系统允许在特定条件下暂停当前程序,转而执行中断服务程序。有五种中断源可以触发中断:INT0、INT1、T0、T1和串口

        中断允许:通过中断允许寄存器IE来控制哪些中断源可以触发中断。IE寄存器的每一位对应一个中断源,设置为1表示允许对应的中断源触发中断

        中断请求:满足特定条件时,中断请求会被发出,并改变中断请求标志的状态。CPU根据这些标志来判断是否有中断需要处理。中断请求标志存放在TCON寄存器中

        中断处理:当一个中断源发出中断请求后,CPU会保存当前断点,然后执行相应的中断服务程序。中断服务程序的格式包括关键字interrupt和中断号,中断号对应于触发中断的中断源

        中断服务程序执行完毕后,CPU会返回到之前保存的断点位置,继续执行原来的程序。

 

 

 

        2.中断优先级

        如果在某一时刻发生了两个中断,或是一个中断正在执行,这时另一个中断请求发出,这种情况该执行哪个中断就涉及到不同中断的优先级顺序了。

(1) 自然优先级

        51单片机有一个自然优先级,即单片机会按照硬件电路实现的默认顺序来响应中断,这个默认中断优先级顺序是根据中断号来排序的。具体的规则和自然优先级顺序如下图所示:

        如果多个中断同时发生(且没有手动设置优先级),CPU会根据这个顺序来决定先响应哪个中断。

 

 

(2) 手动修改优先级

        当你的程序有某些特殊需求时(如需要定时器的计时非常准确),就可以通过IP(中断优先级寄存器)来手动修改优先级顺序。

                其中,每位名字的第一个字母P为Priority (优先级)

                第二个字母则分别是:S (Serial 串口) ,T (Timer 定时器),X(eXternal 外部中断)

                (比如定时器1就是PT1,外部中断0就是PX0)

        通过分别给某位赋值1,就能设置此位为高优先级

        如果同时设置了两个高优先级,那么中断的执行顺序就是先按自然优先级排序高优先级(置1的)中断,再同样按自然优先级排序低优先级(置0的)。比如给两个定时器置1,那中断顺序就为:T0, T1, INT0, INT1, Serial

        如果想设置更多级优先,可以使用IPH寄存器。其操作与IP相同,只是设置的优先级能更高

 

 

(3) 中断嵌套

        这张图就很好描述了中断嵌套,不再赘述:

取自上述B站教程

 

 

 

 --END

 

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值