排队叫号系统方案_单片机实现银行排队叫号系统Proteus仿真

打开大学时期用过的电脑,翻到了当时课程设计——《银行排队叫号系统》分享一下。

一、原理图

c9a57614a8b5a37a0f92d56f34b03419.png

二、代码

/**********************************************************************
* 硬件材料:用M16单片机、4个独立按键(代表四个窗口营业员消号控制端)、
            1个独立按键叫号(顾客使用)、无源蜂鸣器(起到提示作用)以
			及LCD1602显示信息 *
* 目 的:使人们免于排队浪费时间和体力,能在排队的时间里处理个人事务 *
* 用 途:银行的排队,医院的挂号等等 * 
* 功 能:实现自动排队并完成叫号,设置一个排号按键,以及四个柜台用消号
         按键。
		 当按下叫号键时,1.若队列不满,LCD显示"Your No.is 01!"的字样。
		 2.若队列已排满,LCD显示"The queue is full,please wait"的字样。
		 当按下消号键时,1.若队列无人,LCD显示"Sorry,the queue is empty
		 !"的字样。2.若队列有人,蜂鸣器响,LCD显示如"No.01 come to No.1
		 window,please!"的字样。 * 
* 时钟频率:内部1M *
* 编译环境:ICC-AVR6.31 *
* 编 程:Tinyf3 *
* 显 示:用LCD1602显示如"No.01 come to No.1window,please!"的字样 *
* 结 果:实验通过 *
* 
* 要 求:通过控制4个独立按键实现窗口控制消号 ,一个键实现叫号。最大累计
         允许20人排队,当排队人数超过此人数是系统显示停止排队 *
***********************************************************************/
#include <iom16v.h> 
#include <macros.h>

#define uchar unsigned char
#define uint unsigned int

uchar prompt1[]="Your No.is 00!";    //1062第一行显示的字符
uchar prompt2[]="No.00 come to No";  //1062第一行显示的字符
uchar prompt3[]=".0window,please!";  //1062第二行显示的字符
uchar prompt4[]="The queue is";      //1062第一行显示的字符
uchar prompt5[]="full,please wait";  //1062第二行显示的字符
uchar prompt6[]="Sorry,the queue ";  //1062第一行显示的字符
uchar prompt7[]="is empty!";         //1062第二行显示的字符

static uint num_count=0;                  //排队叫的号码
uint rank_number[20]={0};                 //排队叫号存储的数组
uint num=0;                               //窗口消的号码
int RankFlag=0;                           //叫号的标志
int ClearNumFlag=0;                       //消号的标志
static uint LengthFlag=0;                  //队列长度 叫一次号时+1,消一次号时-1
/*****************************************
LCD1602 端口RS、RW、EN的定义
*****************************************/
#define RS_CLR PORTC &= ~BIT(PC4) 
#define RS_SET PORTC |= BIT(PC4)
#define RW_CLR PORTC &= ~BIT(PC5)
#define RW_SET PORTC |= BIT(PC5)
#define EN_CLR PORTC &= ~BIT(PC6)
#define EN_SET PORTC |= BIT(PC6)

/*****************************************
 定义音乐数据二维数组{x,y} 
 x:对应音符音阶的OCR0值,0表示休止符 
 y:对应音符节拍,0表示音乐结束 
 其中0x8A表示音阶6,0xD5表示音阶2
*****************************************/
uint music_data[][2]=
{
{0x8A,600},{0xD5,900},{ 0, 0}
};
/*延时函数*/
void delay_us(unsigned int n) 
{ 
  if (n == 0) 
  {  
    return ;  
  } 
   while (--n);
}
 /*延时函数*/
void delay_ms(unsigned char i) 
{ 
   unsigned char a, b; 
   for (a = 1; a < i; a++) 
     for (b = 1; b; b++);
}
/*****************************************
LCD1602 *显示屏命令写入函数*
*****************************************/
void LCD_write_com(uchar com) 
 {  
   RS_CLR; 
   RW_CLR; 
   EN_SET; 
   PORTA = com; 
   delay_ms(5); 
   EN_CLR;
 }
 /*****************************************
LCD1602 *显示屏命令写入函数*
*****************************************/
void LCD_write_data(uchar data) 
{ 
   RS_SET; 
   RW_CLR; 
   EN_SET; 
   PORTA = data; 
   delay_ms(5); 
   EN_CLR;
}
/*****************************************
LCD1602 *显示屏清空显示*
*****************************************/
void LCD_clear(void) 
{ 
   LCD_write_com(0x01); 
   delay_ms(10);
}

/*****************************************
LCD1602 显示屏初始化函数
*****************************************/
void LCD_init(void) 
{
   DDRA = 0xFF;      /*I/O口方向设置*/ 
//   DDRC|= BIT(PC4) | BIT(PC5) | (BIT(PC6); 
   DDRC |= 0x70;
   LCD_write_com(0x38);    /*显示模式设置*/ 
   delay_ms(10); 
   LCD_write_com(0x38); 
   delay_ms(10); 
   LCD_write_com(0x38); 
   delay_ms(10); 
   LCD_write_com(0x38);  
   LCD_write_com(0x08);    /*显示关闭*/ 
   LCD_write_com(0x01);    /*显示清屏*/ 
   LCD_write_com(0x06);    /*显示光标移动设置*/ 
   delay_ms(10); 
   LCD_write_com(0x0C);    /*显示开及光标设置*/
}

/*****************************************
5按键其键值的读取函数实现 按键1 用来叫号
按键2,3,4,5用做4个窗口消号键
*****************************************/
uint sweep_key()
{  
   uint jianzhi;                      
   DDRD=0x0F;
   PORTD=0xF0;               //行输出低电平,列带上拉电阻输入
   
   delay_us(5); 
   if(PIND==0xF0)
   {
      RankFlag=0;
	  ClearNumFlag=0;;
   }               
   if(PIND!=0xF0)            
   {
      delay_ms(10);          //消斗
	  if(PIND!=0xF0)
      {
         if(PIND==0x70)            
           jianzhi=0;
         else if(PIND==0xB0)        
           jianzhi=1; 
         else if(PIND==0xD0)
           jianzhi=2; 
		 else if(PIND==0xE0)
           jianzhi=3;            
         PORTD=0x0F;               //反转
         DDRD=0xF0; 
         delay_ms(5);
         if(PIND==0x0E)
           jianzhi=jianzhi+1;  
         else if(PIND==0x0D)
           jianzhi=jianzhi+5;
         
	   }
   }
   if(jianzhi==1)                  //使叫号标志有效
      RankFlag=1;
   if(jianzhi>=2 && jianzhi<=5)    //使消号标志有效
      ClearNumFlag=1;
   return(jianzhi);
   }


/*****************************************
叫号机 按一次一号键变量+1,最大为20                        
*****************************************/ 
void QueueNumProcess()
{
   uint i;
   if(RankFlag==1)             //判断叫号标志是否有效
   {
     //n= sizeof(rank_number) / sizeof(rank_number[0]); 
      if ( LengthFlag<20)
      {   
		 num_count++;
	     rank_number[LengthFlag] = num_count;
      }
      LengthFlag++;
   }
}
/*****************************************
窗口消号处理函数
*****************************************/
void ClearNumProcess()
{
   uint i;
   if (ClearNumFlag==1)     //判断消号标志是否有效
   {
      num=rank_number[0];   //把消的号赋给全局变量num
      for(i=0;i<19;i++)     //让数组整体左移一个存储单元,即把消得号删除
      {
	     rank_number[i]=rank_number[i+1];
      }
      LengthFlag--;
   }
}
/*****************************************
检测到按键后,检测函数处理及LCD显示处理
*****************************************/
void CheckButtonProcess(uint m)  //m代表检测到的键值
{ 
   uint jz,i,n;
   jz=m;
   if((jz==1) && (RankFlag==1))
   {  
	   // 当队列人数达到20时,提示
	  // The queue is full,please wait! 
	  if( LengthFlag>=20 )                
	  {
	     LCD_clear();
	     LCD_write_com(0x80+0x02);
         delay_ms(10);
         for(i=0;i<12;i++)
         {
            LCD_write_data(prompt4[i]);
	        delay_ms(10);
         }
		 LCD_write_com(0x80+0x40);
         delay_ms(10);
         for(i=0;i<16;i++)
         {
            LCD_write_data(prompt5[i]);
	        delay_ms(10);
         }  
	  }
	  else
	  {
	     QueueNumProcess();
	     prompt1[11]=(num_count)/10+'0'; 
	     prompt1[12]=(num_count)%10+'0';
	  
	     LCD_clear();
	     LCD_write_com(0x80+0);
         delay_ms(10);
         for(i=0;i<14;i++)
         {
            LCD_write_data(prompt1[i]);  //"Your No.is 00!"; 
	        delay_ms(10);
         }
         RankFlag=0;
	  }
   }
    
   if(jz>=2 && jz<=5 && ClearNumFlag==1)
   {
	  if(LengthFlag==0)
	  {
	     LCD_clear();
	     LCD_write_com(0x80+0);
         delay_ms(10);
         for(i=0;i<16;i++)
         {
            LCD_write_data(prompt6[i]);//"Sorry,the queue ";
	        delay_ms(10);
         }
		 LCD_write_com(0x80+0x40);
         delay_ms(10);
         for(i=0;i<9;i++)
         {
            LCD_write_data(prompt7[i]);//"is empty!"
	        delay_ms(10);
         }  
	  }
	  else
	  {
	     ClearNumProcess();       //消号处理,营业员操作
		 PlayMusic();             //播放一小段音乐,提示
	     prompt2[3]=num/10+'0';
	     prompt2[4]=num%10+'0';
	     LCD_clear();
	     LCD_write_com(0x80+0);
         delay_ms(10);
         for(i=0;i<16;i++)
         {
            LCD_write_data(prompt2[i]); //"No.00 come to No"; 
            delay_ms(10);
         }
	     prompt3[1]=(jz-1)+'0';
	     LCD_write_com(0x80+0x40);
         delay_ms(10);
         for(i=0;i<16;i++)
         {
            LCD_write_data(prompt3[i]); //".0window,please!"; 
	        delay_ms(10);
         }
	     ClearNumFlag=0;
	  }
   }
   
}
/*****************************************
音乐处理函数
*****************************************/
void sound(uchar i)
{
   uint x;
   x=music_data[i][0]; //取音乐的匹配数
   if(x!=0)
   {
      TCNT0=0x00;
      OCR0=x;       //比较值赋值
      TCCR0 = 0x1A; //CTC模式允许比较反转输出OC0
   }
   else
   {
      TCCR0 = 0x00;      //频率为0,休止符,不发声
   }
}
void delayms(uint i)     //节拍延迟
{
   uchar a;
   for(;i;i--) 
   {
      for (a = 220; a; a--) 
      {
        ;
      }
   }
}
/*****************************************
播放音乐函数
*****************************************/
void PlayMusic()
{
   uchar i=0;
   DDRB |= BIT(PB3);
   //PORTB &= ~BIT(PB3);
   while(music_data[i][1]!=0) //等待最后一个音符到来
   {
      sound(i); //输出音符
      delayms(music_data[i][1]);//节拍延时
      TCCR0 = 0x00; //奏完一个音符停止
      i++; //准备一下个音符
   }
}
/*****************************************
main 函数
*****************************************/
void main(void)
{
   uint Kvalue;
   LCD_init();
   while(1)
   {
      Kvalue=sweep_key();       //获取键值
	  if (RankFlag==1 || ClearNumFlag==1)//判断叫号标志和消号标志是否有效
 	     CheckButtonProcess(Kvalue);
	  delay_ms(20);
	  RankFlag=0;             //使叫号标志无效 
	  ClearNumFlag=0;         //使消号标志无效 
	  Kvalue=0;               //键值清0
   }
   
}
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值