一、实验目的:掌握单片机的开发环境,学会Keil C和Proteus的使用方法。
二、实验要求:用单片机的P0.0口控制一个LED电路,并完成编程,使LED循环亮灭。
三、实验设备:计算机、Keil C51编程软件、Proteus仿真软件等。
四、实验步骤:
步骤1:建立工程文件:
(1) 单击“Project"→“New μVision Project” 菜单命令,打开“Create New Project" 对话框;
(2)在“保存在"下拉列表框中,选择工程保存目录(如E: \ project\ ex11), 并在 “文件名” 文本框中输人工程名字(如ex1_1),不需要加扩展名,单击“保存”按钮,出现如图1.3所示的选择目标器件“ Select Device for Target”对话框;
(3)在图1.3中,单击左侧列表框中; Atmel” 项前面的“+”号,展开该层,单击其中的“ AT89C51”,然后再单击“OK"按钮;
(4)打开如图1.5所示的复制标准8051启动代码选择窗口界面,单击“否(N)”按钮回到主界面。
步骤2:建立并添加源文件
(1)单击“File”-“New”菜单命令,在该窗口中输人源程序;
(2)对该源程序检查校正后,单击“File” -“Save as...”菜单命令,将源程序另存为C语言源程序文件;
(3)在工程管理窗口中“Source Group 1”项上单击鼠标右键打开快捷菜单,再选择“Add Files to Group ' Source Group 1'”菜单命令。然后在“文件类型”下拉列表框中选择“C Source file( *.c)”,找到前面新建的“exl_ _1.c"文件并选择后,单击“Add"按钮加入工程中;
(4)在工程管理窗口“Source Group 1”项中会出现名为“ex1_ 1.c” 的文件,说明新文件的添加已完成。
步骤3:配置工程属性
(1) 如图1.12所示,将鼠标移到工程管理窗口的"Target1” 上,单击鼠标右键,再选“Options for Target 1 'Target1 " 菜单;
(2)单击“Output” 选项卡,打开“Output”选项设置页面,选中“Create HEX File”复选框,再单击“OK"按钮。
步骤4:编译工程
(1)在主界面中,单击“Project”一“Build target” 菜单命令(或按快捷键F7),或单击工具栏中的快捷图标“”来进行编译。
单机“P”选中所需的电子元件,按照下图给出仿真电路图。
图1-1硬件仿真图
在keil C51编写如下程序:
ORG 0000H
JMP START
ORG 0030H
START: CLR P0.0
CALL DELAY
SETB P0.0
CALL DELAY
JMP START
DELAY: MOV 55H,#10
D1: MOV 56H,#200
D2: MOV 57H,#248
DJNZ 57H,$
DJNZ 56H,D2
DJNZ 55H,D1
RET
END
五、实验结果:在Proteus仿真中加载编译的程序,观察到程序循环执行,LED一闪一灭。熟悉单片机应用的开发环境,完成了一个简单的单片机应用的设计过程。
六、实验心得:(不如少于200字)
一、实验目的:1、掌握C51的移位运算;
2、熟悉C51程序设计,掌握程序结构和子程序的调用。
二、实验要求:用单片机的P1口接8个LED,使LED依次间隔1秒,循环点亮。
三、实验设备:计算机、Keil C51编程软件、Proteus仿真软件等。
四、实验仿真图:仿真图如下2-1所示。
图2-1 流水灯仿真图
五、实验程序如下:
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
void delay1ms(uint x) //基准延时时间为1ms的延时子程序
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<123;j++);
}
main()
{
uchar i;
while(1)
{
for(i=0;i<8;i++)
{
P1=_crol_(0x01,i); //0000 1000
delay1ms(80);
}
}
}
六、实验结果:通过仿真实验,实验完成了循环点亮LED的要求。掌握了延时子程序的编写和移位函数的应用。
七、实验心得:(不如少于200字)
一、实验目的:1、熟悉单片机中断系统;
2、掌握外部中断的使用方法。
二、实验要求:用单片机的P1口接8个LED,用INT0中断控制8个LED,当有INT0中断触发一次LED依次循环移动一位。
三、实验设备:计算机、Keil C51编程软件、Proteus仿真软件等。
四、实验仿真图:仿真图如下3-1所示。
图3-1 外部中断仿真图
五、实验程序如下:
#include <reg51.h>
#include <intrins.h>
unsigned char sum;
void delay1ms(unsigned int x)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<123;j++);
}
main()
{
TCON=0X01; //TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 IT0=1;
IE=0X81; //EA - - ES ET1 EX1 ET0 EX0 EA=1; EX0=1;
while(1)
{
P1=_crol_(0x01,sum);
}
}
void wbzd() interrupt 0
{
EA=0;
delay1ms(10);
sum=(sum+1)%8;
delay1ms(10);
EA=1;
}
六、实验结论:通过实验仿真,实现了外部中断事件的相应。每按一次外部中断按键LED移位点亮一下。
七、实验总结:
一、实验目的: 1、熟悉单片机中断系统;
2、掌握定时器/计数器中断的使用方法;
3、掌握定时器/计数器的初值的设置方法。
二、实验要求:用T1获取1秒的定时,用单片机的P1口接8个LED,使得每隔1秒循环移位点亮一个LED。
三、实验设备:计算机、Keil C51编程软件、Proteus仿真软件等。
四、实验仿真图:仿真图如下4-1所示。
图4-1 流水灯仿真图
五、实验程序:
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar num;
main()
{
TMOD=0X10; //GATE CT M1 MO GATE CT M1 MO 0001 0000
TH1=0X3C; //TH1=(65536-50000)/256
TL1=0XB7; //TL1=(65536-50000)%256
IE=0X88; //EA - - ES ET1 EX1 ET0 EX0 1000 1000
TCON=0X40; //TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 0100 0000
while(1)
{
P1=_crol_(0x01,num);
}
}
void timer1() interrupt 3
{
uchar js;
TH1=(65536-50000)/256;
TL1=(65536-49990)%256;
js++;
if(js==20)
{
num=(num+1)%8;
js=0;
}
}
六、实验结果:通过仿真实验,实现了定时器中断定时一秒的要求。掌握了定时器中断的应用方法。
七、实验心得:(不如少于200字)
一、实验目的:1、掌握串行通信的异步通信方式的设置;
二、实验要求:通过上位机选中通信的下位机,并向下位机发送数据,数据在下位机用LED指示输出的状态。
三、实验设备:计算机、Keil C51编程软件、Proteus仿真软件等。
四、实验仿真图:仿真图如下4-1所示。
图5-1 多机通信实验图
五、实验程序:
1、上位机程序:
#include <reg51.h>
void initurat()
{
SCON=0Xd0; //M0 M1 M2 REN TB8 RB8 TI RI 1000 0000
TMOD=0X20;
TH1=TL1=0XFa;
PCON=PCON|0X80;
IE=0X90; //EA - - ES ET1 EX1 ET0 EX0 1001 0000
TR1=1;
}
void fssj(unsigned char x)
{
SBUF=x;
while(!TI);
TI=0;
}
main()
{
unsigned char addr,sum;
initurat();
while(1)
{
addr=P0;
TB8=1;
fssj(addr);
TB8=0;
sum=P1;
fssj(sum);
}
}
2、下位机程序:
#include <reg51.h>
unsigned char js,addr;
void delay1ms(unsigned int x)
{
unsigned int i,j;
for(i=0;i<x;i++)
for(j=0;j<125;j++);
}
void initurat()
{
SCON=0Xd0; //M0 M1 M2 REN TB8 RB8 TI RI 1011 0000
TMOD=0X20;
TH1=TL1=0XFA;
PCON=PCON|0X80;
IE=0X90; //EA - - ES ET1 EX1 ET0 EX0 1001 0000
TR1=1;
}
unsigned char jssj()
{
while(!RI);
if(RB8==1)
return 0xee; //若接收到地址位,则接受状态返回非0
js=SBUF; //接收到的数据放在js中
RI=0;
return 0; //若接收到地址位,则接受状态返回0
}
main()
{
initurat(); //串行中断初始化
P2=0; //LED初始状态
while(1)
{
SM2=1; //多机工作方式
while(addr!=P0) //判断接收的地址不为本机地址,执行循环直到满足条件
{
RI=0;
while(!RI);
addr=SBUF;
RI=0;
P2=0;
}
SM2=0; //接收的地址为本机地址,则把接收的数据送P2口输出
addr=jssj(); //执行接受数据,结果送num
if(addr==0) //地址位返回非0,只有返回0时表示是数据
{
P2=js; //输出num的值
delay1ms(100);
}
}
}
六、实验结论:
七、实验心得:(不如少于200字)
一、实验目的: 1、掌握数码管的显示原理;
2、掌握动态显示方式。
二、实验要求:用P0驱动2个数码管,使数码管从00-99循环显示数值,每次的显示为0.4秒。
三、实验设备:计算机、Keil C51编程软件、Proteus仿真软件等。
四、实验仿真图:仿真图如下6-1所示。
图6-1 数码管动态显示仿真图
五、实验程序:
#include<reg51.h>
#include<intrins.h>
#define uint unsigned int
#define uchar unsigned char
#define ulong unsigned long
uchar code smg[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};//共阴数码管0-9字型码
void delay1ms(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<123;j++);
}
void displed(uchar i,j) //动态显示子程序,i为显示的数值,j为位选
{
P0=smg[i]; //输出i的字型码
P2=_crol_(0xfe,j); //输出位选信号,j为0表示选通十位,j为1表示选通个位
delay1ms(1); //延时
P2=0xff; //关位选
}
void disp(ulong x)
{
uchar a[8];
uchar i,j; //12345678
ulong num=1;
for(i=0;i<8;i++)
{
a[i]=(x/num)%10;
num=num*10;
if(num>x) break;
}
for(j=0;j<=i;j++) displed(a[j],7-j);
}
main()
{
uchar num; //i为显示的数值,num控制每一个数值的显示时间
ulong i;
while(1)
{
for(i=0;i<10000000;i++) //i是在0-99之间取值
{
for(num=0;num<20;num++)//num取200,表示每一个数值显示0.4秒
{
disp(i) ;
//displed(i/10,0); //在十位数码管上显示i的十位
//displed(i%10,1); //在个位数码管上显示i的个位
}
}
}
}
六、实验结果:通过仿真实验,实现了数码管的动态显示,实现了实验要求。掌握了数码管显示的原理,掌握了动态显示的设计方法。
七、实验心得:(不如少于200字)
一、实验目的:1、掌握中断按键判断;
2、熟悉软件去抖的方法。
二、实验要求:用一个按键加数码管显示的数值,用另一个按键减数码管显示的数值,数码管显示的范围是0-9。
三、实验设备:计算机、Keil C51编程软件、Proteus仿真软件等。
四、实验仿真图:仿真图如下7-1所示。
图7-1 独立按键实验仿真图
五、实验程序:
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code smg[]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};//共阴数码管字型码
uchar sum; //sum为数码管显示的数值
sbit jia = P3^2;
sbit jian = P3^3;
void delay1ms(uint x) //基准延时1ms的子程序
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<123;j++);
}
void displed(uchar i,j) //显示子程序,i是显示内容,j是位选
{
P2=smg[i];
j=0;
delay1ms(1);
}
main()
{
while(1)
{
if(jia==0)
{
delay1ms(10); //去抖延时
sum=(sum+1)%10; //sum数值在0-9范围内改变,+1
delay1ms(10); //去抖延时
}
if(jian==0)
{
delay1ms(10); //去抖延时
if(sum==0) sum=10;
sum--; //sum数值在0-9范围内改变,-1
delay1ms(10); //去抖延时
}
displed(sum,0);
}
}
六、实验结果:通过仿真实验,实现了独立按键的扫描,达到了实验要求。掌握了独立按键的判断方法及应用设计。
七、实验心得:(不如少于200字)
一、实验目的:1、掌握单片机的矩阵按键设计方法;
2、熟悉软件去抖的方法。
二、实验要求:设计1个4*4的矩阵按键,并给按键编号0-15;当有按键按下就用数码管显示该按键的编号。
三、实验设备:计算机、Keil C51编程软件、Proteus仿真软件等。
四、实验仿真图:仿真图如下8-1所示。
图8-1 矩阵按键实验仿真图
五、实验程序:
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar code smg[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
uchar jz;
void delay1ms(uint x)
{
uint i,j;
for(i=0;i<x;i++)
for(j=0;j<110;j++);
}
void dispw(uchar w,uchar s)
{
P2=_cror_(0x7f,w);
P0=smg[s];
delay1ms(1);
P2=0xff;
P0=0xff;
}
void scanjz()
{
uchar hyw,lyw,hsm,lsm; //gw存放个位数,sw存放十位数,hyw负责p1.0-p1.3送低电平
//lsm扫描p1.4-p1.7是否有低电平,hsm,lsm负责判断按键是否按下松开
for(hyw=0;hyw<4;hyw++)
{
P1=_crol_(0xfe,hyw); //给p1.0-p1.3送低电平,进行行的扫描
for(lyw=0;lyw<4;lyw++) //扫描p1.4-p1.7是否有低电平
{
lsm=_crol_(0xfe,lyw+4)&0xf0; //给lsm赋值,取高四位值
hsm=P1&0xf0; //给hsm赋值,读取P1口高四位值
if(hsm==lsm) //判断按键是否按下
{
delay1ms(10); //去抖延时
while(hsm==lsm) //判断按键是否松开
{
hsm=P1&0xf0; //重新读取hsm值
jz=hyw*4+lyw; //给按键编号jz赋值
}
}
}
}
}
main()
{
uchar gw,sw; //jz存放矩阵按键编号,gc用于存放P1高四位
while(1)
{
scanjz();
gw=jz%10;
sw=jz/10;
dispw(0,gw);
dispw(1,sw);
}
}
六、实验结论:通过仿真实验,实现了矩阵按键的扫描,达到了实验要求。掌握了矩阵按键的判断方法及应用设计。
七、实验心得:(不如少于200字)