PLC的课程设计.docx
《PLC的课程设计.docx》由会员分享,可在线阅读,更多相关《PLC的课程设计.docx(21页珍藏版)》请在冰豆网上搜索。
![PLC的课程设计.docx](https://file1.bdocx.com/fileroot1/2023-7/2/249871b7-7121-4b09-b201-0ff29b726716/249871b7-7121-4b09-b201-0ff29b7267161.gif)
PLC的课程设计
单
片
机
实
验
报
告
专业班级:
08自动化二班
学号:
080108021115
姓名:
徐鑫
指导老师:
张清勇
单
片
机
实
验
报
告
专业班级:
08自动化二班
姓名:
罗恒
学号:
080105011124
一.实验目的
Ø通过本实验将所学单片机的理论知识与实践相结合,进一步加深对理论知识的理解。
同时对真实的单片机产品和系统有所了解
Ø实验所涉及到的程序编写和调试以及现象的测试和原理都需要我们了解和掌握其他方面的知识,如C语言,keil平台,单片机系统的结构原理等。
因此我们可以借此实验延伸和拓展专业知识
Ø最重要的一点是可以借助本实验深入掌握C51系列单片机的结构和功用
二.实验内容
本实验共分为四次,每次实验完成不同的内容,以此逐步掌握各知识要点
Unit1.输入、输出实验
1)点亮板子上的第一个灯D0
2)点亮板子上的D0、D2、D4、D6灯,与D1、D3、D5、D7灯交替闪烁
3)流水灯:
从D7---D0依次点亮
Unit2.数码管实验
1)让第一个数码管显示一个8字
2)在四个数码管上显示1,2,3,4
3)在数码管上实现000-999计数。
Unit3.按键应用实验
1)通过四个按键来控制LED灯的显示情况:
S1:
D0-D3点亮
S2:
D2点亮
S3:
D0-D7点亮
S4:
D0-D5点亮
2)按矩阵键盘上面的key0---key15,在第一个数码管上分别显示0-9,A-F。
Unit4.中断系统应用实验
右边的三个数码管从“000”开始进行加法计数。
按动S2键时计数暂停,再按继续计数。
三.实验设计及调试
Unit1.输入、输出实验
(一)点亮板子上的第一个灯D0
#include
#defineuintunsignedint
sbitP1_0=P1^0;
voidmain()
{
P1_0=0;//点亮第一个灯
}
(二)点亮板子上的D0、D2、D4、D6灯,与D1、D3、D5、D7灯交替闪烁
#include
#defineuintunsignedint
voiddelay();
voidmain()
{
while
(1)
{
P1=0xaa;//点亮D0、D2、D4、D6
delay();
P1=0x55;//点亮D1、D3、D5、D7
delay();
}
}
voiddelay()//延时程序
{
uinti,j;
for(i=500;i>0;i--)
for(j=110;j>0;j--);
}
(三)流水灯:
从D7---D0依次点亮
#include
#include//头文件
#defineucharunsignedchar
#defineuintunsignedint
voiddelay();
voidmain()
{
uchartemp;
temp=0x7f;
while
(1)//大循环
{
P1=temp;
delay();
temp=_cror_(temp,1);//右移
}
}
voiddelay()//延时程序
{
uintx,y;
for(x=100;x>0;x--)
for(y=110;y>0;y--);
}
实验感想:
首先在程序中出现的问题是P口的赋值。
如果将P写成小写,则编译通不过。
因此在C51中出现的不同于C语言的变量一般都是大写的,这个可以从最前面的头文件reg52.h中查看。
里面列举了所有和C51相关变量的预定义。
Ø在写延时子程序的时候,很容易将最后那个用于空操作的分号忘了写上,结果也是编译通不过。
Ø另外,实例4中用于流水灯控制的循环右移函数_cror_则必须在前面加上另一个头文件intrins.h将其包含。
Unit2.数码管实验
硬件图:
(一)让第一个数码管显示一个8字
#include
voidmain()
{
while
(1)
{
P2=0xfe;//位选
P0=0x7f;//显示8
}
}
(二)在四个数码管上显示1,2,3,4
#include
#defineuintunsignedint
voiddelay();
voidmain()
{
while
(1)//大循环
{
P2=0xfe;
P0=0x06;
delay();//显示1一段时间
P2=0xfd;
P0=0x5b;
delay();//显示2一段时间
P2=0xfb;
P0=0x4f;
delay();//显示3一段时间
P2=0xf7;
P0=0x66;
delay();//显示4一段时间
}
}
voiddelay()//延时程序
{
uintx,y;
for(x=5;x>0;x--)
for(y=110;y>0;y--);
}
(三)在数码管上实现000-999计数。
#include
#defineuintunsignedint
#defineucharunsignedchar
ucharcodetable[]={
0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};
voiddelay();
voidmain()
{uintcount;
ucharsecond;
second=0;
while
(1)
{
if(second==999)
{
second=0;//当记到999置0
}
for(count=0;count<100;count++)
{
P2=0xfe;
P0=table[second%10];//个位
delay();
P2=0xfd;
P0=table[second/10%10];//十位
delay();
P2=0xfb;
P0=table[second/100];//百位
delay();
}
second++;
}
}
voiddelay()//延时程序
{
uinti,j;
for(i=2;i>0;i--)
for(j=110;j>0;j--);
}
实验感想:
在动态实现00-59秒的计时器时,想让DS0,DS1两个数码管的显示是同时进行的,那么位选的间隔时间要小于人眼平均视觉暂留时间0.17s,刚开始实验时就是因为没有注意到这一点,导致秒的十位和个位的出现有很强的闪烁感,因此在设计时,将软件延时的1s时间分成100等份,并在主程序中加入一个50次的循环,再乘以位选所用的延时。
可以实现大约1s的计时。
同样,在数码管增大到8个时,动态扫描期间也遇到了这样的问题。
所以在实例2中DS0和DS7之间的所有延时加起来也需要足够小,才不致有闪烁感。
因此也少不了要用到循环,既要将每个数码管对应的数字正常显示,又要看到8个数码管的数字变化。
Unit3.按键应用实验
原理图:
:
(一)通过四个按键来控
制LED灯的显示情况:
S1:
D0-D3点亮
S2:
D2点亮
S3:
D0-D7点亮
S4:
D0-D5点亮S1:
D0-D3点亮
#include
#defineuintunsignedint
#defineucharunsignedchar
ucharflag;
voiddelay(uintk)
{
uintdatai,j;
for(i=0;i{for(j=0;j<121;j++);
}
}
ucharscan_key(void)//按键扫描程序
{
uchartemp;
temp=P3;
returntemp;
}
voidmain()
{
while
(1)
{
P3=0xff;
if(P3!
=0xff)
{delay(20);//延时,去抖动
if(P3!
=0xff)flag=scan_key();
}
elseflag=0;
switch(flag)
{
case0xf7:
P1=0xf0;break;
case0xfb:
P1=0xfb;break;
case0xdf:
P1=0x00;break;
case0xef:
P1=0xc0;break;
default:
P1=0xff;break;
}
}
}
(二)按矩阵键盘上面的key0---key15,在第一个数码管上分别显示0-9,A-F。
#include
#defineucharunsignedchar
#defineuintunsignedint
ucharcodetable[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,
0x7c,0x39,0x5e,0x79,0x71};
voiddelayms(uintk)
{
uinti,j;
for(i=k;i>0;i--)//i=k即延时约k毫秒
for(j=110;j>0;j--);
}
voiddisplay(ucharnum)//显示函数
{
P0=table[num];
P2=0xfe;
}
voidkeyscan()//键盘扫描函数
{
uchartemp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
delayms(10);//延时,去抖动
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
temp=P3;
switch(temp)
{
case0xee:
key=0;break;
case0xde:
key=1;break;
case0xbe:
key=2;break;
case0x7e:
key=3;break;
}
while(temp!
=0xf0)//等待按键释放
{
temp=P3;
temp=temp&0xf0;
}
display(key);//显示
}
}
P3=0xfd;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
temp=P3;
switch(temp)
{
case0xed:
key=4;break;
case0xdd:
key=5;break;
case0xbd:
key=6;break;
case0x7d:
key=7;break;
}
while(temp!
=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xfb;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
temp=P3;
switch(temp)
{
case0xeb:
key=8;break;
case0xdb:
key=9;break;
case0xbb:
key=10;break;
case0x7b:
key=11;break;
}
while(temp!
=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xf7;
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!
=0xf0)
{
temp=P3;
switch(temp)
{
case0xe7:
key=12;break;
case0xd7:
key=13;break;
case0xb7:
key=14;break;
case0x77:
key=15;break;
}
while(temp!
=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
}
voidmain()
{
P0=0;//关闭所有数码管段选
while
(1)
{
keyscan();
}
}
Unit4.中断系统应用实验
右边的三个数码管从“000”开始进行加法计数。
按动S2键时计数暂停,再按继续计数。
#include
#include
#defineuintunsignedint
#defineucharunsignedchar
sbitP30=P3^0;//S2键
ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
ucharcodewei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
uinttemp,flag,num;
voiddisplay();
voiddelay(uintz)//子程序延时
{uintx,y;
for(x=z;x>0;x--)
for(y=100;y>0;y--);
}
voidint0_ti()interrupt0//外部中断0停止启动计数
{TR0=!
TR0;display();}
voidmain()
{TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;//开中断
ET0=1;//允许计时器0中断
TR0=1;//启动定时器
EX0=1;//允许外部中断0
IT0=1;//下降沿有效
while
(1){display();}//调用显示数码管子程序
}
voidint0()interrupt1//定时器0中断
{TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
num++;
if(num==20)//1秒延时
{num=0;temp++;
if(temp==1000)
{num=0;}
}
}
voiddisplay()//数码管显示子程序
{P2=wei[5];
P0=table[temp/100];
delay
(2);
P0=0x00;//消除残影
P2=wei[6];
P0=table[temp/10%10];
delay
(1);
P0=0x00;
P2=wei[7];
P0=table[temp%10];
delay
(2);
P0=0x00;
}
实验感想:
涉及到按键的设计,核心可以说就是按键的检测,实例一中的按键为独立按键,因此其检测方式要较矩阵按键简单,而对于实例二中的矩阵按键键位检测使用的则是逐行扫描方式,并且无论是何种扫描方式,软件消抖这道工序必不可少,否则按键的灵敏度会受到很大限制
提及到按键的灵敏度,还有一点就是检测按键的时间问题。
在实验中,实例二中使用了定时器/计数器作为按键检测的程序,而且每隔500us就检测一次,就是为了提高按键获取的灵敏度,所以在实例一中,通过在单片机板子上的操作我就领会过,有时候反复按几次才会出现反应。
而实例二中按键一次就会在数码管上显示,狠灵敏!
关于定时器/计数器的相应问题:
由于在该次实验中我是首次使用定时器,因此在初次设计过程中,发现定时器工作和设计初衷不一致,后来才发现是TR0的设置出现问题。
关闭定时器后忘了再重新启动。
所以后来将书中有关定时器/计数器的所有寄存器中各变量的含义仔细阅览了一番
四.实验总结
1.编程是实验中的核心环节,但是要有目地的编程,这就要求对硬件结构有所了解,所以弄清楚单片机的四个P口的连接至关重要。
2.程序写好后,首先得编译通过,因此在编译调试过程中也需不断排除错误,常见的有:
比如C语言语句问题,大小写错误,关键字写错,输入法导致的非法字符以及编辑器无法显示的隐藏字符。
3.编译链接都通过后,程序也不一定就如想象中的那样执行得到想要的结果,还要不断的测试和改进,这个环节也是需要更多耐心和细心的。
4.通过本实验,我才知道一个小小的产品其中也包含着复杂的知识原理和设计者的心血,而一个庞大的系统或工艺其实也是由基础构成,设计者的灵感和创意将会借助于一件产品的活力而得以彰显。
5.由于在实验中有很多的地方比较薄弱,因此教材上的知识点虽然涵盖较多,但要就某一个知识点有针对性的深究,则需要我们通过其他各种途径获取帮助,如图书馆,互联网,与老师同学交流等。