目录
一、设计内容
二、中断相关知识
1、51单片机中断源
2、中断系统特殊功能寄存器
3、中断函数与函数调用区别
三、仿真原理图
四、程序设计
五、仿真结果
六、思考题
作者有话说
一、设计内容
本次设计使用2个按键,在无按键按下时,最下面一位发光二极管点亮;当KEY1按下,外部中断0请求中断,控制发光二极管从下到上循环点亮3圈;当KEY2按下,外部中断1请求中断,控制发光二极管闪烁3次。(要求外部中断1优先级高于外部中断0,即KEY2按下后能够打断流水灯的动作,当外中断1处理完后,恢复外中断0的处理,并且能从上次打断的那个LED开始循环)。
二、中断相关知识
1、51单片机中断源
中断源 | 中断号 | 入口地址 |
外部中断0 | 0 | 0003H |
外部中断1 | 2 | 0013H |
定时器T0 | 1 | 000BH |
定时器T1 | 3 | 001BH |
串口中断 | 4 | 0023H |
2、中断系统特殊功能寄存器
中断允许寄存器IE、定时器/计数器T0/T1控制寄存器TCON、定时器/计数器T2控制寄存器T2CON 、串口控制寄存器SCON
3、中断函数与函数调用区别
中断函数不能有返回值、中断函数不能传递参数、中断函数程序应该短小精悍
三、仿真原理图
四、程序设计
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 外部中断
* 创作者 : 薄情书生
* 创作时间 : 2022.9.27
*******************************************************************************/
main.c文件
#include "reg52.h"
#include "led.h"
#include "exit.h"
/*************38译码器**************/
void SelectHC138(unsigned char channel)
{
switch(channel)
{
case 0:
P1 = (P1 & 0x1f)|0x00;break; //发光二极管(LEDS0)
}
}
/*************主函数******************/
void main()
{
SelectHC138(0);
Exint_Init();
while(1)
{
P0 = 0x7f;
}
}
delay.c文件
#include "delay.h"
/*********毫秒延时*********/
void delay_ms(u16 ms)
{
u16 x,y;
for(x=ms;x>0;x--)
for(y=114;y>0;y--);
}
led.c文件
#include "led.h"
#include "reg52.h"
#include "delay.h"
#include "intrins.h"
/*************LED由下至上**************/
void Bottom_Up()
{
u8 i,j;
for(j=0;j<3;j++)
{
for(i=0,P0 = 0xff;i<8;i++)
{
P0 = P0<<1;
delay_ms(200);
}
}
P0 = 0xff;
}
/*************LED由上至下**************/
void Up_Bottom()
{
u8 i,j;
for(j=0;j<3;j++)
{
for(i=0,P0 = 0xff;i<8;i++)
{
P0 = P0>>1;
delay_ms(100);
}
}
P0 = 0xff;
}
/*************LED齐闪烁**************/
void LED_twinkle()
{
u8 i,j;
for(j=0;j<3;j++)
{
for(i=0,P0 = 0x00;i<3;i++)
{
P0 = ~P0;
delay_ms(500);
}
}
P0 = 0xff;
}
/*************LED保持3s**************/
void Hold_3s()
{
P0 = 0x00;
delay_ms(3000);
P0 = 0xff;
}
/*************两边至中间**************/
void LED_sides()
{
u8 i,j,ri,lf;
for(j=0;j<3;j++)
{
for(i=0,ri=0x7f,lf=0xfe;i<4;i++)
{
P0 = ri&lf;
ri = _cror_(ri,1);
lf = _crol_(lf,1);
delay_ms(1000);
}
}
P0 = 0xff;
}
/*************中间至两边**************/
void LED_middle()
{
u8 i,j,ri,lf;
for(j=0;j<3;j++)
{
for(i=0,ri=0xef,lf=0xf7;i<4;i++)
{
P0 = ri&lf;
ri = _crol_(ri,1);
lf = _cror_(lf,1);
delay_ms(1000);
}
}
P0=0xff;
}
exit.c文件
#include "exit.h"
#include "reg52.h"
#include "led.h"
/*********外部中断0、1初始化***********/
void Exint_Init()
{
IT0 = 0;
IT1 = 0;
PX0 = 0;
PX1 = 1;
EA = 1;
EX0 = 1;
EX1 = 1;
}
/*********外部中断0服务函数***********/
void Exint0_Service() interrupt 0
{
Up_Bottom();
}
/*********外部中断1服务函数***********/
void Exint1_Service() interrupt 2
{
LED_twinkle();
}
五、仿真结果
无按键按下时,最下面一位发光二极管点亮。
KEY1按下,外部中断0请求中断,控制发光二极管从下到上循环点亮3圈。
KEY2按下,外部中断1请求中断,控制发光二极管闪烁3次。
KEY2按下后能够打断KEY1流水灯的动作,当外中断1处理完后,恢复外中断0的处理,并且能从上次打断的那个LED开始循环。
六、思考题
请修改程序,将INT0和INT1的优先级都设置成0,先按下KEY2,在LED的闪烁过程中按下KEY1,看能否打断LED的闪烁?原因是什么?思考题参考程序将在设计三:51单片机数码管显示控制给出。
作者有话说
本专栏为51单片机实战教程,旨在以练促学,帮助小伙伴快速入门51单片机,学习51单片机相应理论知识请自行学习。本次设计涉及的相关理论知识:51单片机外部中断控制、独立按键的使用、模块化编程,请自行参考资料学习。
本次设计源程序及仿真源文件百度网盘链接:链接:https://pan.baidu.com/s/1TNwn74gbOoMzb3Wcqopvrg
提取码:vga5
设计一:51单片机控制流水灯思考题参考源程序及仿真源文件百度网盘链接:https://pan.baidu.com/s/1bdtvHcNLI8ydR_t94DWQXw
提取码:gnv6