delay_ms(300);}
PORTC=0XFF;
PORTD=0XFF;
///////////////////////////
for(t=0;t<9;t++)
{PORTD=0XFF>>t;
PORTC=0XFF>>t;
delay_ms(300);}
PORTD=0XFF;
PORTC=0XFF;
for(t=0;t<5;t++)
{
PORTD=dataa[t];
delay_ms(300);}
PORTC=0XFF;
PORTD=0XFF;
for(t=5;t<0XFF;t--)
{
PORTC=~dataa[t];
delay_ms(300);}
PORTC=0XFF;
PORTD=0XFF;
}
}
四、实验指导
打开CodeVisionAVR开发编程软件,新建一个工程文件框架,参照上述程序清单或根据实验要求自己重新修改设置并输入程序。
在程序设计过程中须将ATmegal6的PC口设置为输出。
编译之前先将调试码设置成外部调试码,方法是按下工具栏中的configuretheproject命令,出现一个对话框,再按下ccompiler按钮,在对话框的左上角选择芯片型号和时钟频率,在右下角将文件输出格式设置为外部调试码(即选择OBJROMHEXEEP)。
将所输入的程序进行编译(菜单Project→Make命令),或者在工具栏单击Make按钮),若编译时未生成可执行文件*.hex,说明程序有语法错误,此时必须根据编译器所列出的错误消息,逐条查改,重新编译,直到错误消除并生成*.hex文件。
打开下载程序,将刚刚生成的相应*.hex文件写入单片机(在此之前,须将单片机实验板按要求与PC机连接正确,单片机实训装置接通电源)。
按复位键RESET,观察实验结果。
五、实验扩展
由于本实训装置将ATmegal6的4个I/O口PA、PB、PC和PD的引脚,全部引出且作为独立的端口使用,所以本实验除了可以用PC口和PD口外,PA和PB口都可作为“彩灯”的控制口。
(1)仿照LED与PC和PD口的相连,分别将ATmegal6的PA和PB口作为作为“彩灯”的控制口,重新编写程序、编译并写入实训装置,观察实验结果。
(2)改变延时时间即改变语句delay_ms(300),控制“彩灯”的循环速度。
(3)改变“彩灯”的循环方向。
(4)自行设计“彩灯”的点亮方式及循环方式,观察实验结果。
实验三键控加减计数
一、实验目的与任务
1.实验目的
⑴掌握按键消抖的几种方法;
⑵熟悉并行接口的设置与应用;
⑶进一步熟悉编译软件和下载软件的使用;
⑷熟悉C语言中if、while语句的应用;
2.实验任务
采用PD口的8个发光二极管以“亮1灭0”的方式显示一个8位的二进制数,PC口按键AN7每按下一次,PD口显示的二进制数加1,PC口按键AN0每按下一次,PD口显示的二进制数减1。
二、实验接线图与条件
电路如图13所示。
实验前,用扁平连接线将按钮开关接口与PC接口连接起来,用扁平连接线将LED发光管接口与PD接口相连起来。
图9键控计数电路
实验要求是PC口设置为输入,并且是内部上拉;PD口设置为输出。
三、实验原理
电路中,按钮不按下时,在内部上拉电阻的作用下,PC口为高电平。
按钮按下时,引脚与地短接,PC口相应的该位为低电平。
通常按键所用开关为机械弹性开关,均利用了机械触点的合、断作用,一个电压信号通过机械触点断开、闭合过程的波形如图14所示。
图10按键抖动波形
由于机械触点的弹性作用,一个按钮开关在按下时不会马上稳定地接通,在松手时不会一下子断开。
而是在闭合和断开的瞬间伴随有一连串的抖动,抖动的时间一般为5~10ms。
按键有断开、下按、接通和释放四种情况,对应为高电平、高电平向低电平变化、低电平、低电平向高电平变化四种状态。
每按一次键都要经历这四种状态,检查是否按了一次键,可以检查高电平向低电平变化或者检查低电平向高电平变化。
检查高电平向低电平变化的方法是:
上次检查为高电平,本次检查为低电平,则表示键已按下。
检查低电平向高电平变化的方法是:
上次检查如果为低电平,本次检查为高电平,则表示键已释放。
也可以通过延时来实现消除按键抖动,具体的方法是如果按键按下值为0,延时2ms,跳过前沿抖动,然后执行相关程序。
If(PINC.0==0){while(PINC.0==0)delay_ms
(2);…}
此外还有一些其它方法可以消除抖动:
⑴程序等待按后通过:
while(PINC.0==0);⑵按住时等待或执行预定程序:
while(PINC.0==0){…};⑶按一键后执行预定程序:
If(PINC.0==0)while
(1){…}。
四、实验参考程序
#include
#include
voidmain(void)
{
PORTC=0xff;
DDRC=0x00;
PORTD=0xff;
DDRD=0xff;
while
(1)
{
if(PINC.7==0){while(PINC.7==0)delay_ms
(2);PORTD--;}
}}
五、实验延伸扩展
给出的参考程序是判断键的“按下”时,进行加、减计数的,若将程序改为判断按键“释放”时,加、减计数。
修改程序并调试,观察实验结果。
实验四外部中断的使用
一、实验目的与任务
1.实验目的
⑴掌握外部中断的工作原理,熟悉外部中断的设置与使用;
⑵会用C-AVR的代码生成器生成外中断的基本框架文件,能正确解读框架文件中关于外中断寄存器功能设置的语句。
⑶了解CPU对中断请求的响应过程,会正确修改框架文件实现外中断的命题要求。
⑷进一步熟悉位操作命令;
2.实验任务
任务一:
上电后8只发光管灭,按下外部中断0时,发光管高4位亮;按下外部中断1时,发光管低4位亮。
任务二:
上电后8只发光管灭,按下外部中断0时,发光管单一右移点亮;按下外部中断1时,发光管单一左移点亮。
二、实验原理
Atmega16有3个外部中断源INT0、INT1和INT2,分别对应PD2、PD3和PB2。
外部中断的原理如图15所示。
CPU要实现中断的响应,首先合上中断控制总开关和分开关,其次设置中断触发方式等,然后按要求编制中断服务子程序。
图11外部中断原理图
三、实验接线
在实训装置上,将PD口与按钮开关的接口用扁平线相连,将PC口与LED接口用扁平线相连。
要求PD口设置为输入,并且上拉;PC口设置为输出。
四、实验参考程序
程序一:
#include
interrupt[EXT_INT0]voidext_int0_isr(void)
{PORTC=0X0F;}
interrupt[EXT_INT1]voidext_int1_isr(void)
{PORTC=0XF0;}
voidmain(void)
{//I/O口的设置
PORTC=0xFF;
DDRC=0xFF;
PORTD=0xFF;
DDRD=0x00;
//中断的初始化设置
GICR|=0xC0;
MCUCR=0x0F;
MCUCSR=0x00;
GIFR=0xC0;
#asm("sei")
while
(1)
}
程序二:
#include
#include
bitk1,k2;//设置全局位变量
interrupt[EXT_INT0]voidext_int0_isr(void)
{k1=1,k2=0;}
interrupt[EXT_INT1]voidext_int1_isr(void)
{k1=0,k2=1;}
voidmain(void)
{chari;
//I/O口的设置
PORTC=0xFF;
DDRC=0xFF;
PORTD=0xFF;
DDRD=0x00;
//中断的初始化设置
GICR|=0xC0;
MCUCR=0x0F;
MCUCSR=0x00;
GIFR=0xC0;
#asm("sei")
while
(1)
{
while(k1)for(i=0;i<8;i++){PORTC=~(0X80>>i);delay_ms(200);}
while(k2)for(i=0;i<8;i++){PORTC=~(1<
};
}
五、实验指导
中断服务子程序框架的生成和初始化设置可以通过新建工程文件来建立。
具体的操作是:
新建→工程文件→选择芯片→选择外部中断按钮→先选中断0、设置触发模式为上升沿有效→再选中断1、设置触发模式为上升沿有效→点击菜单上的文件、选中程序阅览→产生中断服务子程序框架→选中该程序→复制→粘贴到C编译软件工程文件下→适当地修改,编译、调试即可。
实现任务二时,注意变量k1,k2必须是全局位变量。
PD口必须接按钮接口设置为输入,这是因为中断0、中断1在PD口。
另外有特别注意中断的初始化设置。
六、实验扩展
读懂本实验程序二,对程序进行修改,按中断0让发光管由中间逐一向两边点亮,按中断1让发光管由两边逐一向中间点亮。
实验五数码管动态扫描显示
一、实验目的与任务
1.实验目的
⑴熟悉8段数码管动态显示数字原理,并能读懂动态扫描程序。
⑵会编制、调试动态扫描程序。
⑶会修改动态扫描程序,使之能符合简单命题要求。
2.实验任务
任务一:
上电后,使八个数码管显示1-8。
任务二:
上电后,使八个数码管显示0-9999高速循环。
任务三:
上电后,使八个数码管显示0-FFFF高速循环。
三、实验接线
用扁平线的两插头分别插入单片机PB口至数码管字形口LEDD插座(AJ4),用扁平线的两插头分别插入单片机PD口至数码管字位口LEDW插座(AJ3),如图16所示。
图12实验五硬件电路连接图
四、实验步骤:
启动CVAVR编译程序
编辑、调试动态扫描程序1。
编译、下载程序到实验板。
五.实验程序清单
程序一:
#include
#include
/*七段译码字形表*/
unsignedchartable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
/*显示缓冲区*/
unsignedcharledbuff[]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};
//unsignedlongxx;
/*****************************************
8路动态扫描显示子程序
*****************************************/
voiddisp(void)
{
unsignedchari;
for(i=0;i<8;i++)
{
PORTB=ledbuff[i];//共阴数码管字形
PORTD=~(1<
delay_ms
(1);//每个数码管显示延时1mS时间
}}
/*****************************************
初始化子程序
*****************************************/
voidinit(void)
{
DDRB=0xff;
PORTB=0xff;
DDRD=0xff;
PORTD=0xff;
}
/*****************************************
BCD转换1子程序
*****************************************/
voidbcd1(unsignedlongxx)
{ledbuff[0]=table[xx%10];
ledbuff[1]=table[xx/10%10];
ledbuff[2]=table[xx/100%10];
ledbuff[3]=table[xx/1000%10];
ledbuff[4]=table[xx/10000%10];
ledbuff[5]=table[xx/100000%10];
ledbuff[6]=table[xx/1000000%10];
ledbuff[7]=table[xx/10000000%10];
}
/*****************************************
主程序
*****************************************/
voidmain(void)
{unsignedlongaa;//设置长整型变量
init();//口初始化
while
(1)
{
aa=12345678;//变量置数
bcd1(aa);
disp();//显示缓冲区的数
}
}
程序二:
#include
#include
/*七段译码字形表*/
unsignedchartable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
/*显示缓冲区*/
unsignedcharledbuff[]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};
//unsignedlongxx,temp;
/*****************************************
8路动态扫描显示子程序
*****************************************/
voiddisp(void)
{
unsignedchari;
for(i=0;i<8;i++)
{
PORTB=ledbuff[i];//共阴数码管字形
PORTD=~(1<
delay_ms
(1);//每个数码管显示延时1mS时间
}}
/*****************************************
初始化子程序
*****************************************/
voidinit(void)
{
DDRB=0xff;
PORTB=0xff;
DDRD=0xff;
PORTD=0xff;
}
/************