概述
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 设计目的
- 代码实现
- 仿真图
设计目的
设计一个四位抢答器与计分系统。
模拟四位抢答器与计分系统,实现倒计时抢答,选择自己所选选项,统计所得分数等功能。
(1)抢答器同时供四名选手或四个代表队使用,分别用一号,二号,三号,四号四个按钮表示。
(2)设置一个抢答开始控制开关,该开关由主持人控制。开关按下开始倒计时30s,有人抢答后就停止倒计时。
(3)抢答器具有锁存与显示的功能。即按下开始按键后,选手按下抢答按钮,锁存相应的编号,且优先抢答的选手的编号会一直保存至下一次抢答开始。
(4)抢答后选手应该给出自己的答案,并通过A,B,C,D四个按钮选择选项,同时显示器会显示所选答案。
(5)回答问题给出选项后,主持根据正确答案对相应选手进行加分或减分(开始时全部选手以十分为底,答对一题加一分,答错扣一分,最少总分为零分。)若回答正确绿灯亮,回答错误红灯亮。
(6)四个显示器分别显示对应选手的总得分。
二、代码实现
代码如下(示例):
#include "regx52.h"
#include <intrins.h>
sbit DIN=P3^0;// 串行数据输入端
sbit LD=P3^1;// 装载数据信号输入端
sbit CLK=P3^2;// 移位脉冲输入端
sbit begin=P3^6;//开始按钮
sbit led1=P2^4;
sbit led2=P2^5;
unsigned char a=10,b=10,c=10,d=10,e=0;
unsigned char choice=15;//选项,没选时显示为灭
unsigned char second=30;//倒计时时间
unsigned char counter=0;//记录中断次数
unsigned char number=0;
unsigned char people=0;//选手编号
unsigned char num_add[]={0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};//max7219读写地址,内容。
unsigned char num_dat[]={0x7e,0x30,0x6d,0x79,0x33,0x5b,0x5f,0x70,0x7f,0x7b};//非译码方式时的共阴数码管显示编码,0-9
unsigned char NixieTable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x40,0x00};//共阴数码管显示编码,0-9,a-d,- 灭
void delay(unsigned int xms)//延时函数
{
unsigned char i, j;
while(xms--)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
}
}
unsigned char shuzi()//键盘扫描函数(按列扫描),并返回对应的键值。
{
unsigned char i;
unsigned int temp;
P1=0xfe;
for(i=4;i>0;i--)
{
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
switch(temp)
{
case 0x70:number=i;
break;
case 0xb0:number=i+4;
break;
case 0xd0:number=i+8;
break;
case 0xe0:number=i+12;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
temp=P1;
temp=temp|0xf0;
temp=_crol_(temp,1);
P1=temp;
}
return number;
}
void Nixie(unsigned char Location,Number)//四位数码管动态显示,Nixie(unsigned char Location,Number),第一个参数显示的位码,第二个为显示的段码
{
switch(Location)
{
case 4:P2_3=1;P2_2=1;P2_1=1;P2_0=0;break;
case 3:P2_3=1;P2_2=1;P2_1=0;P2_0=1;break;
case 2:P2_3=1;P2_2=0;P2_1=1;P2_0=1;break;
case 1:P2_3=0;P2_2=1;P2_1=1;P2_0=1;break;
}
P0=NixieTable[Number];
delay(1);
P0=0x00;
}
void people_display()//选手编号显示,在四位数码管的第一位(最高位)显示选手编号
{Nixie(4,people);
}
void xuanxiang_display()//选手选项显示,在四位数码管的第二位显示选手选项
{Nixie(3,choice);
}
void time_display(unsigned char x)//倒计时时间显示函数
{ unsigned char i,j;
i=x/10;
j=x%10;
Nixie(2,i);
Nixie(1,j);
}
void max7219_send(unsigned char addr,unsigned char wdata)//向max7219写命令
{
unsigned char temp,i=1,j,k;
LD=0;
while(i<16)
{
if(i<8) {temp=addr;} //先写入MAX7219内部寄存器地址,再向内部寄存器写入操作数值
else {temp=wdata;}
for(j=0;j<8;j++)
{
CLK=0;
if((temp&0x80)==0x80) DIN=1; //先发送数据的最高位
else DIN=0;
for(k=5;k>0;k--); //时钟频率高的单片机需曾加延时时间,此处为12MHz
CLK=1;
for(k=5;k>0;k--);
temp<<=1;
}
i+=8;
}
LD=1;
}
void max7219_init()//max7219初始化
{
max7219_send(0x0a,0x07); //显示亮度,取值范围0~f
max7219_send(0x0b,0x07);//8位扫描显示,取值范围0x01~0x07
max7219_send(0x09,0x00);//译码方式,0x00为不译码,0xff为译码
max7219_send(0x0c,0x01); //操作方式,0x00为低功耗模式,0x01为正常操作模式
max7219_send(0x0f,0x00); //显示状态,0x00为正常显示,0x01为显示测试
}void timer_init()//定时器T0初始化
{ EA=1;//总中断允许
ET0=1;//允许定时器T0中断
TMOD=0x01;//定时器T0方式1定时
TH0=0xd8;//设置10毫秒中断一次
TL0=0xf0;//0xd8f0=55536,65536-55536=10000us=10ms
}
void timer0() interrupt 1//定时器T0中断函数,进行100次中断,即用时1s
{
if(counter<100)
{
counter++;
}
else
{
counter=0;
second=second-1;
if(second==0){second=30;}
}
TH0=0xd8;//重新装初值
TL0=0xef;
TR0=1;//启动定时器0
}
void grade_display()//全部选手得分显示
{unsigned char i,j,k,l,m,n,o,p;
i=a/10;
j=a%10;
k=b/10;
l=b%10;
m=c/10;
n=c%10;
o=d/10;
p=d%10;
max7219_send(num_add[1],num_dat[j]);
max7219_send(num_add[0],num_dat[i]);
max7219_send(num_add[3],num_dat[l]);
max7219_send(num_add[2],num_dat[k]);
max7219_send(num_add[5],num_dat[n]);
max7219_send(num_add[4],num_dat[m]);
max7219_send(num_add[7],num_dat[p]);
max7219_send(num_add[6],num_dat[o]);
}
void holderscan()//倒计时和选手编号初始化设置,时间设置30s,选手编号设置为0.并对编号,得分,倒计时进行显示
{ max7219_init();grade_display();people=0;second=30;
time_display(second);people_display();
}
void main()
{ while(1)
{
do{holderscan();
}while(begin);//一直进行倒计时和选手编号初始化设置,直到按下开始按钮
while(~begin);//按键消抖
timer_init();//定时器T0初始化,10ms产生一次中断
TR0=1;//开启定时器计数
do{time_display(second);
if(shuzi()<=4){people=number;}
else{people=0;}
people_display();
}while((!people));//一直进行键盘扫描,直到按下键值小于等于4时,people不为零且为键值,跳出循环。
TR0=0;//关闭定时器计数
do{time_display(second);people_display();shuzi();
if(number<=8&&number>=5) {choice=number+5;}
else {choice=15;}
xuanxiang_display();}while(choice==15);//一直进行键盘扫描,直到按下键值小于等于8,且大于等于5时,choice不为15且为键值+5,跳出循环。
do{time_display(second);people_display();xuanxiang_display();shuzi();
if(number==people+8||number==people+12) {e=number;}
else {e=0;}
switch(e)//进行选择,若e=9,对a加一,绿灯亮1.5秒;若e=13,对a减一,红灯亮1.5秒;......
{ case(9):a++;led2=0;delay(1500);led2=1;break;
case(10):b++;led2=0;delay(1500);led2=1;break;
case(11):c++;led2=0;delay(1500);led2=1;break;
case(12):d++;led2=0;delay(1500);led2=1;break;
case(13):a--;if(a==-1){a=0;}led1=0;delay(1500);led1=1;break;
case(14):b--;if(b==-1){b=0;}led1=0;delay(1500);led1=1;break;
case(15):c--;if(c==-1){c=0;}led1=0;delay(1500);led1=1;break;
case(16):d--;if(d==-1){d=0;}led1=0;delay(1500);led1=1;break;
}
}while(e==0);//一直进行键盘扫描,直到按下键值等于people+8或等于people+12时,e不为0且为键值,跳出循环。
}
}
仿真图
最后
以上就是瘦瘦铅笔为你收集整理的keil 5与proteus8.9仿真实现四路抢答计分器设计目的二、代码实现仿真图的全部内容,希望文章能够帮你解决keil 5与proteus8.9仿真实现四路抢答计分器设计目的二、代码实现仿真图所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复