一、整体功能概述
本程序基于 STC8 系列单片机搭建单路优先抢答锁存系统,配备 7 路抢答按键、1 路复位解锁按键、1 位共阳极数码管、有源 / 无源蜂鸣器。系统分为等待抢答(未上锁)、** 抢答锁定(已上锁)** 两种工作状态,实现抢答优先锁定、抢答编号显示、声光提示、一键复位重置全套抢答逻辑,适用于小型课堂、竞赛简易抢答场景。
二、硬件资源分配
- 抢答按键(P2 口输入,低电平触发)KEY1~KEY7:7 路选手抢答按键,分别对应 1~7 号参赛选手; KEY_RST (P2^0):系统复位解锁按键;
- 显示模块P0 口直驱 1 位共阳极数码管,仅显示 0~7 数字;
- 声光提示P3^6 控制蜂鸣器,通过高频方波发声做抢答、解锁提示;
- IO 配置:P2 全端口高阻输入(按键),P0、P3 准双向输出。
三、两种工作模式详细功能
模式 1:未上锁(等待抢答状态,flag_lock=0,默认上电状态)
- 数码管默认显示数字
0,代表暂无选手抢答; - 程序循环扫描 KEY1~KEY7 全部抢答按键;
- 任意选手按下对应抢答键后执行锁定逻辑: 1)立即置位上锁标志
flag_lock=1,系统进入抢答锁定; 2)数码管切换为当前抢答选手编号(按 KEY1 显示 1、KEY2 显示 2……KEY7 显示 7); 3)蜂鸣器持续发声提示抢答成功,1 号键提示音时长更长,2~7 号提示音较短; 4)按键松手前持续阻塞扫描,避免重复触发; - 锁定后立刻屏蔽所有抢答按键,其余后按下按键无任何响应,保证先按优先。
模式 2:已上锁(抢答锁定状态,flag_lock=1)
- 系统不再检测 KEY1~KEY7 所有抢答按键,后续选手抢答操作无效;
- 数码管保持显示最先抢答选手的编号;
- 仅响应复位解锁按键 KEY_RST: 1)按下复位键消抖确认后,清除上锁标志
flag_lock=0; 2)数码管清零回到显示 0; 3)蜂鸣器短音提示解锁完成; 4)等待复位键松手,系统自动回到等待抢答模式,开启下一轮抢答。
四、配套辅助功能
- 按键消抖:所有按键按下均加入 10ms 延时消抖,避免机械按键抖动误触发;
- 数码管边界保护:仅 0~7 号数字输出有效段码,超出范围数码管全熄灭,防止数组越界;
- 蜂鸣器控制:发声结束自动拉低电平关闭,避免持续异响;
- 上电初始化:开机自动关闭蜂鸣器、清零显示、解锁待命,
无需手动复位。#include <STC8.H> typedef unsigned char uchar; typedef unsigned int uint; // IO引脚定义 sbit KEY1 = P2^7; sbit KEY2 = P2^6; sbit KEY3 = P2^5; sbit KEY4 = P2^4; sbit KEY5 = P2^3; sbit KEY6 = P2^2; sbit KEY7 = P2^1; sbit KEY_RST = P2^0; // 复位解锁按键 sbit BEEP = P3^6; // 蜂鸣器输出 // 共阳极数码管段码 0~7 uchar code seg_table[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8}; bit flag_lock = 0; // 上锁标志 0未锁 1已锁 uchar num = 0; // 当前显示数字 0~7 // 10us延时函数 void delay_10us(uchar ten_us) { while(ten_us--); } // ms级延时 void delay_ms(uint ms) { uint i,j; for(i = ms; i > 0; i--) for(j = 1100; j > 0; j--); } // 数码管显示函数:无锁存P0直出段码 void display(uchar dat) { if(dat <= 7) // 边界保护,防止数组越界 P0 = seg_table[dat]; else P0 = 0xFF; // 超出0~7全灭 } // 蜂鸣器短促报警函数,n为发声时长 void alarmBeep(uchar nums) { while(nums > 0) { BEEP = !BEEP; delay_10us(500); nums--; } BEEP = 0; // 关闭蜂鸣 } // 按键扫描函数 void key_scan(void) { // 上锁状态:只检测复位解锁键 if(flag_lock == 1) { if(KEY_RST == 0) { delay_ms(10); // 消抖 if(KEY_RST == 0) { flag_lock = 0; num = 0; BEEP = 0; alarmBeep(100); // 解锁提示音 while(KEY_RST == 0); // 等待松手 } } return; // 上锁后不再扫描数字按键 } // 未上锁状态,扫描1~7数字按键 if(KEY1 == 0) { delay_ms(10); if(KEY1 == 0) { flag_lock = 1; num = 1; alarmBeep(800); // 上锁长报警提示 while(KEY1 == 0); } } else if(KEY2 == 0) { delay_ms(10); if(KEY2 == 0) { flag_lock = 1; num = 2; alarmBeep(300); while(KEY2 == 0); } } else if(KEY3 == 0) { delay_ms(10); if(KEY3 == 0) { flag_lock = 1; num = 3; alarmBeep(300); while(KEY3 == 0); } } else if(KEY4 == 0) { delay_ms(10); if(KEY4 == 0) { flag_lock = 1; num = 4; alarmBeep(300); while(KEY4 == 0); } } else if(KEY5 == 0) { delay_ms(10); if(KEY5 == 0) { flag_lock = 1; num = 5; alarmBeep(300); while(KEY5 == 0); } } else if(KEY6 == 0) { delay_ms(10); if(KEY6 == 0) { flag_lock = 1; num = 6; alarmBeep(300); while(KEY6 == 0); } } else if(KEY7 == 0) { delay_ms(10); if(KEY7 == 0) { flag_lock = 1; num = 7; alarmBeep(300); while(KEY7 == 0); } } } void main(void) { // IO口模式配置 STC8寄存器 P0M0 = 0x00; P0M1 = 0x00; // P0准双向输出 数码管段码 //P1M0 = 0x00; P1M1 = 0x00; // P1闲置准双向 P2M0 = 0xFF; P2M1 = 0x00; // P2全部高阻输入 按键 P3M0 = 0x00; P3M1 = 0x00; // P3准双向 蜂鸣器 BEEP = 0; // 开机关闭蜂鸣 flag_lock = 0; num = 0; // 主循环:持续扫键+刷新显示 while(1) { key_scan(); display(num); } }
五、工作流程总结
上电初始化 → 数码管显示 0,等待抢答 → 任意选手按键抢答 → 锁定系统、显示选手编号、蜂鸣提示、屏蔽其他按键 → 主持人按下复位键解锁 → 数码管清零,重新进入抢答等待循环。