单片机课设 按键和显示 原理图PCB
课程设计说明书
1设计内容要求简介
1.1Proteus软件简介
Proteus软件是英国Labcenterelectronics公司出版的EDA工具软件。它不仅具有其它EDA工具软件的仿真功能,还能仿真单片机及外围器件。它是目前最好的仿真单片机及外围器件的工具。虽然目前国内推广刚起步,但已受到单片机爱好者、从事单片机教学的教师、致力于单片机开发应用的科技工作者的青睐。Proteus是世界上著名的EDA工具(仿真软件),从原理图布图、代码调试到单片机与外围电路协同仿真,一键切换到PCB设计,真正实现了从概念到产品的完整设计。是目前世界上唯一将电路仿真软件、PCB设计软件和虚拟模型仿真软件三合一的设计平台,其处理器模型支持8051、HC11、PIC10/12/16/18/24/30/DsPIC33、AVR、ARM、8086和MSP430等,2010年新增加了Cortex和DSP系列处理器,并持续增加其他系列处理器模型。在编译方面,它也支持IAR、Keil和MPLAB等多种编译器。
本次设计将使用Proteus7.5SP3版本进行仿真。
1.2AT89C51硬件简介
AT89C51芯片是一种带有4K字节闪存的低电压、高性能CMOS8位微处理器,俗称单片机。单片机的可擦除只读存储器可以反复擦除1000次。该器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高而且价格低廉的方案。
本次设计将使用此芯片作为核心硬件进行设计。
1.3设计内容
设计一个由单片机控制的键盘和显示电路,键盘按下,显示屏上可以显示对应数字。通过设计,掌握单片机控制电路设计的步骤、键盘和显示电路的工作原理,进一步提高综合运用知识的能力。
2总体分析设计
2.1电路结构分析
本次设计的目标为单片机控制的键盘识别显示系统,主要采用AT89C51单片机作为核心,由独立键盘电路、显示电路等模块构成,分别对按键信息和显示电路以及软、硬件各个部分进行控制;本设计采用C语言编程来实现对单片机的控制。实际运作时,单片机会将检测到的按键信号转换成数字,显示于1602显示屏上。系统主要结构可以拆分如下:
①独立键盘:按键传送输入信息;由于本次设计有12个按键故直接使用
12个I/O口来对应12个按键;
②
③AT89C51:采用软件编程来实现按键信息的提取和转换;1602显示屏:用于显示最终被单片机转换过的按键信息。
由以上构思可以设计此按键显示电路。
2.2总体方案设计
图2.2为按键控制显示电路系统的总体原理框图:
图2.2整体电路原理方框图
即实验者通过按下键盘的按键来进行信息输入,当有按键被按下时,循环查询程序会识别按键,然后再由单片机AT89C51进行提取与转换,并控制1602显示相应的数据。
2.3总体电路图
总体电路图如图2.3
所示:
图2.3整体电路图
3单元电路设计
3.1键盘输入模块
由于本次任务要求12个按键,故直接使用12个独立键盘,分别接至单片机的P2和P3.1~3.3口,其电路图如图3.1
;
图3.1独立按键
3.2单片机
AT89C51单片机模块是整个电路的核心,时钟信号与复位信号的产生以及程序的处理等任务都是由单片机来完成的。时钟信号用来提供单片机片内各种微操作的时间基准,复位信后用来初始化单片机内部的某些特殊功能寄存器,使CPU及系统各部件处于确定的初始状态,并从初始状态开始正常工作。由于Protues软件自带缺省引脚的信息自动补充功能,本实验中将省略内部时钟电路与外部复位电路。实际引脚连线、时钟源、复位电路的部分如图3.3
;
图3.2AT89C51单片机最小系统
3.31602模块
液晶显示模块具有体积小、低功耗、显示内容丰富的特点,现在字符型液晶
显示模块已经是单片机应用设计中最常见的信息显示器件了。
经过学习已经掌握了液晶屏的使用手法。这里我们在第一行显示所按下的按键是什么按键;第二行显示要求对应的显示内容。
4软件设计与仿真
4.1软件流程图
按键检测方式为程序扫描。所以程序是一个循环的模式。
4.2主系统程序代码
/*********************************************************************
mainfunction
***********************************************************************/voidmain(void)
{LcdInitiate();
while(1)
{
numa=P3&0x0f;
numb=P2;
switch(numa)//用SWITCH语句来分别判断按下去的是什么按键并分别显示
{
case0X0e:a=9;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0X0d:a=0;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
//调用LCD初始化函数
case0X0b:a=888;LCDDIA(a,0x4B);LCDDIB(2);break;
case0X07:a=0;LCDDIA(a,0x4B);LCDDIB(1);break;
case0X0f:break;
default:LCDDIB(3);
}
switch(numb)
{
case0Xfe:a=8;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xfd:a=7;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xfb:a=6;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xf7:a=5;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xef:a=4;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xdf:a=3;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xbf:a=2;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0X7f:a=1;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xff:break;
default:LCDDIB(3);
}
}
}
4.3仿真结果
实验采用Proteus
软件仿真。结果达到了任务书的要求。
按下“开始”按下“0”按下“1
”
按下“5”按下“9”按下“停止”
5心得体会
在为期一周的单片机课程设计中,从选课题查资料,到学软件做仿真,再到检测与调试,我都收获了很多。不光理论知识得到了强化,实践动手能力也被大大增强了,此外我对课程设计的流程也更熟稔了。
在知识方面,我不仅回顾了这个学期所学的单片机技术基础理论知识,也回顾了过去所学的模数电相关的知识;不仅加深了对单片机理论的理解,在与之相关的学科方面也得到了拓展与深化。
此次课程设计,让我对模数电与单片机等科目有了更深入细致的了解。同时我也深深发觉到,仅懂得理论、纸上谈兵是远远不够的,我们还需要进行更多的实物制作,或是软件仿真,因为当理论运用到实际中时,往往会出现很多的问题与偏差。所以这次的实践训练是非常合时并且有意义的,它使我懂得了只有不断实践才能真正掌握知识。
最后感谢指导教师的细心教导,谢谢!
参考文献
[1]张艳兵,赵建华,鲜浩.计算机控制技术.北京:国防工业出版社,2008.
[2]郭天祥.51单片机C语言教程.北京:电子工业出版社,2012.
[3]鲜浩,任爱芝.单片机原理及工程设计方法.北京:国防工业出版社,2012.
[4]李群芳,张士军,黄建等.单片微型计算机与接口技术.电子工业出版社,2009
[5]陈光东,赵性初.单片微型计算机原理与接口技术.华中科技大学出版社,2005
[6]高峰.单片微机应用系统设计及实用技术.机械工业出版社,2004
附录1
原理图
附录2
PCB
附录3程序清单
//按键显示程序设计
#include
#include
#include
sbitRS=P1^0;
sbitRW=P1^1;
sbitE=P1^2;
sbitBF=P0^7;//包含单片机寄存器的头文件//包含随机函数rand()的定义文件//包含_nop_()函数定义的头文件//寄存器选择位,将RS位定义为P2.0引脚//读写选择位,将RW位定义为P2.1引脚//使能信号位,将E位定义为P2.2引脚//忙碌标志位,,将BF位定义为P0.7引脚unsignedintnuma,numb;
unsignedinta,b;
unsignedcharcodeKEY[]={"thekeyis"};//定义字符数组显示数字
unsignedcharcodeNUM[]={"thenumis"};//定义字符数组显示提示信息
/*****************************************************函数功能:延时1ms
(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒***************************************************/voiddelay1ms()
{
unsignedchari,j;
for(i=0;i
for(j=0;j
;
}
/*****************************************************函数功能:延时若干毫秒
入口参数:n
***************************************************/voiddelay(unsignedcharn)
{
unsignedchari;
for(i=0;i
delay1ms();
}
/*****************************************************函数功能:判断液晶模块的忙碌状态
返回值:result。result=1,忙碌;result=0,不忙
***************************************************/unsignedcharBusyTest(void)
{
bitresult;
RS=0;
RW=1;
E=1;
_nop_();
_nop_();
_nop_();
_nop_();
result=BF;
E=0;//空操作四个机器周期,给硬件反应时间//将忙碌标志电平赋给result//将E恢复低电平
//根据规定,RS为低电平,RW为高电平时,可以读状态//E=1,才允许读写//空操作
returnresult;
}
/*****************************************************
函数功能:将模式设置指令或显示地址写入液晶模块
入口参数:dictate
***************************************************/
voidWriteInstruction(unsignedchardictate)
{
while(BusyTest()==1);//如果忙就等待
RS=0;
指令
RW=0;
E=0;//E置低电平(根据表8-6,写指令时,E为高脉冲,
//就是让E从0到1发生正跳变,所以应先置"0"
_nop_();
_nop_();
P0=dictate;
_nop_();
_nop_();
_nop_();
_nop_();
E=1;
_nop_();
_nop_();
_nop_();
_nop_();
E=0;
命令
}
/*****************************************************
函数功能:指定字符显示的实际地址
入口参数:x
***************************************************/
voidWriteAddress(unsignedcharx)
{
WriteInstruction(x|0x80);//显示位置的确定方法规定为"80H+地址码x"
}
11//根据规定,RS和R/W同时为低电平时,可以写入//空操作两个机器周期,给硬件反应时间//将数据送入P0口,即写入指令或地址//空操作四个机器周期,给硬件反应时间//E置高电平//空操作四个机器周期,给硬件反应时间//当E由高电平跳变成低电平时,液晶模块开始执行
/*****************************************************
函数功能:将数据(字符的标准ASCII码)写入液晶模块
入口参数:y(为字符常量)
***************************************************/
voidWriteData(unsignedchary)
{
while(BusyTest()==1);
RS=1;
RW=0;
E=0;//E置低电平(根据表8-6,写指令时,E为高脉冲,
//就是让E从0到1发生正跳变,所以应先置"0"
P0=y;
_nop_();
_nop_();
_nop_();
_nop_();
E=1;
_nop_();
_nop_();
_nop_();
_nop_();
E=0;
}
/*****************************************************
函数功能:对LCD的显示模式进行初始化设置
***************************************************/
voidLcdInitiate(void)
{
unsignedchari;
delay(15);
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x38);
delay(5);
WriteInstruction(0x38);//连续三次,确保初始化成功
delay(5);
WriteInstruction(0x0c);//显示模式设置:显示开,无光标,光标不闪烁
12//RS为高电平,RW为低电平时,可以写入数据//将数据送入P0口,即将数据写入液晶模块//空操作四个机器周期,给硬件反应时间//E置高电平//空操作四个机器周期,给硬件反应时间//当E由高电平跳变成低电平时,液晶模块开始执行命令//延时15ms,首次写指令时应给LCD一段较长的反应时间//显示模式设置:16×2显示,5×7点阵,8位数据接口//延时5ms,给硬件一点反应时间
delay(5);
WriteInstruction(0x06);
delay(5);
WriteInstruction(0x01);
delay(5);
WriteAddress(0x00);
i=0;
while(KEY[i]!='\0')
{
WriteData(KEY[i]);//将第i个字符数组元素写入LCD
i++;
}
WriteAddress(0x40);
i=0;
while(NUM[i]!='\0')
{
WriteData(NUM[i]);//将第i个字符数组元素写入LCD
i++;
}
}
/**************************************
显示程序A用来在KEY和NUM位置显示所按下的按键和对应的显示
********************************************/
voidLCDDIA(unsignedintnum,unsignedintadd)
{unsignedintge,shi,bai;
bai=num%1000/100;
shi=num%100/10;
ge=num%10;
WriteAddress(add);
WriteData('');
WriteData('');
WriteData(bai+0x30);
WriteData(shi+0x30);
WriteData(ge+0x30);
}
/**************************************
显示程序B用来在KEY和NUM位置显示startstoperror
13//显示模式设置:光标右移,字符不移//清屏幕指令,将以前的显示内容清除//写地址,从第1行第0列开始显示//从字符数组的第1个元素开始显示//只要没有显示到字符串的结束标志'\0',就继续//指向下一个数组元素//写地址,从第2行第0列开始显示//从字符数组的第1个元素开始显示//只要没有显示到字符串的结束标志'\0',就继续//指向下一个数组元素//百位//写地址,从add开始显示
********************************************/
voidLCDDIB(charc)
{
{if(c==1)WriteAddress(0x0B);
WriteData('s');
WriteData('t');
WriteData('a');
WriteData('r');
WriteData('t');
}
if(c==2)
{WriteAddress(0x0B);
WriteData('');
WriteData('s');
WriteData('t');
WriteData('o');
WriteData('p');
}
if(c==3)
{WriteAddress(0x0B);
WriteData('e');
WriteData('r');
WriteData('r');
WriteData('o');
WriteData('r');
WriteAddress(0x4B);
WriteData('e');
WriteData('r');
WriteData('r');
WriteData('o');
WriteData('r');
}
}
/*********************************************************************
mainfunction
***********************************************************************/voidmain(void)
14//写地址,从add开始显示//写地址,从add开始显示//写地址,从add开始显示//写地址,从add开始显示
{LcdInitiate();
while(1)
{//调用LCD初始化函数
numa=P3&0x0f;
numb=P2;
switch(numa)//用SWITCH语句来分别判断按下去的是什么按键并分别显示{
case0X0e:a=9;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0X0d:a=0;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0X0b:a=888;LCDDIA(a,0x4B);LCDDIB(2);break;
case0X07:a=0;LCDDIA(a,0x4B);LCDDIB(1);break;
case0X0f:break;
default:LCDDIB(3);
}
switch(numb)
{
case0Xfe:a=8;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xfd:a=7;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xfb:a=6;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xf7:a=5;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xef:a=4;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xdf:a=3;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xbf:a=2;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0X7f:a=1;LCDDIA(a,0x4B);LCDDIA(a,0x0B);break;
case0Xff:break;
default:LCDDIB(3);
}
}
}
15