ATmega16(AVR)单片机外部中断实验

注意:本实验题目取自课后实验,由于近期白嫖抄作业等现象时有发生,所以作者在代码中做出微小改动(错误),希望读者读懂代码后自行修改

                            实验三  外部中断实验

一、实验目的

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口。

实验相对简单,不做过多赘述,有任何问题欢迎私信交流

原理图连线

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值