📄 基于单片机的8路抢答器程序.txt
字号:
#include <stdio.h>//调用库函数
#include <reg51.h>
#include <intrins.h>
unsigned char key, leda[11]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0xf3};//共阴位段码
unsigned char sec, sec_=65; //定时65秒
unsigned char key,key_0,key_flag,key_count;
unsigned char mask=0xee,t0_count,set_no=0,led_no=0;
unsigned char set_flag=0,disp[4];
#define hi 0x3c //定时初值1(50ms)
#define lo 0xb0
#define hi1 0xff //定时初值2
#define lo1 0x00
sbit P37=P3^7;sbit P36=P3^6;sbit clk=P0^7;sbit sda=P0^6; sbit P30=P3^0;//单片机端口位矢量定义
////////////////////////////////////////////
void delay(unsigned int n) //延时函数
{unsigned int i,j;
for(i=0;i<n;i++)
for(j=0;j<n;j++);
}
////////////////////////////////////////////
void shift(unsigned char dx) //74LS164移位函数
{static unsigned char d;
unsigned char j=0;
d=dx;
while(j<8) //循环8次完成8位段码的串行移入
{ if((d&0x80)!=0) sda=1; //如果d最高位是高电平,就输出高电平
else sda=0; //否则为0电平,就输出0电平
clk=0;clk=1; //产生脉冲信号
d<<=1; //左移循环
j++;
}
}
////////////////////////////////////////////
void clktodisp(unsigned char j,xx) //数制转换
{disp[j]=xx/10; j--; xx=xx%10; disp[j]=xx;}
////////////////////////////////////////////
void t0() interrupt 1 //0#外中断
{ TH0=hi;TL0=lo; //重装初值
t0_count++;key_count++;
if(t0_count==20) //如果半秒时间到
{ if (key_flag==1&&sec>0)sec--; //如果有键按下开始倒计时
if (key_flag==1&&sec_>0)sec_--; t0_count=0;
}
}
////////////////////////////////////////////////////////
void t1() interrupt 3 //1#外中断
{P30=!P30;TH1=hi1;TL1=lo1;}
////////////////////////////////////////////
unsigned char get_char() //取键值
{ unsigned char key_code;
static unsigned char column=0,column1=4;
if(P37==0 && key_flag==0)key_code=column; //如果有键按下,显示键号并锁定
else
{
if(P36==0 && key_flag==0)key_code=column1; //如果有键按下,显示键号并锁定
else key_code=0xff;
}
column++; column1++;led_no++;
if(column>3)column=0; //如果检测到P37为低电平,使键值(1)从0变化到3
if(column1>7)column1=4; //如果检测到P36为低电平,使键值(2)从4变化到7
if(led_no>3)led_no=0;
mask=_crol_(mask,1); //左移循环
return key_code; //返回键值
}
///////////////////////////////////////////////////
void out() //输出8位段码
{ unsigned char dd;
dd=leda[disp[led_no]];
if((key_flag==0&&led_no!=0)||(key_flag==1&&led_no==2))shift(0x00); //使百位不显示
else
{ if(key_flag==0)shift(leda[10]); //如果没有键按下显示“P”字码
else shift(dd);
}
P2=mask;
}
////////////////////////////////////////////
void key_func(key) //读键,并锁定
{ switch (key)
{ case 0: disp[3]=1;key_flag=1;break;
case 1: disp[3]=2;key_flag=1;break;
case 2: disp[3]=3;key_flag=1;break;
case 3: disp[3]=4;key_flag=1;break;
case 4: disp[3]=5;key_flag=1;break;
case 5: disp[3]=6;key_flag=1;break;
case 6: disp[3]=7;key_flag=1;break;
case 7: disp[3]=8;key_flag=1;break;
default: break;
}
}
////////////////////////////////////////////
void main(void) //主函数
{ unsigned char i=1;
TMOD=0x11; //0#,1#定时器模式,方式1
TH0=hi;TL0=lo; //赋初值
TH1=hi1;TL0=lo1;
EA=1; //开中断
ET0=1;ET1=1; //开定时
TR0=1; //允许计数
sec=60; //定时60s
P30=0;
while(1) //不断循环
{
clktodisp( 1,sec); //使数码管显示倒计时时间
key=get_char( ); //取键值函数
key_func(key); //键功能函数
out();
delay(20); //延时函数
if(key_flag==1&&sec==60)
{TR1=1;key_count=0;} //如果有键按下则响一次铃
else
{TR1=0; //停止计数
P30=0; //关闭响铃
}
if(sec_<=5&&sec_>0)
{ if(t0_count<10 ) //延时半秒
TR1=1; //倒计时时间到蜂鸣器响5s
else
{TR1=0;P30=0;} //蜂鸣器响5s后停止响铃
}
if(sec_==0)break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -