一、中断系统
1、基础概念
1.1、中断结构
1.2、中断定义
中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的;
当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求,要求CPU暂停当前的工作,转而丢处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。
1.3、中断源定义
请示CPU中断的请求源称为中断源(打断当前工作的事件)。
微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题。
通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断请求源,即规定每一个中断源有一个优先级别。
CPU总是先响应优先级别最高的中断请求。
1.4、51单片机的5个中断源
外部中断:某个引脚电平变化产生的中断;
UART:串口中断(用于串口通信)
2、中断执行流程
1、中断源发出中断请求;
2、CPU检查是否响应中断及该中断源是否被屏蔽;
3、检查中断优先级;
4、保护现场;
5、执行中断服务函数;
6、恢复现场;
注:
(1)中断总开关(EA)控制全部中断源的开关;
(2) 每个中断源可独立被关闭;
(3)中断优先级可用系统默认的也可自配;
(4)中断低级别无法打断高级别;嵌套最多二层;
(5)相同优先级的中断源谁的数字小先响应谁;
3、中断向量表
3.1、中断向量表
指针的数组,保存的是中断函数的入口地址;
3.2、51的中断向量(中断号)
注: 中断设置:中断方式、中断允许;
3.3、中断服务函数
系统调用中断服务函数(在硬件中实现软件功能)
中断和轮询之间的区别
1、中断时,设备会通知CPU引起注意;而在轮询中,CPU会稳定地检查设备是否需要注意。
2、中断不是协议,而是一种硬件机制;轮询反之。
3、在中断中,该设备由中断处理程序提供服务;轮询时,该设备由CPU维修。
4、中断可以随时发生;轮询时,CPU会以固定的间隔稳定地对设备进行投票。
5、在中断中,中断请求线用作指示设备需要维修的指示;在轮询时,命令就绪位用作指示,表明设备需要维修。
6、在中断中,一旦任何设备将其中断,处理器就会受到干扰;在轮询中,处理器通过重复检查每个设备的命令就绪位来浪费无数的处理器周期。
二、外部中断
中断寄存器
(一)中断允许寄存器IE
(二)中断优先级控制寄存器IP/XICON和IPH
(三)定时器/计数器0/1控制寄存器TCON
低电平触发:引脚为低电平不断触发中断
下降沿触发:高电平掉低电平过程中会请求中断
三、定时器/计数器
(1)定时器的工作原理:
定时器的原理是一个加法器,通过晶振分之一开始加,直到溢出,发生中断;(通过计数器初值来设置中断时间)
(2)定时器的功能:
LED点亮、数码管显示及模拟PWM功能
(3)晶振频率:
分为12MHz和11.0592MHz
定时器/计数器0和1的相关寄存器
(一)定时器/计数器控制寄存器TCON
(二)定时器/计数器工作模式寄存器TMOD
注:
16位定时器工作模式:counter0//两个字节,TH0(高)与TL0(低)组合在一起;
8位自动重装载定时器(工作的是TL0)TL0加到255后溢出,溢出时刻会把TH0的值装回来;
四、PWM(脉冲宽度调制)及 蜂鸣器
(一)PWM(脉冲宽度调制)
PWM:一种通过数字信号控制模拟电路的技术;
指标:占空比、周期(占空比=高电平/周期)
(二)蜂鸣器
蜂鸣器:
有源蜂鸣器(只要通上电内部存在震荡电路)
无源蜂鸣器(内部无震荡电路,只有不断通电断电震荡)
注:源不是指电源而是指震荡源
1、原理图
2、代码:通过按键实现蜂鸣器发出响声
main.c
#include <reg52.h>
#include "timer.h"
#include "led.h"
#include "key.h"
#define HZ200 63231 //200赫兹
#define HZ400 64383
#define HZ600 64768
#define HZ800 64959
int main(void)
{
init_led();
init_timer0();
while(1)
{
int key = key_pressed();
if(key == 1)
{
g_n = HZ200;
}
else if(key == 2)
{
g_n = HZ400;
}
else if(key == 3)
{
g_n = HZ600;
}
else if(key == 4)
{
g_n = HZ800;
}
}
}
timer.c
#include <reg52.h>
#include "timer.h"
#include "led.h"
#define HZ200 63231 //200赫兹
#define HZ400 64383
#define HZ600 64768
#define HZ800 64959
unsigned int g_n;
void timer0_handler(void) interrupt 1
{
TH0 = g_n>>8;
TL0 = g_n;
P2 ^= (1 << 1);
/*
++g_n;
if(g_n >= 1000) //1000毫秒为1秒一闪,可改为500毫秒
{
led_all_nor();
g_n = 0;
}
*/
}
void init_timer0(void)
{
TMOD &= ~(0X0F <<0);
TMOD |= (1<<0);
TH0 = g_n>>8;
TL0 = g_n;
TCON |= (1<<4);
IE |= (1<<7) | (1<<1);
}