00 读题
客户端:
1.取号功能:通过按键完成取号。
2.显示:数码管显示号码和当前等待人数。
主机:
1.报号功能:通过串口发出报号指令。
2.显示:数码管显示叫到的号码,蜂鸣器发出蜂鸣声。
01 分析功能:
2. 系统工作原理
- 客户端和主机通过串口进行通信。客户端用户按下取号按键,人数减一.
- 客户端接收到号码后,显示排第一的号码和等待人数。
- 主机接收到取号指令后,发出报号指令,并显示号码在数码管上,同时通过蜂鸣器发出提示音。
1.使用到51单片机、数码管、蜂鸣器和按键、串口、
2.在客户端(单片机),按键触发取号操作并显示号码。
3.在主机(电脑),通过串口接收取号指令,发出报号指令并显示号码。
按我们的理解是
默认显示“排第一个”人的号码
当串口输入号码时显示刚收到的号码
02 系统硬件设计
客户端:
- 按键输入:用于“取号”操作。
- 数码管显示:用于显示取号号码和当前排队人数。
- 蜂鸣器:用于在报号时发出提示音。
- 串口通信:用于客户端和主机之间的通信,发送和接收号码。
03 实现步骤
步骤 1:硬件初始化
-
初始化51单片机:
- 配置I/O口,数码管的控制端口(如P1.0~P1.2)和按键的输入端口(如P2)。
sbit ADDR0 = P1^0; //LED位选译码地址引脚0 sbit ADDR1 = P1^1; //LED位选译码地址引脚1 sbit ADDR2 = P1^2; //LED位选译码地址引脚2 sbit ADDR3 = P1^3; //LED位选译码地址引脚3 sbit ENLED = P1^4; //LED显示部件的总使能引脚 sbit KEY1 = P2^4; sbit KEY2 = P2^5; sbit KEY3 = P2^6; sbit KEY4 = P2^7; sbit KEYout = P2^3; KEYout = 0; P0 = 0xFF; ENLED = 0; //使能U3 ADDR3 = 1;
- 初始化串口通信,以便客户端和主机之间的数据传输。
void ConfigUART(unsigned int baud) { SCON = 0x50; //配置串口为模式1 TMOD &= 0x0F; //清零T1的控制位 TMOD |= 0x20; //配置T1为模式2 TH1 = 256 - (11059200/12/32)/baud; //计算T1重载值 TL1 = TH1; //初值等于重载值 ET1 = 0; //禁止T1中断 ES = 1; //使能串口中断 TR1 = 1; //启动T1 }
- 初始化蜂鸣器的控制端口,用于发出声音。
sbit BUZZ = P1^6; //蜂鸣器控制引脚
- 配置I/O口,数码管的控制端口(如P1.0~P1.2)和按键的输入端口(如P2)。
-
初始化数码管:
- 数码管用于显示号码和当前等待人数。你可以使用6段数码管显示数字(0-9)。
void ShowLedNumber(unsigned char index, unsigned char num, unsigned char point) { LedBuff[index] = LedChar[num]; //输入数字转换为数码管字符0~F if (point != 0) { LedBuff[index] &= 0x7F; //point不为0时点亮当前位的小数点 } }
- 数码管用于显示号码和当前等待人数。你可以使用6段数码管显示数字(0-9)。
-
初始化蜂鸣器:
- 蜂鸣器的控制可以通过直接控制GPIO口进行。
BUZZ = 0; Delay_ms(delay); BUZZ = 1;
- 蜂鸣器的控制可以通过直接控制GPIO口进行。
步骤 2:客户端功能
-
按键触发取号功能:
- 配置按键扫描,检测用户按下“取号”按钮。
if( (keybuf == 1)&&( people>=1 ) ) { BuzzPlay( 500); if( mode==1 ) { people--; if( people ==0) { for ( j=0;j<=limt-1;j++ ) { mark[j][0]=0; } numall = 0; } } else if( mode==0 )mode=1;//设置只有在显示第一个排队的人的时候才可取号 }
3.另外可通过按键2切换查看队首或队尾
else if(keybuf == 2) { BuzzPlay( 500); mode = (mode>=1)?0:1;//若mode已经=1则令mode=0,反之亦反, }
-
显示取号号码和当前等待人数:
- 显示当前号码。每次取号时,号码递增(可以从1开始,递增显示)。
- 显示当前的等待人数。每当取号操作发生,等待人数减1。
if( flag1s ==1 ) { flag1s = 0; if( mode==0 )//显示排最后的 { ShowLedNumber(0, mark[numall][0]%10, 0); ShowLedNumber(1, mark[numall][0]/10%10, 0); ShowLedNumber(2, mark[numall][0]/100%10, 0); }else if( mode ==1 )//显示排第一的 { ShowLedNumber(0, mark[numall-people+1][0]%10, 0); ShowLedNumber(1, mark[numall-people+1][0]/10%10, 0); ShowLedNumber(2, mark[numall-people+1][0]/100%10, 0); } LedBuff[3] &= 0xbf; //点亮- ShowLedNumber(4, people%10, 0); ShowLedNumber(5, people/10%10, 0); } /* T0中断服务函数,执行数码管扫描显示 */ void InterruptTimer0() interrupt 1 { static unsigned char i = 0; //动态扫描的索引 static unsigned char tmr1s = 0; TH0 = T0RH; //加载T0重载值 TL0 = T0RL; tmr1s++; //中断次数计数值加1 if (tmr1s >= 100) //中断1000次即1秒 { tmr1s = 0; //清零计数值以重新开始下1秒计时 flag1s = 1; //设置1秒定时标志为1 } //以下代码完成数码管动态扫描刷新 if (ENLED == 0) //LED使能时才进行动态扫描 { P0 = 0xFF; //关闭所有段选位,显示消隐 P1 = (P1 & 0xF8) | i; //位选索引值赋值到P1口低4位 P0 = LedBuff[i]; //缓冲区中索引位置的数据送到P0口 if (i < 5) //索引递增循环,遍历整个缓冲区 i++; else i = 0; } }
步骤 3:主机功能
-
报号功能(串口接收指令):
- 主机发送一个新的号码,并通过串口返回给客户端。
- 主机发送一个新的号码,并通过串口返回给客户端。
-
显示叫号和触发蜂鸣器:
- 主机根据接收到的号码,在数码管上显示当前叫到的号码。
- 同时,通过蜂鸣器发出提示音,提醒用户该号码已被叫到。
/* UART中断服务函数 */ void UART_Handler(void) interrupt 4 { int RxdByte; char gData; if (RI) //接收到字节 { RI = 0; //手动清零接收中断标志位 gData = SBUF; //接收到的数据保存到接收字节变量中 //flag=1; if(gData == '@') { RxdByte = 0; } else if( (gData == '#')||(gData == ' ') ) { people++, numall++; mark[people][0] = RxdByte; Serial_SendNumber(mark[people][0], 4); BuzzPlay( 500); mode = 0; } else { RxdByte = RxdByte*10 + (gData - '0'); } //Serial_SendNumber( Min_Limit, 2); } if (TI) //字节发送完毕 { TI = 0; //手动清零发送中断标志位 } }
步骤 4:串口通信协议
-
串口通信设计:
- 客户端和主机之间通过串口通信进行数据传输。可以使用简单的通信协议,例如:主机发送到客户端(如“@101#”表示号码为101)。
-
数据格式设计:
- 可以通过串口发送数据包
---对应123号码。客户端可以根据返回的号码更新显示。@123#
- 可以通过串口发送数据包
如果需要指导帮助,可以添加我的QQ或者加入我的新建的交流群
2796920378