200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > AVR16单片机--外部中断实验

AVR16单片机--外部中断实验

时间:2023-08-16 13:05:58

相关推荐

AVR16单片机--外部中断实验

一、实验目的

1. 理解单片机中断的概念。

2. 掌握外部中断的编程方法。

二、实验内容

1. 验证课堂例题

编译下载运行课堂例题——“按键次数显示”(INT_EX1)和“按键次数显示清零”(INT_EX2),查看运行结果。理解程序的编程思想和程序执行过程。

2. 设计程序

参考上述例题的电路和编程思路,自行设计电路,包括三个按键K1、K2和K3,分别连接外部中断INT0-INT2,6位数码管显示,1个LED报警灯;编程实现K1按键次数的显示,显示数据清零和次数越限报警等功能。

具体要求如下:

(1)初始状态下,数码管显示“200000”,其中后两位用于K1按键次数显示,前两位用于当前按键次数报警阈值显示(报警阈值初始为20);

(2)每当K1按下时,后两位数码管显示K1按下次数,计数到报警阈值时不再进行累加;

(3)当计数超过当前设置的报警阈值时,LED进行点亮报警,此时再按下K1不再进行计数;

(4)K2按下时,显示计数值清零并且LED熄灭,即解除报警。

(5)K3每按下一次,按键次数报警阈值在20、15、10、5间进行循环转换,并在数码管前两位进行当前报警阈值的显示,并且显示计数归零。

在设计报告中,需进行总体设计思路描述,给出所涉及到的主程序、中断程序、关键功能子函数的流程图和设计代码。描述程序调试结果及出现的问题。

三、实验结果

1. 在下方贴出使用Proteus绘制的电路原理图。

2. 描述所设计程序的总体设计思路(包括根据任务划分的程序顶层结构、各任务的设计思路、各任务间的数据传递,如何解决关键问题等)

总体思路:初始化IO口,配置中断,数码管初始化,编写中断函数INT0通过K1控制按键计数、中断函数INT1通过K2控制数码管后两位清零、中断函数INT2通过K3切换阈值并使数码管后两位清零。

3.根据所设计的程序顶层结构,对主函数、中断函数(如果没有使用中断可不写)、关键功能子函数的设计思路进行简单描述,并给出各函数的流程图(用Visio画)

主函数main():初始化各个IO口,打开总中断,不断调用LED显示函数。

LEDshow():进行从0到5的for(i)循环,,进行数码管位选选择第i个数码管,进行数码管段选显示数组LEDBuf[i]。

Increase_INT0_Ir():K1按下数码管最后一位加1,直到达到设定的阈值,到达阈值后计数不再增加并且点亮LED。

Increase_INT1_Ir():数码管后两位计数值清零并且LED熄灭。

Increase_INT2_Ir():切换阈值并且数码管清零。

4. 给出(3)中相关函数的实现代码(在ICCAVR中进行编程,以截屏贴图方式放入实验报告中,注意规范性,必须加注释)

#include <iom16v.h>

#include <macros.h>

#define uchar unsigned char

#define uint unsigned int

uchar LEDBuf[6]={2,0,0,0,0,0};//存放数码管显示数据,0-9数字格式

uint j=0;

//延时函数

void delay(uint ms)//延时函数

{

uint p,q;

for(p=0;p<ms;p++)

{

for(q=0;q<1141;q++);

}

}

//系统初始化

void Init(void)

{

DDRA|=BIT(PA0); //PA0设置为输出状态

DDRA|=BIT(PA3); //PA3设置为输出状态

DDRA|=BIT(PA4); //PA4设置为输出状态

DDRB=0xFB; //K3按键设置为输入端口

PORTB = 0XFF; //使能上拉电阻

DDRC=0xFF; //PC口设置为输出状态

DDRD = 0X00; //K1 K2按键设置为输入端口

PORTD = 0XFF; //使能上拉电阻

MCUCR=0x0A; //下降沿INT0,下降沿INT1

MCUCSR=0x00;

GICR|=0b11100000; //允许INT0、INT1、INT2

}

//6位共阴极数码管

uchar const DuanXuan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//0~9

uchar const WeiXuan[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};//从左到右第0-5位数码管

//数码管显示函数

//数码管从左到右刷新一次

//0-5位数码管显示数据放在LEDBuf[]中,存放0-9数字格式

void LEDshow(uchar LEDBuf[6])

{

uchar i;

for(i=0;i<6;i++)//循环扫描一次

{

PORTC=WeiXuan[i];//选择第i位数码管

PORTA|=BIT(PA4);//PA4输出高电平,位选端拉高

//delay(1);

PORTA&=~BIT(PA4);//PA4输出低电平,位选端拉低,位选锁存

PORTC=DuanXuan[LEDBuf[i]]; //输出段选

PORTA|=BIT(PA3); //PA3输出高电平,段选端拉高

//delay(1);

PORTA&=~BIT(PA3);//PA3输出低电平,段选端拉低,段选锁存

delay(1);

}

}

void main(void)

{

uchar i;

Init(); //调用IO初始化函数

SREG|=0x80; //开总中断

while(1)

{

LEDshow(LEDBuf);//调用数码管显示函数

delay(1);

}

}

#pragma interrupt_handler Increase_INT0_Ir:2

void Increase_INT0_Ir(void)

{

if(LEDBuf[5]==LEDBuf[1]&&LEDBuf[4]==LEDBuf[0])

{

PORTA|=0x01; //打开LED

return;

}

LEDBuf[5]++;

if(LEDBuf[5]==10)

{

LEDBuf[5]=0;

LEDBuf[4]++;

if(LEDBuf[4]==10)

{

LEDBuf[4]=0;

}

}

}

#pragma interrupt_handler Increase_INT1_Ir:3

void Increase_INT1_Ir(void)

{

uchar i;

for(i=4;i<6;i++)

{

LEDBuf[i]=0; //后两位清零

PORTA&=0xFE; //关闭LED

}

}

#pragma interrupt_handler Increase_INT2_Ir:19

void Increase_INT2_Ir(void)

{

j++;

switch(j)

{

case 1:

LEDBuf[0]=1,LEDBuf[1]=5;

LEDBuf[4]=0,LEDBuf[5]=0;

break;

case 2:

LEDBuf[0]=1,LEDBuf[1]=0;

LEDBuf[4]=0,LEDBuf[5]=0;

break;

case 3:

LEDBuf[0]=0,LEDBuf[1]=5;

LEDBuf[4]=0,LEDBuf[5]=0;

break;

case 4:

LEDBuf[0]=2,LEDBuf[1]=0;

LEDBuf[4]=0,LEDBuf[5]=0;

break;

}

if(j==4)

{

j=0;

}

return;

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。