在网上没能容易地直接找到仿真文件,所以我把这个上传,希望对各位有所帮助。
倒是有不少好心人给出了图文教学和源代码,对他们表示感谢。我也是用这位老哥的代码和电路稍作了修改,感谢分享。
简要介绍图中各按钮的作用:
起初 led 数码管是熄灭的,按下 P2.1 的按钮会将它们点亮,开始抢答。
抢答开始后 P2 口按钮失效。按下 P1 口按钮后将在右侧数码管显示对应的选手号码,这时计时将暂停,按下 P2.0 按钮表示回答正确,3 秒左右后数码管熄灭,准备下一轮抢答;按下 P2.1 按钮继续这轮抢答·。
时间耗尽时,暂停 3 秒左右,之后计时器熄灭,准备下一轮抢答。
代码:
#include <reg51.h>
#define RAT 30 // 抢答时间 rush to answer time
sbit DIN = P3 ^ 0; // 与MAX7219的接口引脚定义
sbit LOAD = P3 ^ 1;
sbit CLK = P3 ^ 2;
sbit key0 = P1 ^ 0; // 定义8路抢答器按键
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 speaker = P0 ^ 0;
sbit keyClear = P2 ^ 0; // 主持人的“清除/设置时间”按键
sbit begin = P2 ^ 1; // 主持人开始按键
sbit sounder = P3 ^ 7; // 蜂鸣器相连的引脚
unsigned char second = RAT; // 秒表计数值
unsigned char counter = 0; // counter 每计100,minite加1
unsigned char people = 0; // 抢答结果
unsigned char numAdd[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}; // MAX7219的读写地址
unsigned char numDat[] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89};
unsigned char keyScan() { // 键盘扫描函数
unsigned char keyValue, temp;
keyValue = 0;
P1 = 0xff; // P1口的8个引脚设置为输入
temp = P1;
if (~(P1 & temp)) { // 如P1口的引脚电平发生变化,有键按下
switch (temp)
{
case 0xfe: // 如P1.0口的引脚电平为低,则S1键按下
keyValue = 1;
break;
case 0xfd: // 如P1.1口的引脚电平为低,则S2键按下
keyValue = 2;
break;
case 0xfb: // 如P1.2口的引脚电平为低,则S3键按下
keyValue = 3;
break;
case 0xf7: // 如P1.3口的引脚电平为低,则S4键按下
keyValue = 4;
break;
case 0xef: // 如P1.4口的引脚电平为低,则S5键按下
keyValue = 5;
break;
case 0xdf: // 如P1.5口的引脚电平为低,则S6键按下
keyValue = 6;
break;
case 0xbf: // 如P1.6口的引脚电平为低,则S7键按下
keyValue = 7;
break;
case 0x7f:
keyValue = 8; // 如P1.7口的引脚电平为低,则S8键按下
break;
default:
keyValue = 0;
break;
}
}
return keyValue; // 返回键号
}
void secondIniter() {
second = RAT;
}
void max7219Send(unsigned char add, unsigned char dat) { // 向MAX7219写命令函数
unsigned char ADS, i, j;
LOAD = 0;
i = 0;
while (i < 16) {
if (i < 8) {
ADS = add;
} else {
ADS = dat;
}
for (j = 8; j >= 1; j--) {
DIN = ADS & 0x80;
ADS <<= 1;
CLK = 1;
CLK = 0;
}
i += 8;
}
LOAD = 1;
}
void max7219Init() { // MAX7219初始化函数
max7219Send(0x0c, 0x01);
max7219Send(0x0b, 0x07);
max7219Send(0x0a, 0xf5);
max7219Send(0x09, 0xff);
}
void max7219Shutdown() { // MAX7219关闭函数
max7219Send(0x0C, 0x00); // 发送关闭命令给MAX7219
}
void timeDisplay(unsigned char x) { // 时间显示函数
unsigned char i, j;
i = x / 10;
j = x % 10;
max7219Send(numAdd[1], numDat[j]);
max7219Send(numAdd[0], numDat[i]);
}
void scareDisplay(unsigned char x) { // 显示抢答结果函数
unsigned char i, j;
i = x / 10;
j = x % 10;
max7219Send(numAdd[3], numDat[j]);
max7219Send(numAdd[2], numDat[i]);
}
void delayMs(unsigned int ms) { // 延时函数
unsigned int i, j; // 定义两个循环变量
for (i = 0; i < ms; i++) // 外层循环控制毫秒数
for (j = 0; j < 112; j++)
; // 内层循环控制微秒数,具体值要根据晶振频率和编译器优化程度调整
}
void mkNoi(char modle) { // 开始和结束时播放
int i;
for (i = 0; i < 400 / modle; i++) {
speaker = ~speaker;
delayMs(modle);
}
}
void bingo() { // 答对了要播放这个
int i, j;
for (i = 4; i > 0; i--) {
for (j = 0; j < 200 / i; j++) {
speaker = ~speaker;
delayMs(i);
}
}
}
void holderScan() { // 函数功能:设置抢答时间为0~60s
timeDisplay(second); // 时间显示
scareDisplay(people);
if (~keyClear) { // 如果回答正确,开始下一轮抢答
while (~keyClear)
;
bingo();
secondIniter(); // 抢答器重置
delayMs(3000);
timeDisplay(second); // 显示重置后的时间
people = 0;
scareDisplay(people); // 显示重置后的抢答区
max7219Shutdown();
}
}
void timerInit() { // 定时器T0初始化
EA = 1;
ET0 = 1;
TMOD = 0x01; // 定时器T0方式0定时
TH0 = 0xd8; // 装入定时初值,10ms中断一次
TL0 = 0xef;
}
void main() { // 主函数
while (1) {
do{
holderScan();
} while (begin); // 若未按下“开始”键,则循环
while (~begin)
; // 若按下“开始”键,则往下执行
mkNoi(1);
max7219Init(); // MAX7219初始化
timerInit(); // 定时器T0中断初始化
TR0 = 1; // 启动定时器T0
do {
timeDisplay(second); // 显示时间
scareDisplay(people); // 显示抢答结果
people = keyScan();
} while ((!people) && (second)); // 运行直到抢答结束或者时间结束
TR0 = 0;
if (!second) { // 回合结束
timeDisplay(second);
mkNoi(2);
delayMs(3000);
secondIniter();
max7219Shutdown();
}
}
}
void timer0() interrupt 1 { // 定时器T0中断函数
if (counter < 100) {
counter++;
if (counter == 50) {
sounder = 0; // 蜂鸣器发出声响
}
} else {
sounder = 1;
counter = 0;
second--;
}
TH0 = 0xd8; // 重新装载定时初值
TL0 = 0xef;
TR0 = 1; // 启动T0
}
下载链接:
度盘: https://pan.baidu.com/s/1YU4sybDi_oqA3SSCCIHoGw?pwd=jmvg 提取码: jmvg 复制这段内容后打开百度网盘手机App,操作更方便哦
https://cloud.lilywhite.cc/s/7RrSA 文章来源:https://www.toymoban.com/news/detail-494072.html
希望自己没有损失的情况下,能有更多人随手分享^^文章来源地址https://www.toymoban.com/news/detail-494072.html
到了这里,关于proteus 仿真 at89c51 单片机八位抢答器,文末附源文件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!