注意:本实验题目取自课后实验,由于近期白嫖抄作业等现象时有发生,所以作者在代码中做出微小改动(错误),希望读者读懂代码后自行修改
实验三 外部中断实验
一、实验目的
1. 理解单片机中断的概念。
2. 掌握外部中断的编程方法。
二、实验内容
1. 验证课堂例题
编译下载运行课堂例题,查看运行结果。理解程序的编程思想和程序执行过程。
2. 设计程序
参考上述例题的电路和编程思路,自行设计电路,包括三个按键K1、K3和K4(其中:K1键使用查询方式;K2和K3分别使用外部中断INT0和INT1),4(或6)位数码管显示,1个LED报警灯;编程实现K1按键次数的显示,显示数据清零和次数越限报警等功能。
具体要求如下:
(1)初始状态下,数码管显示“5 0”,其中右边用于K1按键次数显示,左边用于当前按键次数报警阈值显示(报警阈值初始为5),其它位不显示;
(2)每当K1按下时,后两位数码管显示K1按下次数,计数到报警阈值时不再进行累加;
(3)当计数等于当前设置的报警阈值后继续按键,LED进行点亮报警,此时再按下K1不再进行计数;
(4)K2按下时,显示计数值清零并且LED熄灭,即解除报警。
(5)K3每按下一次,按键次数报警阈值在20、15、10、5间进行循环转换,并在数码管左侧进行当前报警阈值的显示,并且显示计数归零。
在设计报告中,需进行总体设计思路描述,给出所涉及到的主程序、中断程序、关键功能子函数的流程图和设计代码。描述程序调试结果及出现的问题。
源代码
#include <iom16v.h>
#include <macros.h>
#define uchar unsigned char
#define uint unsigned int
void delay(uint time)//延时
{
uint ii,iii;
for(ii=0;ii<time;ii++)
{
for(iii=0;iii<time;iii++);
}
}
uchar shumaguan[11]={0x03,0x9f,0x25,0x0c,0x98,0x48,0x40,0x1e,0x00,0x08,0xff};///定义数码管显示数组,分别对应0~9
数码管显示函数
void shownumber(uint a,uint b,uint c,uint d,uint e,uint f)///a~f分别控制数码管的6位
{
uint z;
uint iio,jj;
DDRA=0xff;///数码管位选
for(iio=0;iio<200;iio++)///加一段时间延时,以防止短时间内多次检测到按键
{
for(z=0;z<30;z++)//
{
PORTC=0x02;
PORTA=shumaguan[a];
}
for(z=0;z<55;z++)///
{
PORTC=0x04;
PORTA=shumaguan[b];
}
for(z=0;z<55;z++)///
{
PORTC=0x08;
PORTA=shumaguan[c];
}
for(z=0;z<55;z++)///
{
PORTC=0x10;
PORTA=shumaguan[d];
}
for(z=0;z<55;z++)///
{
PORTC=0x20;
PORTA=shumaguan[e];
}
for(z=0;z<29;z++)///最后一位显示的数字
{
PORTC=0x40;
PORTA=shumaguan[f];
}
}
}
uchar yuzhi=5;///阈值初值为5
uint v=10;
uint q,p,cnm,sb;///数码管显示
void main(void)
{
DDRB=0xff;B口输出
PORTB=0xff;//初始状态为全高电平,led不亮
DDRC=0xff;///C口数码管位选
DDRD &=0x00;///PD输入
PORTD |=0xff;//PD上拉输入
// PORTC=0x00;
MCUCR |=0x02;//下降沿触发
GICR |=0xe0;//开
SREG |=0x80;//打开全局中断
p=5;///初始状态数码管显示5 0
cnm=10;
q=0;
sb=0;///计数归零
while(1)
{
shownumber(p,v,10,10,cnm,q);
if(PIND==0xfe)///判断k1是否按下
{
delay(30);
if(PIND==0xfe)
{
if(sb<=yuzhi)判断按键按下次数小于阈值时执行计数
{
sb++;
if(sb>=yuzhi)
{
q=(int)(yuzhi%10);
cnm=(yuzhi/10);///当按键次数达到阈值,数码管显示的数字不再改变
}
else
{
q=(int)(sb%10)-1;
cnm=(sb/10);
}
}
else
{}
if(sb>yuzhi)判断按键按下次数是否大于阈值
{
sb=yuzhi;
q=(int)(yuzhi%10)-1;
cnm=(yuzhi/10);
PORTB=0x7e;led亮起
}
else
{}
}
else
{}
}
else///k1键没有按动,执行当前流水灯
{}
}
}
#pragma interrupt_handler int0_isr:2
void int0_isr(void)///中断0
{
q=0;///数码管显示清零
sb=0;///清零
PORTB=0xff;
}
#pragma interrupt_handler int1_isr:iv_INT1
void int1_isr(void)
{
if(yuzhi==5)//改变阈值
{
yuzhi=20;
p=2;
v=0;
}
else if(yuzhi==20)
{
yuzhi=15;
p=1;
v=6;
}
else if(yuzhi==15)
{
yuzhi=10;
p=1;
v=0;
}
else
{
yuzhi=5;
p=5;
v=10;
}
sb=0;
cnm=0;
q=0;
}
实验中,数码管采用6位共阳极数码管,报警灯接入PB7口。
实验相对简单,不做过多赘述,有任何问题欢迎私信交流
原理图连线