在上文中我们讲到了基本的中断定义和外部中断的使用方法。本篇将继续介绍另外两种常见的中断,也即定时器中断和串口中断。
标准的51单片机有5个中断源:两个外部中断、两个定时器/计数器中断。具体如下:

优先级 中断源 介绍
1st INT0——外部中断0 由P3.2端口引入,低电平或下降沿引起。
2nd INT1——外部中断1 由P3.3端口引入,低电平或下降沿引起。
3rd T0——定时器/计数器0中断 由T0计数器计满回零引起。
4th T1——定时器/计数器1中断 由T1计数器计满回零引起。
5th TX/RX串口中断 由串口通信引起。

上文中我们通过对外部中断的介绍让大家有了一个对中断的基本认识。中断,也就是暂停你现在所运行的程序,去从事另外的工作。完成后再返回去做现在所做的这件事情。中断需要一个触发条件和一个处理程序,比如说你在敲代码,可能会出现这些情况:你可能会突然急着上厕所;你定了一个专注计时器到了时间要去打卡;你同学打电话找你你需要接听。你有一个良好的习惯,在处理这些事儿前你会先停下手头的工作并且保存你完成的代码,然后回来以后重新打开你保存的代码接着干活。
这就是一个比较符合生活习惯的中断过程,外部中断对应你急着上厕所的情况,是你自身受到某种外界条件的触发而执行的动作;定时器中断对应你定了专注计时器到时打卡的操作,是经过一个固定的时间就要去执行的;而串口通信则是有人通过通讯方式呼叫你,而你需要去完成通讯。在之前的文章中我们讲过了外部中断的处理方式,在本文中我们主要介绍定时器中断和串口中断两种方式。
首先是定时器中断,我们通过一个最简单的例子来介绍一下:

如图是一个非常简单的倒计时装置,这是定时器一种最基本的应用场景。每经过一秒钟的时间,LCD显示的数字减一。那么这样一个最基本的程序是以什么样的方式实现的呢?

#include <reg52.h>
unsigned char time = 10, cnt = 0;
void main(void)
{TMOD = 0X01;TH0 = (65536-50000)/256;TL0 = (65536-50000)%256;ET0 = 1;EA = 1;TR0 = 1;while (1){P1=time;}
}
void timer0() interrupt 1
{//50ms中断一次,20次为1scnt++;if(cnt==20){time--;cnt = 0; }TH0 = (65536-50000)/256;TL0 = (65536-50000)%256;
}

代码包括主函数部分和中断处理函数部分。主函数中我们首先对定时器进行了一些基本的设置,包括计时器模式和定时器初始值。然后我们开启了总中断和定时器0的中断,最后启动了定时器0。循环部分我们将倒计时值time直接输出到P1端的BCD码数码管,直接显示倒计时值。在中断处理函数部分,当每次中断发生时,我们对临时变量cnt进行一次加一操作。如果临时变量cnt值达到20,则倒计时值time应当减一,并复位cnt为0。然后重新装载定时器初始值。这就是一个最基本的定时器中断程序,基本流程如下图所示。

在这个程序中,我们所定的中断时间为50ms发生一次,因此当中断发生20次时,计时达到1秒,可以进行计数-1。而这个50ms的计数值又是怎么实现的呢?
在整个程序中,我们首先配置的是寄存器TMOD。TMOD寄存器对应的是51单片机最基本的定时器0和定时器1的相应配置,低四位对应定时器0,高四位对应定时器1。对于每个定时器的四位,其格式是这样的:

/ 第7/3位 第6/2位 第5/1位 第4/0位
含义 GATE门控 C/T切换 M1模式高位 M0模式低位
高电平 外部启动 计数器 模式2/3 模式1/3
低电平 内部启动 定时器 模式0/1 模式0/2

外部启动的含义是:当且仅当定时器0/1对应引脚P3.2/P3.3为高时,定时器置TRx=1方可以启动,相比内部启动模式增加了一层限制。
计数器和定时器的区别在于:计数器的脉冲来自于其对应的引脚脉冲,而定时器的脉冲来源为内部晶振。我们比较常用的是定时器,但我们不能忽略定时器本身兼有的计数器功能。这一功能在一些特殊场合会经常用到,如光电门测速是就需要检测引脚脉冲来实现计数。
定时器的四种模式如下:

模式 适用 定时/计数范围 TH初值 TL初值 描述
0 T0/T1 1-8192次脉冲 (8192-N)/32 (8192-N)%32 13位
1 T0/T1 1-65536次脉冲 (65536-N)/256 (65536-N)%256 16位
2 T0/T1 1-256次脉冲 256-N 256-N 8位自动重装,TH自动装载,TL储存计数
3 T0 1-256次脉冲*2 256-N1 256-N0 分离8位定时器,其中TH定时器由TR1驱动

内部晶振的频率一般为11.0592MHz,约合12MHz,产生的脉冲频率为晶振频率的1/12,即1MHz,时长为1μs。因此定时器能够定到的最长时间为65536μs,即约65.5ms。对于更长时间的定时,我们需要通过中断的进一步处理,比如之前举例中使用的变量处理方法。
定时器在实际使用中应用十分广泛,一种常见的应用是通过定时器输出PWM波形。PWM波形属于我们常见的方波,但与方波的主要区别是高电平与低电平的时间不等长。在一个很短的周期内,高电平与低电平的交替波动并不容易使人察觉,但端口上的平均电压降低了。因此我们如果将led灯接到PWM波的输出端口,可以看见led灯会有变暗;将直流电机接到PWM波的输出端口,可以看见电机旋转明显变慢。如图所示。

添加的代码为:

if(cnt<=time*2) moto = 1;
else moto = 0;

使得PWM占空比随时间下降由100%逐渐变为0,从而可以明显看到电机出现了减速效果。连接示波器也可以看到PWM波形的占空比有明显变化。

了解了定时器中断之后,下面我们可以接着了解串口通信和串口中断的过程。串口通信,顾名思义,通过一个串行端口串行地将数据发送出去/接收进来。在我们的单片机上,端口P3.0对应的RXD和P3.1对应的TXD就是这两个功能,TXD发送,RXD接收。与定时器一样,串口通信也有其控制寄存器SCON。SCON的格式如下表:

位置 含义 详细介绍
7-6 方式选择SM0 SM1 0=同步移位1=八位异步2/3=九位异步 2波特率固定
5 多机控制SM2 1=多机通信,0=单机通信
4 接收允许REN 1=允许接收,0=不允许接收
3 发送数据位TB8 第9数据位,可用作校验位和地址/数据标识位
2 接收标志位RB8 第9数据位或停止位
1 发送中断标志TI 发送一帧结束,TI=1触发中断
0 接收中断标志RI 接收一帧结束,RI=1触发中断

波特率即每秒钟传送的码元符号,也即数据位的个数。串口通信需要通信双方的波特率一致,方可正确传递信息。串口通信中波特率的设置通过定时器和控制位SMOD来实现。一般在串口通信中我们普遍使用定时器的模式2,也就是八位自动重装模式,以节约重装单片机计数值所需要的开销。具体的波特率计算公式如下(fosc为晶振频率,一般为11.0592MHz):

方式 名称 波特率公式
0 同步移位 B=fosc/12
1 8位异步通讯 B=T溢出率/32(SMOD=1则加倍)
2 9位异步通讯 B=fosc/64(SMOD=1则加倍)
3 9位异步通讯 B=T溢出率/32(SMOD=1则加倍)

其中T溢出率=fosc/12/t,t为定时器模式总长度与所定的时间长度的差。
比如我们需要设置波特率为9600时,选用定时器方式1,则可得到我们需要的t应该满足fosc/12/t/32=9600,推得t=3,定时器初值应设为0xfd。
下面是一个具体的例子,单片机向串口输出"Connected!",然后数码管实时显示串口发来的数字。

代码实现如下:

#include "reg52.h"
typedef unsigned char u8;
void init_ser()
{SCON = 0x50; TMOD = 0x20;TH1 = 0xFD;TL1 = 0x0;TR1 = 1;EA  = 1;ES  = 1;
}
void delay1ms(u8 s)
{u8 a,b,c;for(c=s;c>0;c--)for(b=142;b>0;b--)for(a=2;a>0;a--);
}
void send(u8 text[])
{u8 *s;for(s=text;*s;s++){SBUF = *s;}
}u8 code smg[17] = {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
u8 t,nums[8];void main()
{int i = 0;init_ser();send("Connected!\n");for(i=0;i<8;i++){nums[i]='0';}t=0;while(1){for(i=0;i<8;i++){P2 = i;P1 = ~smg[nums[i]-'0'];delay1ms(1);}}
}void int_uart(void) interrupt 4
{if(RI){RI = 0;nums[t++] = SBUF;if(t==8)  t=0;}if(TI) TI = 0;
}

串口初始化的部分与之前的定时器中断初始化相似,仅仅是不开启定时器中断,并改为开启串口中断ES。串口数据发送过程中,每发送一个8位数据都会触发一次中断,并需要在中断函数中清理TI标志位。串口每接收到一个8位数据,也会触发一次中断,可以通过RI标志位判断并处理接收到的数据,处理后也需要将RI标志清理。
以上就是中断的全部内容。中断机制是所有微处理器之中最重要的机制,正因为有了中断机制,处理器才可以处理更多复杂的不确定任务。中断机制的存在也为操作系统的实现奠定了基础。理解了中断机制和外部中断、定时器、串口等具体功能实现,单片机的基本核心内容就可以算是完结了。

从单片机到嵌入式开发——(6) 定时器与串口中断相关推荐

  1. 嵌入式开发比单片机要难很多?谈谈单片机和嵌入式开发设计经历

    嵌入式开发比单片机要难很多?谈谈单片机和嵌入式开发设计经历 \\\插播一条:文章末尾有惊喜哟~/// 单片机和嵌入式,其实没有什么规范的定义来区分他们,对于进行过单片机和嵌入式开发的开发者来说,都有他 ...

  2. 从单片机到嵌入式开发——(9) 从8051到ARM——STM32介绍和基本使用

    在之前的文章中,我们介绍了51单片机的IO口.编写语言.三种中断方式(外部.定时器.串口)和常见外设的应用(LED灯.数码管.按键.显示屏.AD.基于I2C协议通信的EEPROM),同时简要介绍了μC ...

  3. 51单片机 (6)串口中断通信+定时器2串口中断

    [若有疑问错误或版权等问题请联系我] [转载请注明出处:http://blog.csdn.net/leytton/article/details/48442129] 51单片机默认使用定时器1作为串口 ...

  4. 嵌入式学习——使用定时器同时实现串口通信和LED流水灯

    一.定时器的概念以及作用 1.定时器的概念以及作用 在芯片中使用晶振作为计时单位,通过对晶振的计数来实现计时,当时间达到定时器设定的时长后,会跳入对应的函数执行对应的操作. 定时器的主要作用是产生一个 ...

  5. 嵌入式作业STM32定时器实现串口通信及LED灯闪烁

    目录 前言 一.什么是定时器 1.定时器与计数器 2. 定时器有什么用 3. 定时器的原理 4.时钟产生器和时基单元 二.用STM32CubeMx创建项目 1. 创建项目 2.配置RCC和SYS 3. ...

  6. 【嵌入式系统开发13】采用串口中断方式完成单字符接受与字符串接受

    本文目的是主要介绍通过STM32F103C8T6接收到字符"s"时,停止持续发送"hello windows!"; 当接收到字符"t"时,持 ...

  7. 从单片机到嵌入式开发——(8) μC/OS-II嵌入式实时操作系统概述

    首先是一个对目前写的这些东西的总结.后面我会花大概两篇左右的内容来简单介绍一下STM32的使用.正文部分在后面一点,可以直接往后翻. 感想什么的 截止本篇为止,单片机的基本原理部分已经介绍完毕了.这个 ...

  8. 单片机项目实例 - 嵌入式开发 - C语言版 - 基础篇

    目录标题 1. 流水灯 效果,六个LED内嵌灯不停切换(位输出) 2. 流水灯 效果,六个LED内嵌灯不停切换(循环移位) 3. 数码管显示内容 4. 数码管显示内容 (略有闪烁) 5. 数码管显示内 ...

  9. [C语言] 在单片机的嵌入式开发中使用宏定义一键开关日志输出/打log调试

    前言 在编写项目时,我们通常需要日志输出来帮助我们追踪程序执行的内容,以便在出现BUG时较为方便的复现,并在调试完成后快速的关闭过于详细的LOG输出,避免干扰使用中的体验,在函数中一个一个的增加pri ...

最新文章

  1. Java单元测试的意义_单元测试重要意义及方法介绍
  2. 第十五届全国大学生智能车竞赛车模技术检查表格
  3. java for与foreach_java中for和foreach的区别是什么?
  4. 天大和武大计算机考研,985大学排名出炉,天大和武大并列第10,榜首是哪所?...
  5. OpenCASCADE:拓扑 API之3D模型Defeaturing
  6. uniq 去除重复命令使用方法介绍
  7. python数据库优化_python | Mysql性能优化一
  8. python cpu_python 让cpu满载
  9. 两台具有独立操作系统的计算机,第1章计算机网络习题与思考题参考答案
  10. 【老孙随笔】怎样才能当上项目经理?
  11. 【渝粤题库】陕西师范大学164105 物流管理学 作业(高起专)
  12. macos 10.15.2 iso镜像网盘下载
  13. Excel单元格设置选择项
  14. 反向代理为何叫反向代理?(含案例)
  15. SQL Server 遇到报错解决办法--更新中
  16. Windows 下Apache ftpServer安装和配置
  17. 小闹乎谈新手必备的撸猫手册
  18. 读取EL1809模块输入信号
  19. 应用调试(三)oops
  20. 中荣股份上市首日破发:市值相对蒸发约3亿元,黄焕然为实控人

热门文章

  1. 西门子 S7200 以太网模块连接力控组态方法
  2. linux查看ihs进程和端口,IHS日志查看
  3. abex' creak me#1
  4. 纯 Css 绘制扇形
  5. 接线 科思模块怎么和plc_博途S1200数字量模块接线图,NPN和PNP不要接错了,快收藏吧...
  6. 基于android的农产品销售App平台【可微信小程序与android studio运行】
  7. 代码随想录训练营day56
  8. RAP2的安装和部署
  9. 建筑图纸怎么查看?有什么CAD快速看图的技巧?
  10. 关于iPhone屏幕像素和各机型显示的探究