基于51单片机的双机串口通信排队叫号系统(LCD显示)设计

1 开发环境

仿真图:proteus8.9以上

程序代码:KEIL4/KEIL5

原理图:AD

设计编号:A0006

视频讲解

基于51单片机的双机串口通信排队叫号系统(LCD显示)设计

2 功能说明介绍

结合实际情况,基于51单片机设计一个排队叫号系统设计。该系统应满足的功能要求为:

由51单片机、按键模块、LCD1602液晶屏、蜂鸣器呼叫模块构成

具体功能:

1、主机通过按键完成叫号,LCD1602液晶显示屏显示被叫的号码及服务的柜台号;同时,蜂鸣器响,以提醒顾客接收服务;

2、从机按下按键实现取号,并通过串行通信方式实现排队取号功能;

3、从机还可以实时显示自己的排队号及及当前正在等待的人数。

3 仿真图

AT89C51是美国ATMEL公司生产的低电压,高性能CMOS16位单片机,片内含4k bytes的可反复擦写的只读程序存储器和128 bytes的随机存取数据存储器,期间采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用16位中央处理器和Flash存储单元,功能强大的AT89C51单片机可灵活应用于各种控制领域。

AT89C51提供以下标准功能:4k字节Flash闪速存储器,128字节内部RAM,32个I/O口线,两个1 6位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。同时,AT89C51可降至0Hz的静态逻辑操作,并支持两种软件可选的节电工作模式。空闲方式停止CPU的工作,但允许RAM,定时/计数器,串行通信口及中断系统继续工作。掉电方式保存RAM中的内容,但振荡器停止工作并禁止其它所有部件工作直到下一个硬件复位。

本系统中央控制器采用的单片机AT89C51,复位电路采用上电复位电路。外接的晶振为12MHz晶振。

img

当前仿真情况为:取号机取了三个号,叫号器的柜台2叫第一个号。叫号过程有蜂鸣器提示。

img

4 程序

工程文件使用Keil4/keil5打开。

代码分为取号机代码和叫号机代码,分别编译产生hex加载到对应的单片机中。

代码

img

叫号机主函数

#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char 
#define uint unsigned int 
sbit RS=P2^0;     //1:数据输入,0:指令输入 
sbit RW=P2^1;    //1: 读出,0:写入 
sbit E=P2^2;      //1:有效,0:无效
sbit key0=P1^0; 
sbit key1=P1^1; 
sbit key2=P1^2; 
sbit key3=P1^3; 
sbit key4=P1^4; 
sbit key5=P1^5;
sbit key6=P1^6; 
sbit key7=P1^7; 
sbit BEEP=P2^6;
uint sev=0; 
uint sev1=0; 
uint sev2=0; 
uint sev3=0; 
uint sev4=0;
uint m=0,i=0;
uint jhao=1,qhao=0,dhao=0;                              //排队叫号                                 //窗口消的号码 
uint jz=0;
uchar data test[]="Hello!";                    //初始显示的字符 
uchar data prompt2[]="No.00 come to No";     //1062第一行显示的字符 
uchar data prompt3[]="0.window,Please!";     //1062第二行显示的字符 
uchar data prompt8[]="00 is left"; 
uchar data prompt9[]="All is 00"; 
uchar data prompt10[]="W1 - 00"; 
uchar data prompt11[]="W2 - 00";
uchar data prompt12[]="W3 - 00"; 
uchar data prompt13[]="W4 - 00"; 
                                  
void intCon()  
{
    
        
	  EA=0;   	   //关总中断
	  SCON=0x50;   //0101 0000,SM0 SM1=01表示选择工作方式1;SM2 REN=01表示串行口多机通讯控制位,串行口允许接收(从外部接收数据)
	  PCON=0X00;   //电源控制寄存器 最高位为SMOD,为0,表示波特率不加倍,为1,表示波特率加倍
	  TMOD=0x20;   //0010 0000,GATE=0,以运行控制位TR启动定时器;采用定时1工作方式2
	  TH1=0xfd;    //波特率9600=2^smod*(11.05926*10^6)/(32*12*(2^8-X))
	  TL1=0xfd;  
	  TR1=1;  		 //计数器工作
  } 
//
 void delay(int n)       //延时子程序 
{
    
     
int k,j;  
 for(k=0;k<=n;k++)  
 for(j=0;j<=10;j++); 
} 
void delay1s(int n)     //延时子程序
 {
    
     
int k,j;  
 for(k=0;k<=n;k++)  
 for(j=0;j<=120;j++); 
}  
void SPEAKER(uint x)   //蜂鸣器程序
 {
    
       
for(i=0;i<=200;i++)    
 {
    
            
delay(x);  
 BEEP=~BEEP;  
 }     
 BEEP=1; }
 /**************LCD程序**********/
 void delay1ms(unsigned int ms)   //延时的时间
{
    
     
uint k,j;  
 for(k=0;k<ms;k++)   
 for(j=0;j<100;j++); 
}
 void LCD_w_com(unsigned com)  // 写入指令 
 {
    
      
RW=0;  
RS=0;
E=1;  
P0=com; 
delay1ms(40);  
E=0; 
RW=1;
} 
void LCD_w_dat(uchar dat)   // 写入数据 
{
    
     

 RW=0; 
 RS=1;  
E=1; 
P0=dat; 
delay1ms(40); 
E=0;  
RW=1; 
}  
void gotoxy(unsigned x,unsigned y)  {
    
      
 if(x==1)  
LCD_w_com(0x80+y); 
 else 
LCD_w_com(0xC0+y); 
} 
void clear_LCD(void) 
{
    
     
LCD_w_com(0x01);       //清屏指令  
LCD_w_com(0x02);      // 光标归位
} 
void init_LCD(void)      // 初始化LCD 
{
    
      
LCD_w_com(0x38);     // LCD为两行显示             
LCD_w_com(0x0c);     // 显示字符  关闭光标 
LCD_w_com(0x06);     // 输入方式设置 
 gotoxy(1,0); 
 for(i=0;i<=5;i++)  
{
    
      
 LCD_w_dat(test[i]); 
 } 
} 
/*********叫号机 按一次一号键变量+1最大为10*************/   
void key()
{
    
             
  if(qhao>jhao)     
{
    
           
 SPEAKER(11); 
     delay(200);    
SPEAKER(15); 
clear_LCD();      

sev++;   
prompt2[3]=(jhao+1)/10+'0';               
prompt2[4]=(jhao+1)%10+'0';      
prompt3[0]=jz+'0';                
gotoxy(1,0);      
for(m=0;m<=15;m++)      
{
    
          
LCD_w_dat(prompt2[m]);      
}      
gotoxy(2,0);      
for(m=0;m<=15;m++)      
{
    
    
LCD_w_dat(prompt3[m]);     
 }         
 jhao++; 
}
}

void k5()
{
    
    
clear_LCD();  
dhao=qhao-jhao;
prompt8[0]=dhao/10+'0';  
prompt8[1]=dhao%10+'0';  
gotoxy(1,0);  
for(m=0;m<=9;m++)  
{
    
      
LCD_w_dat(prompt8[m]);     
}       
}

void k6()
 {
    
         
clear_LCD();   
prompt9[7]=(sev)/10+'0';   
prompt9[8]=(sev)%10+'0';   
gotoxy(1,0);   
for(m=0;m<=8;m++)   
{
    
       
LCD_w_dat(prompt9[m]); 
}  
}

void k7()
{
    
    
clear_LCD();        
prompt10[5]=sev1/10+'0';    
prompt10[6]=sev1%10+'0';    
prompt11[5]=sev2/10+'0';    
prompt11[6]=sev2%10+'0';    
prompt12[5]=sev3/10+'0';    
prompt12[6]=sev3%10+'0';    
prompt13[5]=sev4/10+'0';    
prompt13[6]=sev4%10+'0';     
gotoxy(1,0);    
for(m=0;m<=6;m++)    
{
    
        
LCD_w_dat(prompt10[m]);    
}        
gotoxy(1,8);    
for(m=0;m<=6;m++)    
{
    
        
LCD_w_dat(prompt11[m]);    
}    
gotoxy(2,0);    
for(m=0;m<=6;m++)    
{
    
        
LCD_w_dat(prompt12[m]);    
} 
 gotoxy(2,8);    
for(m=0;m<=6;m++)    
{
    
        
LCD_w_dat(prompt13[m]);    
}    
} 

 //矩阵键盘扫描函数
void matrixkeyscan()
{
    
    	
	unsigned char temp;	
	P1=0xff; //先向P1 口写1;端口读状态
	P1=0xf0; //列送di电平,行送gao电平
	temp=P1;
	if(temp!=0xf0)//判断是否有键按下,若有键按下则temp不等于0xf0
	{
    
    
		delay(10);	// 防抖动
		if(temp!=0xf0)  
		{
    
    
			P1=0xef;  //扫描第一行
			temp=P1;
			switch(temp)
			{
    
    
		 		case(0xe7):{
    
    jz=1;sev1++; key();} ;break; //第一行第一列
				case(0xeb):{
    
    jz=2;sev2++; key();} ;break; //第一行第二列
				case(0xed):{
    
    jz=3;sev3++; key();} ;break;  //第一行第三列
				case(0xee):{
    
    jz=4;sev4++; key();} ;break;  //第一行第四列
			    
             }
			P1=0xdf;
			temp=P1;
			switch(temp)   //扫描第二行
			{
    
    
				case(0xd7):k5();break;	//第二行第一列

				case(0xdb):k6();break;	//第二行第二列

				case(0xdd):k7();break;	//第二行第三列
				
			}
		}
	}
} 
void main() 
{
    
     
    //intCon(); 
    clear_LCD();   
    init_LCD(); 
		jhao=0;
   while(1)  //一直执行
  {
    
       
      
    matrixkeyscan(); 
	  SBUF=jhao;  //叫号送发送存储器  
	  while(!TI);  	//若一帧数据发送完毕,则TI=1,在将 TI置为0,让其处于接收状态  
	  TI=0;     
      if(RI)   //若接收完一帧数据,则RI=1
	  {
    
        
	    RI=0;  //将RI置0,让其处于接收状态  
	    qhao=SBUF;//取号数从接收存储器中取得  
	  }	  
   } 
}

叫号机主程序流程图如下图所示。

img

取号机部分代码:

unsigned long qhao=1,dhao=1,jhao=0;    //分别为取到的人数,等待的人数 叫到的人数 
void intCon() 
 {  
	 EA=0;	   //关总中断
	 SCON=0x50;    //0101 0000,SM0 SM1=01表示选择工作方式1;SM2 REN=01表示串行口多机通讯控制位,串行口允许接收(从外部接收数据)
	 PCON=0X00;   //电源控制寄存器 最高位为SMOD,为0,表示波特率不加倍,为1,表示波特率加倍
	 TMOD=0x20;   	//0010 0000,GATE=0,以运行控制位TR启动定时器;采用定时1工作方式2
	 TH1=0xfd;    //波特率为9600bit/s
	 TL1=0xfd;  
 	 TR1=1;  	 //计数器工作
 } 
void delay(int n)   //延时程序 
{ 
int k,j;   
for(k=0;k<=n;k++)   
for(j=0;j<=10;j++); 
} 
void delay1s(int n)   //延时程序 
{
 int k,j;   
for(k=0;k<=n;k++)   
for(j=0;j<=120;j++); 
}       
  /**************LCD程序**********/
 void delay1ms(unsigned int ms)   //延时的时间
{ 
uint k,j;  
 for(k=0;k<ms;k++)   
 for(j=0;j<100;j++); 
}
 void LCD_w_com(unsigned com)  // 写入指令 
 {  
RW=0;  
RS=0;
E=1;  
P0=com; 
delay1ms(40);  
E=0; 
RW=1;
} 
void LCD_w_dat(uchar dat)   // 写入数据 
{ 

	RW=0; 
	RS=1;  
	E=1; 
	P0=dat; 
	delay1ms(40); 
	E=0;  
	RW=1; 
}  
void gotoxy(unsigned x,unsigned y)  {  
 if(x==1)  
LCD_w_com(0x80+y); 
 else 
LCD_w_com(0xC0+y); 
} 
void clear_LCD(void) 
{ 
LCD_w_com(0x01);       //清屏指令  
LCD_w_com(0x02);      // 光标归位
} 
void init_LCD(void)      // 初始化LCD 
{  
LCD_w_com(0x38);     // LCD为两行显示             
LCD_w_com(0x0c);     // 显示字符  关闭光标 
LCD_w_com(0x06);     // 输入方式设置 
 gotoxy(1,0); 
 for(i=0;i<=7;i++)  
{  
 LCD_w_dat(test[i]); 
 } 
} 

// 判断取号键被按下
void panduan_01() 	
{  
   if(K1==0)  
    { delay(10);    //防抖
      if(K1==0)   
			{    
          if(qhao>99)  
					{
						EA=0;  
						delay1s(5000);      
						clear_LCD();      
						gotoxy(1,2);   
					for(m=0;m<=11;m++)   
					{    
						LCD_w_dat(prompt4[m]);      
					}    
					gotoxy(2,0);   
					for(m=0;m<=15;m++)   
					{    
						LCD_w_dat(prompt5[m]);  //提示队列已满      
					}     
					} 	
					else
					{
						clear_LCD();     
						prompt1[11]=(qhao)/10+'0';       
						prompt1[12]=(qhao)%10+'0';    
						qhao++;    
						gotoxy(1,0);  
						for(m=0;m<=13;m++)   
						{   
							LCD_w_dat(prompt1[m]); //"Your No.is 00!"; 
						}   
					} 
					dhao=qhao-jhao;    //等待的人数=人数-叫的人 
					prompt8[0]=(dhao-1)/10+'0';  
					prompt8[1]=(dhao-1)%10+'0';  
					gotoxy(2,0);				
					for(m=0;m<=9;m++)  
					{  
						LCD_w_dat(prompt8[m]);     
					} 
			}
	}
	 while(K1==0);   
	
}
//判断等待的人数键被按下 ,按下显示等待的人数,松开后显示取到的号码 
void panduan_02() 
{   
   if(K2==0)  
    { delay(10);   //防抖
      if(K2==0)   
			{ 
					dhao=qhao-jhao;    //等待的人数=人数-叫的人
					clear_LCD();  
					prompt8[0]=dhao/10+'0';  
					prompt8[1]=dhao%10+'0';  
					gotoxy(2,0);				
				for(m=0;m<=9;m++)  
				{  
					LCD_w_dat(prompt8[m]);     
				}    

	   }  
	 }   
	
}  
void main(void) 
{ 
    clear_LCD();       
		init_LCD();
    intCon(); 
		jhao=0;
    while(1)  
     {   
		if(K1==0)  
	    panduan_01();
			SBUF=qhao;		//取号送发送存储器
		while(!TI);   	//若一帧数据发送完毕,则TI=1,在将 TI置为0,让其处于接收状态
		TI=0;
		if(RI) //若接收完一帧数据,则RI=1  
	    {    
		    RI=0; //将RI置0,让其处于接收状态   
		    jhao=SBUF;  //叫号数从接收存储器中取得  
	    }		
		 if(K2==0)	   
				panduan_02();  	   
	   } 	   
}

取号机取号程序流程:

img

5 原理图

原理图由AD绘制,原理图和仿真图有出入,原理图需要电源,电源开关模块。此设计资料详细,硬件手册资料图片详细,不对硬件调试负责,做实物需要一定的基本功。主控芯片可以换为STC89C51/STC89C52

img

如图3.1是本系统的硬件设计方案,具体地,主机及从机硬件电路由以下模块构成:

(1)单片机最小系统。用于驱动和控制其他模块,以实现整体功能,其以AT89C51单片机为核心芯片,并辅以复位电路和晶振电路。

(2)按键模块。主机按键由四个矩阵按键构成,代表不同的柜台;从机按键由一个按键构成,用于顾客取号;

(3)显示模块。主机通过LCD1602液晶显示屏显示被叫的号码及服务的柜台号; 从机通过LCD1602液晶显示屏显示自己的排队号;

(4)蜂鸣器模块。用以提醒顾客接收服务;

img

(5)电源模块。用于整个系统的供电。

6 视频讲解

代码讲解+仿真讲解+仿真演示+原理图讲解

7 设计报告

排队论(又称随机服务系统)是研究系统由于随机因素的干扰而出现排队(或拥塞)现象的规律的一门学科,它适用于一切服务系统,包括公共服务系统、通信系统、计算机系统等。可以说,凡是出现拥塞现象的系统,都属于随机服务系统。一个对象通过拥塞系统接受服务必须经过三个环节,即到达、排队等候处理、接受服务和离去。例如在医院中,排队流程如下:患者在挂号的同时领取排队号码,然后到候诊区候诊;当为前一患者完成诊断后,医生通过本系统呼叫队列中下一位患者,患者就可直接到空闲诊室行排队等候服务。

另一个方面,伴随着服务行业业务量不断增长,业务种类日益增多,排队等候已成为人们经常面临的实际问题。在银行,医院,电信,税务,工商等营业大厅里,前拥后挤,杂乱无章的排队等候,已是司空见惯的现象,影响了服务质量。因此,改善服务质量,树立良好的企业形象,解决客户劳累的排队现象,创造人性化服务环境已成为急需解决的问题。设计一套排队抽号的服务系统,可以很好的解决因排队引起的种种问题。

本系统通过AT89C51单片机直接扩展独立键盘,完成排队取号流程,单片机控制LCD1602显示排队等待情况,控制蜂鸣器发声完成叫号功能。该系统有良好的人机交互界面,模拟排队管理,科学地处理各种排队情况,操作简便,控制灵活,显示清晰,制作成本低,性价比较高。

7.1 设计目的

(1)巩固和加深对单片机原理和接口技术知识的理解;

(2)培养根据课题需要选学参考书籍、查阅手册和文献资料的能力;

(3)学会方案论证的比较方法,拓宽知识,初步掌握工程设计的基本方法;

(4)掌握常用仪器、仪表的正确使用方法,学会软、硬件的设计和调试方法;

(5) 能按课程设计的要求编写课程设计报告,能正确反映设计和实验成果,能用计算机绘制电路图、仿真图和流程图。

7.2 设计要求及内容

(1)主机通过按键完成叫号,LCD1602液晶显示屏显示被叫的号码及服务的柜台号;同时,蜂鸣器响,以提醒顾客接收服务;

(2)从机按下按键实现取号,并通过串行通信方式实现排队取号功能;

(3)从机还可以实时显示自己的排队号。

7.3 本文结构安排

本文围绕着基于51单片机的排队叫号系统展开设计,以排队叫号需求为出发点,首先明确了研究背景与意义,介绍了设计目的,并论述了设计要求及设计内容,接下来的几章将具体展开相关设计与研究:

第二章介绍系统总体方案及相关理论知识,重点阐述了系统功能需求和系统方案论证,接着简要介绍了系统硬件及软件基本知识。

第三章重点展开硬件系统设计,首先明确主机及从机硬件电路设计的思路及框架。接着依次介绍了:单片机最小系统、按键电路、LCD1602显示电路、蜂鸣器提醒电路、电源电路等。通过对以上重点电路的介绍,强化了硬件电路设计的细节和重点。

第四章展开软件系统设计,通过对软件设计进行需求分析,明确软件设计的目的与需求,进一步通过程序流程图展示设计思路及框架。接着依次介绍了主函数流程、从机取号流程、主机叫号程序流程、蜂鸣器提醒流程。

第五章介绍仿真实现步骤,特别是仿真电路实现的流程和仿真测试,完美实现了设计需求及目标。

第六章总结全文,总结本文所做的工作及贡献,并根据存在的问题展望此课题今后的研究方向。

img

资料清单下载链接

见文章视频

img

本资料下载链接:

猜你喜欢

转载自blog.csdn.net/Jack_0220/article/details/128754249