ATMEGA16单片机实验

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

ATMEGA16单⽚机实验
实验⼀软件和硬件的认识
⼀、实验⽬的:
1、掌握硬件原理。

2、初步掌握实验板的使⽤⽅法。

3、熟悉软件⼯作界⾯。

⼆、实验仪器:ATmage16实验板⼀块
PC机⼀台
三、实验内容及步骤:
1、插上电源,按下开关。

观察批⽰灯是否点亮。

电源(可输⼊7~12V)
ATmega16管脚图
2、由原理可知I/O⼝的批⽰灯为低电平亮,在实验板上取地与I/O⼝相接,观察是否点亮。

I/O⼝LED显⽰与接⼝
3、打开编程界⾯,点击各栏,认识各栏的⽤途。

A VRICC IDE 软件的⼯作界⾯
4、输⼊以下程序:
#include
int main(void)
{
DDRA = 0xff;/* all outputs */
DDRB = 0xff;/* all outputs */
DDRC = 0xff; /*all outputs */
DDRD = 0xff; /*all outputs */
PORTA = 0x00; /* 输出低电平*/
PORTB = 0x00; /* 输出低电平*/
PORTC = 0x00; /* 输出低电平*/
PORTD = 0x00; /* 输出低电平*/
while(1);
}
观察I/O⼝的灯是否被点亮。

实验⼆I/O⼝的输⼊与输出
⼀、实验⽬的:
1、了解IO⼝的结构;
2、熟悉IO⼝的特性;
3、掌握IO⼝的控制。

⼆、实验仪器:ATmage16实验板⼀块
PC机⼀台
三、实验原理:
作为通⽤数字I/O 使⽤时,A VR 所有的I/O 端⼝都具有真正的读-修改-写功能。

这意味着⽤SBI 或CBI 指令改变某些管脚的⽅向( 或者是端⼝电平、禁⽌/ 使能上拉电阻) 时不会改变其他管脚的⽅向( 或者是端⼝电平、禁⽌/ 使能上拉电阻)。

输出缓冲器具有对称的驱动能⼒,可以输出或吸收⼤电流,直接驱动LED。

所有的端⼝引脚都具有与电压⽆关的上拉电阻。

并有保护⼆极管与VCC 和地相连,如Figure23 所⽰。

在控制I/O时,分别由⽅向寄存器DDRX与数据寄存器PORTX控制I/O的状态,如下表。

Figure 23. I/O 引脚等效原理图
I/O⼝LED显⽰与接⼝四、实验内容及步骤:输⼊以下程序:这个程序为流⽔灯
#include
//*******************延时us
void delay_us(int t)
{
do
t--;
while(t>1);
}
//*******************延时ms
void delay_ms(unsigned int t)
{
while(t!=0)
{
delay_us(1142);
t--;}
}
int main(void)
{
DDRA = 0xff;/* all outputs */
DDRB = 0xff;/* all outputs */
DDRC = 0xff; /*all outputs */
DDRD = 0xff; /*all outputs */
PORTA=0XFF;
PORTB=0XFF;
PORTC=0XFF;
PORTD=0XFF;
while(1)
{//***IO⼝输出低电平有效,如:0X01为⼗六进制数,⼆进制表⽰为00000001B,再取反
PORTA=~0X01;
delay_ms(1000);//************延时1秒
PORTA=~0X02;
delay_ms(1000);
PORTA=~0X04;
delay_ms(1000);
PORTA=~0X08;
delay_ms(1000);
PORTA=~0X10;
delay_ms(1000);
PORTA=~0X20;
delay_ms(1000);
PORTA=~0X40;
delay_ms(1000);
PORTA=~0X80;
delay_ms(1000);
PORTA=0XFF;
PORTB=~0X01;
delay_ms(1000);//************延时1秒
PORTB=~0X02;
delay_ms(1000);
PORTB=~0X04;
delay_ms(1000);
PORTB=~0X08;
delay_ms(1000);
PORTB=~0X10; delay_ms(1000); PORTB=~0X20; delay_ms(1000); PORTB=~0X40; delay_ms(1000); PORTB=~0X80; delay_ms(1000); PORTB=0XFF; PORTC=~0X01; delay_ms(1000); PORTC=~0X02; delay_ms(1000); PORTC=~0X04; delay_ms(1000); PORTC=~0X08; delay_ms(1000); PORTC=~0X10; delay_ms(1000); PORTC=~0X20; delay_ms(1000); PORTC=~0X40; delay_ms(1000); PORTC=~0X80; delay_ms(1000); PORTC=0XFF; PORTD=~0X01; delay_ms(1000);
PORTD=~0X02; delay_ms(1000); PORTD=~0X04; delay_ms(1000); PORTD=~0X08; delay_ms(1000); PORTD=~0X10;
delay_ms(1000); PORTD=~0X20; delay_ms(1000); PORTD=~0X40; delay_ms(1000); PORTD=~0X80; delay_ms(1000); PORTD=0XFF;
}
}
观看现象是不是流⽔灯。

实验三外部中断
⼀、实验⽬的:
1、了解外部中断的库函数;
2、熟悉外部中断的特性;
3、掌握外部中断的使⽤。

⼆、实验仪器:ATmage16实验板⼀块
PC机⼀台
三、实验原理:
外部中断通过引脚INT0 与INT1 或PCINT23..0 触发。

只要使能了中断,即使引脚INT0与INT1 或PCINT23..0 配置为输出,只要电平发⽣了合适的变化,中断也会触发。

这个特点可以⽤来产⽣软件中断。

只要使能,PCINT23..16 引脚上的电平变化将触发外部中断PCI2,PCINT14..8 引脚上的电平变化将触发外部中断PCI1,PCINT7..0 将触发外部中断PCI0。

PCMSK2、PCMSK1 与PCMSK0 寄存器则⽤来检测是哪个引脚上的电平发⽣了变化。

PCINT23..0 外部中断的检测是异步的。

也就是说,和其他中断⽅式⼀样,这些中断也可以⽤来将器件从休眠模式唤醒。

INT0 与INT1 中断可以由下降沿、上升沿,或者是低电平触发。

具体由外部中断控制寄存器A –EICRA 的设置来确定。

当INT0 或INT1 中断使能且设定为电平触发时,只要引脚电平被拉低,中断就会产⽣。

若要求INT0 或INT1 在信号下降沿或上升沿触发中断,则I/O时钟必须⼯作(请参见P23”时钟系统及其分布”了解更多信息)。

INT0与INT1 的低电平中断检测是异步的。

也就是说它可以⽤来将器件从休眠模式唤醒。

在休眠过程( 除了空闲模式) 中I/O 时钟是停⽌的。

通过电平中断将MCU 从掉电模式唤醒时,要保证低电平保持⼀定的时间以使MCU 完成唤醒过程并触发中断。

如果触发电平在启动时间结束前就消失,MCU 将被唤醒,但中断不会被触发。

启动时间由熔丝位SUT 与CKSEL 决定。

详见P23”系统时钟及其选项”。

外部中断控制寄存器MCUCR 外部中断控制寄存器 A 包括决定中断触发⽅式的控制位。

位1, 0 –ISC01, ISC00: 中断触发⽅式控制0 之位1 与位0外部中断0 由引脚INT0 激发,如果SREG 寄存器的I 标志位和相应的中断屏蔽位置位的话。

触发⽅式如Table35 所⽰。

在检测边沿前MCU ⾸先采样INT0 引脚上的电平。

如果选择了边沿触发⽅式或电平变化触发⽅式,那么持续时间⼤于⼀个时钟周期的脉冲将触发中断,过短的脉冲则不能保证触发中断。

如果选择低电平触发⽅式,那么低电平必须保持到当前指令执⾏完成。

中断完成后回到被中断的位置。

外部中断控制寄存器MCUCR 外部中断控制寄存器 A 包括决定中断触发⽅式的控制位。

通⽤中断控制寄存器GICR,控制外部中断使能位,具体如下:
四ICC软件中断程序书写格式及16中断向量表
16中断向量表
五实验步骤及内容:
输⼊程序:本程序⼀开始是IO⼝中的A⼝以流⽔灯⼯作,⼀旦有外部中断请求,就是B⼝以流⽔灯⼯作,循环⼀次后回到被中断处继续运⾏。

程序如下:
#include
#include
//*******************延时us
void delay_us(int t)
{
do
t--;
while(t>1);
}
//*******************延时ms
void delay_ms(unsigned int t)
{
while(t!=0)
{
delay_us(1142);
t--;}
}
#pragma interrupt_handler INT_0:2 //外部中断0执⾏函数void INT_0 (void) {
PORTC=0XFF;
PORTB=~0X01;
delay_ms(1000);
PORTB=~0X02;
delay_ms(1000);
PORTB=~0X04;
delay_ms(1000);
PORTB=~0X08;
delay_ms(1000);
PORTB=~0X10;
delay_ms(1000);
PORTB=~0X20;
delay_ms(1000);
PORTB=~0X40;
delay_ms(1000);
PORTB=~0X80;
delay_ms(1000);
PORTB=0XFF;
}
void main(void)
{
DDRA = 0xff;/*输出*/
DDRB = 0xff;/*输出*/
DDRC = 0xff;/*输出*/
DDRD = 0xff; /*输出*/
PORTA=0XFF;
PORTB=0XFF;
PORTC=0XFF;
PORTD=0XFF;
MCUCR=0X02; //定义外部中断INT0为下降沿产⽣中断请求GICR=0X40; //中断屏蔽寄存器开INT0
SEI(); //******开全局中断
for (;;)
{
PORTA=~0X01;
delay_ms(1000);
PORTA=~0X02;
delay_ms(1000);
PORTA=~0X04;
delay_ms(1000);
PORTA=~0X08;
delay_ms(1000);
PORTA=~0X10;
delay_ms(1000);
PORTA=~0X20;
delay_ms(1000);
PORTA=~0X40;
delay_ms(1000);
PORTA=~0X80;
delay_ms(1000);
}
}
实验四数码LED 实验
⼀、实验⽬的:
1、了解数码管的原理;
2、熟悉数码管的使⽤;
3、掌握外部中断和数码管动态显⽰的应⽤。

⼆、实验仪器:ATmage16实验板⼀块
PC机⼀台
三、实验原理:数码管原理图如下:
多个数码管的动态显⽰是利⽤⼈的眼睛在瞬间⽆法识别的原理来实现在,如电灯也是利⽤这个原理。

四、实验步骤及内容:这个程序是数码管动态显⽰,按INT0键加1,⼀直到
数码管显⽰为9999再重新计数。

实验程序如下:
#include
#include
int led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//*******显⽰符0,1,2,3,4,5,6,7,8,9,
unsigned int i;
int g,s,b,q;
//*******************延时us
void delay_us(int t)
{
do
t--;
while(t>1);
}
//*******************延时ms
void delay_ms(unsigned int t)
{
while(t!=0)
{
delay_us(1142);
t--;}
}
#pragma interrupt_handler INT_0:2 //外部中断0执⾏函数
void INT_0 (void)
{ i++;
delay_ms(15);//******键盘防抖动
}
void main(void)
{
DDRD = 0xff;/* all outputs */
DDRC = 0xff;/* all outputs */
DDRB = 0xff; /*all outputs */
PORTB=0XFF;
PORTC=0X00;
PORTD=0XFF;
MCUCR=0X02; //定义外部中断INT0为下降沿产⽣中断请求GICR=0X40; //中断屏蔽寄存器开INT0 SEI(); //******开全局中断
for (;;)//****显⽰按键次数
{
i f(i>9999)
i=0;
g=i%10; //取个位,取余
PORTC=0X01;
PORTB=led[g];
delay_ms(1);
s=i%100/10; //取⼗位
PORTC=0X02;
PORTB=led[s];
delay_ms(1);
b=i%1000/100; //取百位
PORTC=0X04;
PORTB=led[b];
delay_ms(1);
q=i%10000/1000; // 取千位
PORTC=0X08;
PORTB=led[q];
delay_ms(1);
/* for (i=0;i<4;i++)
PORTB=led[g];
g=i/10; //取整
PORTC=0x00;;
)*/
}
}
实验五键盘接⼝实验
⼀、实验⽬的:1、了解IO⼝的结构;
2、熟悉键盘的程序原理;
3、掌握键盘的使⽤。

⼆、实验仪器:MEGA16实验板⼀块
PC机⼀台
三、实验原理:在A VR 单⽚机中,当I/O⽅向设置为输⼊,电平被设置为
⾼电平时,⼀旦外部接⼊低电平,端⼝电平被拉低,电平变化会反映相应端⼝PINX寄存器中,利⽤这⼀特点,在键盘中采⽤设置⾏所对IO⼝为输出,⾼电平,列所对IO⼝为输⼊,⾼电平。

对⾏所对IO⼝电平逐个设置为低电平,此时列线上某列电平被拉低。

通过读取列线上电平,计算出所按键值。

四实验程序
#include
#include
/////////////////////////////延时///////////////////////////////////////////
void delay_us( int t) //us
{
do
t--;
while(t>1);
}
void delay_ms(unsigned int t) //ms
{
t--;
}
}
unsigned char led[]={ 0X3F,/*0*/ //七段译码表
0X06,/*1*/
0X5B,/*2*/
0X4F,/*3*/
0X66,/*4*/
0X6D,/*5*/
0X7D,/*6*/
0X07,/*7*/
0X7F,/*8*/
0X6F,/*9*/
0X77,/*A*/
0X7C,/*b*/
0X39,/*C*/
0X5E,/*d*/
0X79,/*E*/
0X71,/*F*/
}; //显⽰符0,1,2,3,4,5,6,7,8,9,
unsigned char led_buff[]={0x3f,0x3f,0x3f,0x3f,0x3f,0x3f}; //显⽰缓冲区unsigned char scan_key(void) //不做按键释放检查的键盘扫描函数{
unsigned char i,temp;
DDRD=0X0F; //设置D⼝的⾼四位为输⼊,低四位为输出
PORTD=0XFf; //D⼝输出⾼电平
for(i=0;i<4;i++)
{
PORTD=~(1<
delay_us(500);
temp=PIND&0XF0; //temp取D⼝⾼四位的值
if(temp!=0xf0) //如有键按下,延时15ms
{
delay_ms(15); //延时⽤来消除显⽰抖动
temp=PIND&0xf0; //再读键盘
temp&=0xf0;
switch (temp) //计算键值
{
case 0x70:temp=15-(3-i)*4;break;
case 0xb0:temp=14-(3-i)*4;break;
case 0xd0:temp=13-(3-i)*4;break;
case 0xe0:temp=12-(3-i)*4;break;
default:temp=0x7f;
}
return temp; //返回temp
}
}
PORTD=0xff;
}
return 0x7f;
}
void port_init(void) //初始化IO
{
DDRA=0xff;
PORTA=0xff;
DDRC=0xff;
PORTC=0Xff;
DDRD=0x0f;
PORTD=0xff;
}
void display(void) //六位数码管显⽰
{
unsigned int i=0;
for(;i<6;i++)
{
PORTA=led_buff[i]; //PA⼝为段选PORTC=(1< delay_us(1000);
PORTC=0X00;
}
}
unsigned char key1,key2;
unsigned char i;
port_init();
for(;;)
{
key1=scan_key(); //键盘扫描if (key1!=0x7f)
{
do
{
key2=scan_key();
display();
}
while(key1==key2);
for (i=0;i<5;i++) //显⽰
led_buff[5-i]=led_buff[4-i]; //按下⼀次移⼀次
led_buff[0]=led[key1]; //做led显⽰转换
}
display(); //显⽰
}
}
实验六模数转换AD 实验
⼀、实验⽬的:
1、了解IO⼝的结构;
2、熟悉A/D的特性;
3、掌握A/D的使⽤。

⼆、实验仪器:MEGA16实验板⼀块
PC机⼀台
三、实验原理:
四、实验步骤及内容:
#include
#include
#define VREF 4.950
unsigned int V=0;
float Vin=0;
unsigned char led[]={0X3F,0X06,0X5B,0X4F,0X66,0X6D,0X7D,0X07,0X7F,0X6F}; //0-9 unsigned char led_putff[]=
void delay_us(int t)
{
do
t--;
while(t>1);
}
//*******************延时ms
void delay_ms(unsigned int t)
{
while(t!=0)
{
delay_us(1142);
t--;}
}
/*....中断....*/
#pragma interrupt_handler ADC_isr:15 void ADC_isr(void)
{
V=ADCL;
V=(ADCH<<8)+V; //读取转换数值
}
/*....系统初始化....*/
void xhushihua(void)
{
DDRD=0XFF; //位选
DDRB=0XFF; //数码管
DDRA=0XFE; //C0⼝电压输⼊PORTD=0X00;
PORTB=0XC0;
PORTA=0X00;
ADCSRA|=(1<
SEI();
}
/*....AD初始化....*/
void ad_link(void)
ADCSRA|=(1<
ADCSRA|=(1<
ADMUX=0X00; //右对齐,基准电源VREF。

零通道SFIOR=0X00; //开启连续模式}
/*....计算转换值....*/
void led_put(void)
{
unsigned char sreg;
unsigned char i=0;
unsigned char f=0;
unsigned int X=0;
sreg = SREG; //保存全局中断标志
CLI(); //禁⽤中断
Vin=V*VREF/1024; //转换数值
X=(unsigned short)(1000*Vin);
for(i=0;i<4;i++)
{
f=X%10;
led_putff[i]=led[f];
X=X/10;
}
led_putff[3]=0X80|led_putff[3];
SREG=sreg; //恢复全局中断标志
}
/*....数码管扫描....*/
void display(void)
{
unsigned char i=0;
for(i=0;i<4;i++)
{
PORTB=led_putff[i];
PORTD|=(1<
delay_us(30);
PORTD=0X00;
}
void main(void)
{
xhushihua();
ad_link();
for(;;)
{
led_put();
display();
}
}
实验七PWM使⽤
⼀、实验⽬的:
1、熟悉PWM的原理与特性;。

相关文档
最新文档