C51单片机实训论文.docx
《C51单片机实训论文.docx》由会员分享,可在线阅读,更多相关《C51单片机实训论文.docx(18页珍藏版)》请在冰豆网上搜索。
C51单片机实训论文
上海第二工业大学
实训课程
课程:
二级项目(电子设计)
学生姓名:
许奇峰
学号:
104827477
学院名称:
电子与电气工程学院
专业班级:
10测控C1
摘要
近年来随着科技的飞速发展,单片机的应用正在不断深入,同时带动传统控制检测技术日益更新。
在实时检测和自动控制的单片机应用系统中,单片机往往作为一个核心部件来使用,仅单片机方面知识是不够的,还应根据具体硬件结构软硬件结合,加以完善。
本实验采用的单片机为C51,以C语言为程序设计的基础,通过4*4的矩阵键盘上的特定的按键来控制1602液晶显示屏,以显示设计人的姓名、学号,还有时钟来显示时、分、秒、日期,并且显示当时的温度,PWM和A/D转换等功能。
一.实验目的
通过此次实训,让我们掌握了单片机基本原理的基础、单片机的编程知识以及初步掌握单片机应用系统开发实用技术,了解单总线的读/写控制方法。
同时培养学生理论与实践相结合的能力,提高分析问题和解决问题的能力,增强学生独立工作能力;培养了我们团结合作、共同探讨、共同前进的精神与严谨的科学作风。
本次实验的目的主要有以下几点:
1、熟悉51单片机的基本构造和原理基础;
2、能运用51单片机进行简单的单片机应用系统的硬件设计;
3、掌握单片机应用系统的硬件、软件调试方法;
4、4*4矩阵键盘的应用,1602液晶显示屏幕的应用等;
5、运用C51单片机来设计显示时钟、温度、PWM、A/D转换。
二.硬件组成
·51单片机最小系统
1、震荡器
单片机系统正常工作的保证,如果振荡器不起振,系统将会不能工作;假如振荡器运行不规律,系统执行程序的时候就会出现时间上的误差,这在通信中会体现的很明显:
电路将无法通信。
他是由一个晶振和两个瓷片电容组成的,x1和x2分别接单片机的x1和x2,晶振的瓷片电容是没有正负的,注意两个瓷片电容相连的那端一定要接地。
2、复位端复位电路
给单片机一个复位信号(一个一定时间的低电平)使程序从头开始执行;一般有两中复位方式:
上电复位,在系统一上电时利用电容两端电压不能突变的原理给系统一个短时的低电平;手动复位,同过按钮接通低电平给系统复位,时如果手按着一直不放,系统将一直复位,不能正常
·AT89C51
1)简介
A89C51是一种带4K字节闪烁可编程可擦除只读存储器(FPEROM—FlashProgrammableandErasableReadOnlyMemory)的低电压,高性能CMOS8位微处理器,俗称单片机。
单片机的可擦除只读存储器可以反复擦除100次。
该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器。
AT89C51单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
外形及引脚排列如图所示。
2)功能特性
·与MCS-51兼容
·4K字节可编程闪烁存储器
·寿命:
1000写/擦循环
·数据保留时间:
10年
·全静态工作:
0Hz-24MHz
·三级程序存储器锁定
·128×8位内部RAM
·32可编程I/O线
·两个16位定时器/计数器
·5个中断源
·可编程串行通道
·低功耗的闲置和掉电模式
·片内振荡器和时钟电路
·矩阵键盘(如附录2,图2)
在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式。
在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。
这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。
由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。
矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。
这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。
行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。
·蜂鸣器
通过加一个低电压,大电流,小信号的PNP型硅三极管Q8550来放大电流达到驱动蜂鸣器的作用,蜂鸣器的正极接到Q的集电极C上,蜂鸣器的负极接地,三极管的发射极E接电源VCC,基极B经过限流电阻R9后与单片机P1.3的引脚相连,当单片机P1.3引脚输出高电平时,三极管截止,没有电流通过线圈,蜂鸣器不发声;当单片机P1.3引脚输出低电平时,三极管导通,电流形成回路,蜂鸣器发声。
·LED1602液晶屏
1602液晶也叫1602字符型液晶它是一种专门用来显示字母、数字、符号等的点阵型液晶模块它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。
每位之间有一个点距的间隔每行之间也有间隔起到了字符间距和行间距的作用,正因为如此所以他不能显示图形。
引脚定义:
1脚:
VSS为电源地;
2脚:
VDD接5V电源正极;
LED1602引脚图
3脚:
V0为对比度调整端,接正电源时对比度最弱,接地电源时最高;
4脚:
RS为寄存器选择,高电平时数据寄存器、低电平时指令寄存器;
5脚:
RW为读写信号线,高电平时进行读操作,低电平时进行写操作;
6脚:
E(或EN)端为使能(enable)端;
7~14脚:
D0~D7为8位双向数据端;
15~16脚:
空脚或背灯电源;15脚背光正极,16脚背光负极。
二.实验过程
1.启动KEIL,使用自己做的含C51芯片的单片机电路板。
2.在main.c中编写主程序代码
3.选用buildtarget生成目标,然后编译连接工程
4.打开STC-ISP-V4.86-NOT-SETUP-CHINESE,选择com口,将编译的文件下载到电路板上
5.按键操作,显示,观察。
。
。
实验流程图
四.实验总结
随着电子技术的日益进步,微型计算机取得了突飞猛进的发展。
作为微型计算机的一个重要分支,单片机以其体积小、功能齐全、价格低廉、可靠性高等特殊优点,在工业测控、智能仪表器、机电一体化产品、家电等领域取得了快速的发展。
通过几天的实习,深有体会,学习单片机只有对着电脑,反复敲打键盘,不断编写、修改、做记录,才能很好了解单片机、学好单片机。
相信捉住这条思维,在以后学习中,能给予很大的帮助。
几天下来,在我个人方面,学到的东西还是挺多的。
经过一个学期的单片机学习,使我们收获不少,在这个设计中,也学到了不少东西,从找设计开始,各种元件的选择,和同学一起分享画图,敲程序,学到了制作的过程,对数字电子钟也有了一定的认识。
十分感谢老师和同学们一学期以来的帮助。
这次实验,不仅学会了电子钟的制作,也对单片机的知道有了更加深入的了解,对自己帮助非常大,扩展了自己的视野。
1.实验附录
附录一(效果图)
图一.菜单显示图二.菜单显示
图三.菜单显示图四.时间显示
图五.A/D转换显示图四.温度显示
附录二(参考程序):
#include
#include
//#include
#defineuintunsignedint
#defineucharunsignedchar
sbitbell=P3^2;
sbitled=P3^4;
ucharkey,m,p=0,flag=0,keyboard=0;
ucharhour=12,min=0,sec=0;
ucharcount_10ms=0;
charnum=0;
uchar*Anum[]={"NO.1_Time...","NO.2_Tempture...","NO.3_AD...",
"NO.4_PWM...","NO.5_Else..."};
voiddelay(uintz)//延时程序
{uintx,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);}
voidwr_com(unsignedcharcom)//写命令
{delay1ms(5);
EN=0;//使能端给一个高脉冲,因为初始化函数中已经将lcden置为0
RS=0;//选择写命令模式
RW=0;//P0=com;//将要写的命令送到数据总线上
EN=1;//将使能端置0以完成高脉冲}
voidwr_dat(unsignedchardat)//写数据
{delay1ms(5);
EN=0;
RS=1;
RW=0;
P0=dat;
EN=1;}
voidinit()//清屏
{wr_com(0x38);//设置16*2,显示5*7点阵,8位数据接口
wr_com(0x0C);//设置开显示,不显示光标
wr_com(0x06);//写一个符号地址指针自动加一
wr_com(0x01);//显示清0,数据指针清0}
voidMoveKey(ucharNum)
{lcd_clr();
wirte_str(0,0,Anum[Num]);
wirte_str(1,0,Anum[Num+1]);
lcd_wcmd(0x0f);}
voidkeypress(ucharkey)//显示keypress功能
{if(key==12)//下
{MoveKey(num);
keyboard=num+1;
num--;
if(num<0)num=5;
delay(10);}
if(key==16)//上
{MoveKey(num);
keyboard=num+1;
num++;
if(num>5)num=0;
delay(10);}
if(key==11)//退出
{lcd_clr();
wirte_str(0,0,"XuQifeng");
wirte_str(1,0,"104827477");}}
voidgetKey()
{uchartemp,readRow;
P2=0xFE;
temp=P2;
temp=temp&0xf0;
if(temp!
=0xf0)
{delay(10);
readRow=~temp>>4;
switch(readRow)
{case1:
key=10;break;//enter进入
case2:
key=11;break;//esc退出
case4:
key=12;break;//下
case8:
key=16;break;//上
default:
break;}
while(temp!
=0xf0)
{temp=P2;
temp=temp&0xf0;}
delay(10);
keypress(key);}
P2=0xFD;
temp=P2;
temp=temp&0xf0;
if(temp!
=0xf0)
{delay(10);
readRow=~temp>>4;
switch(readRow)
{case1:
{key=14;m++;if(m==10)m=0;};break;//右
case2:
key=3;break;case4:
key=6;break;
case8:
key=9;break;}
while(temp!
=0xf0)
{temp=P2;
temp=temp&0xf0;}
delay(10);
keypress(key);}
P2=0xFB;
temp=P2;
temp=temp&0xf0;
if(temp!
=0xf0)
{delay(10);
readRow=~temp>>4;
switch(readRow)
{case1:
{key=13;m--;if(m==0)m=10;};break;//左
case2:
key=2;break;case4:
key=5;break;case8:
key=8;break;}
while(temp!
=0xf0)
{temp=P2;
temp=temp&0xf0;}
delay(10);
keypress(key);}
P2=0xF7;
temp=P2;
temp=temp&0xf0;
if(temp!
=0xf0)
{delay(10);
readRow=~temp>>4;
switch(readRow)
{case1:
key=0;break;case2:
key=1;break;case4:
key=4;
break;case8:
key=7;break;}
while(temp!
=0xf0)
{temp=P2;temp=temp&0xf0;}
delay(10);
keypress(key);}}
voidtime1()interrupt3//显示Time功能
{TH1=0xdc;TL1=0x00;
count_10ms++;}
voidtime1_init()
{TMOD=0x10;TH1=0xdc;TL1=0x00;EA=1;ET1=1;TR1=1}
uchardisp_buf[6]={0x00,0x00,0x00,0x00,0x00,0x00};
voidlcd_dat(ucharh,m,s)//读取时间
{disp_buf[0]=h/10+0x30;disp_buf[1]=h%10+0x30;
disp_buf[2]=m/10+0x30;disp_buf[3]=m%10+0x30;
disp_buf[4]=s/10+0x30;disp_buf[5]=s%10+0x30;}
voidlcd_display()//显示时间
{lcd_wcmd(0x44|0x80);lcd_wdat(disp_buf[0]);lcd_wdat(disp_buf[1]);
lcd_wdat(0x3a);lcd_wdat(disp_buf[2]);lcd_wdat(disp_buf[3]);
lcd_wdat(0x3a);lcd_wdat(disp_buf[4]);lcd_wdat(disp_buf[5]);}
voidTime()
{keyboard=0;
time1_init();
lcd_init();
wirte_str(0,0,"Time");
while
(1)
{if(count_10ms>=100)
{count_10ms=0;
sec++;}
if(sec>=60)
{sec=0;min++;
if(min>=60)
{min=0;hour++;
if(hour>=24)
{hour=0;min=0;sec=0;}}}
lcd_dat(hour,min,sec);
lcd_display();
getKey();
if(key==11)break;}}}
voidTempture()//显示Temp功能
{voiddisplay()
{unsignedlongtemp;
temp=Temp*100;
disdata[0]=temp/1000+0x30;//十位数
disdata[1]=temp%1000/100+0x30;//个位数
disdata[2]=temp%100/10+0x30;//小数
disdata[3]=temp%10+0x30;
if(disdata[0]==0x30)
{disdata[0]=0x20;//如果十位为0,不显示
if(disdata[1]==0x30)//如果十位为0,个位为0也不显示
{disdata[1]=0x20;}}
lcd_wcmd(0xc1);
lcd_wdat(disdata[0]);//显示十位
lcd_wdat(disdata[1]);//显示个位
lcd_wdat(0x2e);//显示小数点
lcd_wdat(disdata[2]);//显示小数
lcd_wdat(disdata[3]);}
uchardisdata[5];
floatTemp;
voiddelayms(uintxms)
{uinti,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);}}
voidAD_Init()//显示A/D功能
{P1M0=0x0f;//设置P1口低4位为开漏模式,AD采集
P1M1=0x0f;
P1ASF=0x0f;//P1口模拟功能控制位,
ADC_CONTR=0xe0;//开启AD转换并选择最高转换速度
AUXR1=0x00;//数据格式设置高八位在ADC_RES低二位在ADC_RESL
delayms(100);}
intGetAD(ucharchannel)//选择通道号并获取数据
{ucharAD_finished=0;
intresult;
ADC_CONTR|=channel;//选择通道号
ADC_CONTR|=0x08;//启动AD转换
while(AD_finished=0)
{AD_finished=(ADC_CONTR&0x10);//查询ADC_FLAG是否置1}
result=ADC_RES*4+ADC_RESL;
ADC_CONTR&=0xef;//清除转换结束标志
return(result);}
floatAd_Av(ucharchannel)//对获取的数据进行处理
{floatVal_Av=0;
ucharnum;
for(num=100;num>0;num--)
{Val_Av+=GetAD(channel);}
Val_Av/=100.0;
Val_Av=Val_Av*5/1024;
return(Val_Av);}
voidAD()
{keyboard=0;
AD_Init();
lcd_init();
lcd_wcmd(0x80);//显示字符AD
lcd_wdat(0x41);
lcd_wdat(0x44);
while
(1)
{delayms(500);
Temp=Ad_Av(0);//通道0进行数据采集
display();
getKey();
if(key==11)break;}}
sbitPwm=P1^0;//显示PWM功能
ucharn=0,m=0;
voiddelayms(uintxms);
voidTimer0_init();
voidPWM()
{keyboard=0;
time1_init();
lcd_init();
lcd_clr();
wirte_str(0,0,"PWM");
while
(1)
{if(count_10ms>=10)
{count_10ms=0;
if(n<=m)
Pwm=1;
else
Pwm=0;
n++;
if(n==10)n=0;}
getKey();
if(key==11)break;}}
voidElse()//显示Else功能
{lcd_clr();
wirte_str(0,0,"That'sall");
wirte_str(1,0,"Thankyou");
delay(100);
keyboard=0;}
voidmain()//主函数
{lcd_init();
wirte_str(0,0,"XuQifeng");
wirte_str(1,0,"104827277");
while
(1)
{getKey();
if(key==10)//enter
{switch(keyboard)
{case1:
Time()break;
case2:
Tempture();break;
case3:
AD();break;
case4:
PWM();break;
case5:
Else();break;
default:
break;}}}