北邮小学期AVR单片机模拟电梯系统实验报告副本Word格式文档下载.docx
《北邮小学期AVR单片机模拟电梯系统实验报告副本Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《北邮小学期AVR单片机模拟电梯系统实验报告副本Word格式文档下载.docx(36页珍藏版)》请在冰点文库上搜索。
我们小组一共练习了3个工程:
流水灯、按键蜂鸣器和秒表计时器,学会了使用AVRstudio工作环境和WINAVR(GCC)编译器,并在板子上写入程序。
学会了I/O端口初始化、输入输出操作,通过端口控制LED序列、8段数码管、蜂鸣器,中断和定时的使用。
2.1流水灯
2.1.1功能
学会I/O端口的初始化及通过端口控制LED,使得LED呈现流水灯效果,我们小组用的PB端口作为控制LED的端口,并且由于人眼频率和单片机频率的关系加了延迟函数,使得流水灯每个状态保持1s
2.1.2程序代码
#include<
avr/io.h>
intmain(void)
{
chartemp;
//用来存储当前A端口的输出
unsignedinti,k;
//循环变量
DDRA=0xff;
//将A端口设为输出
PORTA=0b00000001;
//初始化A端口,从接入PA0的LED灯亮
while
(1)
{
temp=PORTA;
PORTA=PORTA<
<
1;
if(temp&
0b10000000)//若接入7的LED灯亮
{
PORTA=PORTA|0b00000001;
//则点亮接入PA0的LED灯
}//即实现流水灯循环
for(i=0;
i<
50;
i++)//延时,约1秒钟
for(k=0;
k<
1000;
k++);
}
}
}
2.2蜂鸣器/按键蜂鸣器
2.2.1功能
按键蜂鸣器主要为了了解按键的使用,并且学会中断的应用
2.2.2程序代码
蜂鸣器:
{
DDRB|=(1<
3);
//对B端口的设置,使得PD3设置为输出
PORTB&
=~(1<
//初始时蜂鸣器不响
while
(1)
PORTB^=(1<
//设置蜂鸣器每隔约一秒响一次
i++)
按键蜂鸣器:
#include<
DDRA&
6);
//按钮6的设置
PORTA|=(1<
7);
//按钮7的设置
2);
//按钮2的设置
//按钮3的设置
DDRB|=(1<
//蜂鸣器输出
DDRD=0xff;
//灯的输出
switch(PINA&
0b11001100)
case0b11001100:
//K1被按下
{
PORTD|=(1<
0);
//LED0发光
break;
}
case0b11000000:
//K2被按下
1);
//LED1发光
case0b10001000:
//K3被按下
//LED2发光
case0b01001000:
//K4被按下
PORTB|=(1<
//蜂鸣器鸣响
default:
PORTB&
//关蜂鸣器
PORTD=0;
//关灯
2.3秒表计时器
2.3.1功能
利用两位数码管,实现秒表计时的功能
2.3.2程序代码
avr/interrupt.h>
inttable[]=//显示0—9的数组
0x3f,
0x06,
0x5b,
0x4f,
0x66,
0x6d,
0x7d,
0x07,
0x7f,
0x6f};
DDRB=0xff;
DDRD=0b11110111;
PORTD=(1<
//设置中断
PORTB=0b00001000;
MCUCR|=(1<
ISC11);
//设置INT1下降沿触发中断
GICR|=(1<
INT1);
sei();
unsignedinti,j,k,x,y;
unsignedchartemp;
TCCR0|=(1<
CS01);
60;
x=i/10,y=i%10;
//x为十位数,y为个位数
PORTD=table[x];
//接入PD口的数码管显示十位数
PORTB=table[y];
//接入PB口的数码管显示个位数
temp=PORTA;
//流水灯的显示
PORTA=PORTA<
1;
if(temp&
(1<
7))
PORTA|=1;
TCNT0=55;
3;
k++)//延时
for(j=0;
j<
10000;
j++)
while(!
(TIFR&
TOV0)));
TCNT0=55;
SIGNAL(SIG_INTERRUPT1)//中断程序
{intm=0;
{if(PIND&
2))
{delay(10);
while
(1)
m++;
if(!
(PIND&
2)))
break;
delay(500);
if(m==2)
delay(100);
break;
2.4流水灯与60秒秒表计时器
2.4.1功能
学会I/O端口的初始化及通过端口控制LED,使得LED呈现流水灯效果,此外,利用两个数码管,实现60秒秒表计时功能,可随时停止。
2.4.2程序代码
charTEMP;
//将B端口设为输出
PORTB=0b11001100;
//初始化B端口,最开始第一个灯亮
while
(1)//主循环
TEMP=PORTB;
PORTB=PORTB<
if(TEMP&
0b10000000)
PORTB=PORTB|0b00000001;
for(i=0;
100;
for(j=0;
j++);
charnum[10]=
{
0b00111111,//0
0b00000110,//1
0b01011011,//2
0b01001111,//3
0b01100110,//4
0b01101101,//5
0b01111101,//6
0b00000111,//7
0b01111111,//8
0b01101111,//9
};
charshuma[10]=
0b10111111,
0b10000110,
0b01011111,
0b11001111,
0b11100110,
0b11101111,
0b11111101,
0b10000111,
0b11111111,
};
unsignedinta=0,tag=0;
unsignedinti,j;
PORTA=0b10001100;
DDRC&
PORTC|=(1<
DDRD|=(1<
7)|(0<
PORTC&
//关数码管
TCNT0=55;
TCCR0|=(1<
CS01);
//八分频
//DDRD=0xff;
DDRA|=0xf0;
TCNT0=55;
PORTD|=(1<
MCUCR|=(1<
ISC01)|(0<
ISC00);
GICR|=(1<
INT0);
sei();
{
/*if(PINC&
(1<
7))//按键没被按下
if(a==9)
tag=(tag+1)%6;
a=(a+1)%10;
PORTD=num[a];
PORTB=num[tag];
Else//按键按下
PORTD=PORTD;
//保持原状态
PORTB=PORTB;
}*/
PORTA=0b11000000;
temp=PORTA;
0b10000000)//使最后一个等亮起后,又从第一个亮起
PORTA=PORTA|0b00000001;
for(i=0;
i<
50000;
i++)
(1<
TOV0)));
SIGNAL(SIG_INTERRUPT0)//中断程序
PORTA=0xff;
for(intp=0;
p<
10000;
p++)
while(!
(~(PORTD|0b11111011)))
3.设计过程
3.1设计流程
(1)了解AVR单片机原理及编程规则.
(2)编写代码,然后接好电路,下载到单片机测试
(3)所有部分完成后,进行整体测试,有错的话继续整改,无错直接下载测试
3.2实验元器件
Atmeal16单片机1块
JTAG下载器1个
4X4矩阵键盘1块
电机1个
蜂鸣器1个
数码显示管1个
导线若干
3.3实验程序主要流程图
运行结果及组员分工:
申宇飞:
主要负责模拟电梯系统程序的编写
徐萌扬:
主要负责硬件的连接和实物的制作
3.4实验原理及原理图
3.4.1实验原理
单片机识别按键按下的是哪个键,随之进行判断,如果需要进行移动,则驱动电机,在到达指定的楼层后停止,期间可以不断扫描输入,不断更新路线,被按下楼层有指示灯显示,到达该楼层后灯灭掉,蜂鸣器响一下。
在电梯运动同时到达相应楼层时,数码管显示当前楼层,用红色和绿色发光二极管组成的箭头来指示电梯当前是处于上升状态还是下降状态。
此外,如果按下按键,还可以实现电梯的紧急停止和恢复启动。
3.4.2原理图
3.4.3.1中央处理器MCU
中央处理器
中央处理器用的是ATMega16,如图所示。
PA0~PA7用于连接键盘输入,PC0驱动蜂鸣器,PC1和PC7口设置为电机接入端口,PB0~PB7用于连接数码管显示器,PD2设置为中断按键,PD3~PD7为LED灯阵。
当PC1输出高电平PC7输出低电平时,电动机逆时针旋转;
反之,电动机顺时针旋转。
由此实现电梯上下行功能。
3.4.3.24x4键盘
图3
键盘与接PB口连接,见图3。
键盘的工作原理:
按键设置在行、列线交点上,行、列线分别连接到按键开关的两端。
行线通过上拉电阻接到+5V电源上。
无按键按下时,行线处于高电平的状态,而当有按键按下时,行线电平与此行线相连的列线电平决定。
将行列线值组合后即得到一个两位为0六位为1的八位二进制数。
由此八位二进制数即可确定按键并设置相应数值。
4.程序源代码及程序分析
5.#include<
avr/signal.h>
util/delay.h>
#defineucharunsignedchar
#defineuintunsignedint
intw_counter=0,d_counter=0;
//计数按键次数
intdirection;
//标志上下坡
intfloor_now=1;
//当前楼层号
intfloor_go=0;
//紧接着要去的楼层号
intfloor_wait[6]={0,0,0,0,0,0};
//有人等着的楼层号
intfloor_des[6]={0,0,0,0,0,0};
//目的楼层号
ucharkey,key_temp;
//键盘输入;
存key以判断输入
chardata[10]=
0b00111111,//0
0b00000110,//1
0b01011011,//2
0b01001111,//3
0b01100110,//4
0b01101101,//5
0b01111101,//6
0b00000111,//7
0b01111111,//8
0b01101111,//9
voidalarm();
//蜂鸣器控制函数
voidlight(intdirection);
//上下行亮灯函数
voidkeyscan()//4*4键盘的扫描
ucharcord_h,cord_l,cord;
DDRB=0x0f;
PORTB=0xf0;
//行线输出全为0
delay
(1);
cord_h=PINB&
0xf0;
//读入行线值
if(cord_h!
=0xf0)//先检测有无按键按下
//delay(10);
//去抖
if(cord_h!
=0xf0)
DDRB=0xf0;
PORTB=0x0f;
//输出当前列线值
delay
(1);
cord_l=PINB&
0x0f;
//读入列线值
cord=cord_l|cord_h;
//键盘最后组合码值
switch(cord)
case0b11101110:
floor_wait[1]=1;
PORTD|=0b00000001;
//1外部
case0b11011110:
floor_wait[2]=2;
PORTD|=0b00000010;
//2
case0b10111110:
floor_wait[3]=3;
PORTD|=0b00000100;
//3
case0b01111110:
floor_wait[4]=4;
PORTD|=0b00001000;
//4
case0b11101101:
floor_wait[5]=5;
PORTD|=0b00010000;
//5
case0b11011101:
floor_wait[0]=6;
PORTD|=0b00100000;
//6
case0b10111011:
floor_des[1]=1;
//1内部
case0b01111011:
floor_des[2]=2;
case0b11100111:
floor_des[3]=3;
case0b11010111:
floor_des[4]=4;
case0b10110111:
floor_des[5]=5;
case0b01110111:
floor_des[0]=6;
//6
break;
//键盘对应的楼层号的设置,记录等待楼层号
voiddelay(intms)//延时函数
inti,j;
ms;
for(j=0;
111;
voidtoNext(intfn,intfg)//去往下一次
intdis=fn-fg;
//floor_now=fg;
PORTA=data[floor_now];
if((dis==0)||(fg==0))
PORTD&
=0b00111111;
elseif(dis>
0)//去的楼在当前楼的下面
direction=0;
downstair(dis);
elseif(dis<
0)//去的楼在当前楼的上面
direction=1;
upstair(-dis);
voidupstair(intdis)//上楼
light
(2);
intdiv=abs(dis);
light(direction);
while(div>
0)
clean(floor_now,floor_wait,floor_des);
for(intk=0;
6;
k++)
if((floor_des[k]!
=0)||(floor_wait[k]!
=0))
if(k==0){PORTD|=0b00100000;
else{PORTD|=(1<
(k-1));
else
if(k==0){PORTD&
=0b11011111;
else{PORTD&
=~(1<
PORTD|=0b10000000;
=0b10111111;
for(inti=0;
1500;
keyscan();
if(!
(PINC&
0b00000010))//按下
{
while(!
0b00000010))
{
PORTD&
alarm();
}
PORTD&
PORTD|=0b10000000;
break;
}
PORTD|=0b10000000;
//if(PINC&
0b00000010)
//{PORTD&
div--;
floor_now++;
PORTA=data[floor_now];
//clean(floor_now,floor_wait,floor_des);
if((floor_wait[floor_now]!
=0)||(floor_des[floor_now]!
PORTD&
alarm();
delay(500);
clean(floor_now,floor_wait,floor_des);
clean(floor