原创 MCS-51单片机的四路抢答器

2010-12-17 18:06 3608 8 9 分类: MCU/ 嵌入式

基于MCS-51单片机的四路抢答器


1.显示程序


       void delay_20ms(void)             //延时20ms


void max7219_reset(void)       //初始化MAX7219


void write_reg(uchar reg,uchar sdata) //写入命令


void write_digit(uchar digit,uchar number)//显示数字


void send_data(uchar byte)          //MAX7219的驱动程序


void display_time(void) //显示倒计时剩余时间


2.按键扫描程序


bit control_key(void) //检测主持人是否按键


{


if(KEY5==1) //如果KEY5为高说明没有按键


return 1; //返回1,表示没有按键动作


else //如果KEY5为低说明可能有按键动作


delay_20ms(); //延时20ms,去抖动


if(KEY5==1) //如果20ms后KEY5变为高电平是干扰


return 1; //返回1


else //如果20ms后仍为低电平确认有按键动作


return 0; //返回0


}


子程序get_key_num()用于检测是否有参赛者按动答题按键。程序代码如下:


  uchar get_key_num() //检测哪个参赛者按键


{


uchar key_state=0;


key_state=P1;


key_state&=0x0f; //读取P1口的低四位


if(key_state==0x0f) //若均为高电平,说明无人按键


return 0; //返回1


else


{


key_state^=0xff;


if(key_state&0x01) return 1; //如果KEY1被按下,返回1


     else if(key_state&0x02) return 2; //如果KEY2被按下,返回2


else if(key_state&0x04) return 3; //如果KEY3被按下,返回3


else return 4; /如果KEY4被按下,返回4


}


}


子程序key_handle()用于对答题按键进行处理。程序代码如下:


void key_handle(uchar key_number) //按键处理


{


write_digit(DIGIT0,key_number); //显示按键者号码


buz_on();


}


3.报警程序模块


代码如下:


void buz_on(void)


{


uchar i;


BUZ=0; //开蜂鸣器


for(i=1;i<=25;i++) //延时500ms


delay_20ms;


BUZ=1; //关蜂鸣器


}


子程序foul_handle()用于当有人犯规时报警处理。程序调用write_digit()函数显示犯规者号码,同时控制蜂鸣器发声。代码如下:


void foul_handle(uchar key_number) //犯规处理


{


write_digit(DIGIT0,key_number); //显示犯规者号码


write_digit(DIGIT1,0x0f); //显示“FF”


write_digit(DIGIT2,0x0f);


buz_on(); //蜂鸣器响


}


子程序time_over_handle(void)用于处理超时情况,即主持人按动启动按键后,并且预设的答题时间到,仍然没有人按答题按键。子程序调用相关函数显示0,同时控制蜂鸣器发声。代码如下:


void time_over_handle(void) //超时处理


{


write_digit(DIGIT0,0x0); //显示“0”


write_digit(DIGIT1,0x0e); //显示“EE”


write_digit(DIGIT2,0x0e);


buz_on(); //蜂鸣器响


}


4.主程序模块


代码如下:


uchar set_time(void) //根据设置决定倒计时时间


{


uchar intr_counter;


if(P3^5==0) intr_counter=160; //8s


else if (P3^4==0) intr_counter=120; //6s


else if (P3^3==0) intr_counter=80; //4s


else intr_counter=200; /如果没有设置,默认为10s


return intr_counter;


}


子程序init_t0(void)用于初始化定时器T0。T0工作于方式1,16位定时器模式,定时时间50ms。代码如下:


void init_t0(void)


{


TMOD=0x01; //T0选择工作方式1,16位定时器


TH0=TIMER_HBYTE; //定时时间为50ms


TL0=TIMER_LBYTE;


EA=1; //使能CPU中断


ET0=1; //使能T0溢出中断


TR0=1; //T0运行


}


子程序isr_t0(void)是T0的中断服务程序。当50ms时间到时,该程序被执行,重新装载T0的计数初值,并判断倒计时时间是否到。代码如下:


void isr_t0(void) interrupt 1 //T0中断服务函数


{


TH0=TIMER_HBYTE; //定时时间为50ms


TL0=TIMER_LBYTE;


intr_counter--; //中断次数


if(intr_counter==0) //倒计时时间到


{


time_over_flg=1; //设置超时标志


TR0=0;//禁止T0运行


}


}


系统主程序流程。程序如下所示:


#include <reg51.h>


typedef unsigned char uchar;


sbit LE=P1^4;


sbit KEY5=P3^7;


sbit DIN=P2^4; //定义P2.5控制MAX7219的串行数据输入端


sbit LOAD=P2^3; //定义P2.4控制MAX7219的载入使能端


sbit CLK=P2^2; //定义P2.3控制MAX7219的时钟信号


sbit BUZ=P0^1;


#define TIMER_HBYTE -50000/256 //定时50ms


#define TIMER_LBYTE -50000%256


uchar intr_counter; //设定的时间,用需要产生的中断次数表示


uchar bdata byte; //在bdata区定义一个变量,便于位操作


sbit byte_7=byte^7;


bit foul_flg; //是否有人犯规标志


bit time_over_flg; //是否倒计时超时标志


bit key_flg; //是否有人在规定时间内按键标志


void max7219_reset(void); //初始化MAX7219


void write_reg(uchar,uchar); //向控制寄存器写数据


void write_digit(uchar,uchar); //向字型寄存器写数据


void send_data(uchar); //底层的硬件驱动


uchar set_time(void); //函数功能:设置倒计时时间


bit control_key(void); //函数功能:检测主持人是否按键


uchar get_key_num(void); //函数功能:检测哪个参赛者按键


void display_time(void); //函数功能:显示倒计时剩余时间


void foul_handle(uchar); //函数功能:犯规处理


void key_handle(uchar); //函数功能:按键处理


void time_over_handle(void); //函数功能:超时处理


void init_t0(void); //函数功能:初始化T0定时器


void delay_20ms(void); //函数功能:延时20ms,按键去抖动


void buz_on(void) //函数功能:蜂鸣器响500ms


void main(void)


{


uchar key_number;


max7219_reset(); //初始化MAX7219


while(1)


{


foul_flg=0; //设置初始环境


time_over_flg=0;


TR0=0; //禁止T0运行


write_digit(DIGIT0,LED_code[0x0]);//上电后三个数码管全部显示0


write_digit(DIGIT1,LED_code[0x0]);


write_digit(DIGIT2,LED_code[0x0]);


while((control_key()==1)&&(foul_flg==0))


{//如果主持人没有按键


key_number=getkey_num();//检查是否有人犯规


if(key_number==0) //如果没有,进行下一次循环


continue;


else //如果有人犯规


{


foul_handle(); //犯规处理


foul_flg=1; //设置犯规标志


}


}


if(foul_flg==1) //如果有人犯规


{


while(control_key()==1); //等待主持人按键以进入下一轮


continue; //主持人按键后进入下一轮


}


else //如果没有人犯规,必定是主持人允许答题


{


intr_counter=set_time(); //读取倒计时时间


init_t0(); //定时器T0开始计时


buz_on(); //蜂鸣器响500ms


while(time_over_flg==0&&key_flg==0)


{


key_number=getkey_num(); //在规定时间内检查是否有按键


if(key_number!=0) //如果有


{


key_handle(key_number); //按键处理


key_flg=1; //设置有人按键答题标志


TR0=0; //停止T0运行


}


else //否则循环检测


{


display_time(); //并显示剩余时间


continue;


}


}


if(key_flg==1) //如果有人在规定时间内答题


{


while(control_key()==1); //等待主持人按键以进入下一轮


continue; //主持人按键后进入下一轮


}


else //倒计时时间到仍无人按键


{


time_over_handle(); //超时处理


while(control_key()==1); //等待主持人按键以进入下一轮


continue; //主持人按键后进入下一轮


}


}


}


}

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户377235 2012-12-12 19:14

你没写完啊

相关推荐阅读
用户313686 2013-05-16 18:56
汤金
施耐德汤金...
用户313686 2013-05-16 18:52
S图纸H
电气图纸...
用户313686 2011-09-02 16:55
芯片查询软件
芯片查询,pdf下载软件.zip...
用户313686 2011-09-01 15:43
平面板
平板灯怎么做才能达到80LM/W,,大家谈 一下自己的想 法...
用户313686 2011-08-16 21:01
025
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromed...
用户313686 2011-08-06 10:42
PID调试方法
1.1 PID参数调试 从设备结构可以看出,这是个没有控制迟滞的系统,不像暖通空调、加热系统那样具有非常大的控制迟滞(控制输出增加后,被控制变量要比较长的时间才会有所变化)。所以,PID控制器中的...
EE直播间
更多
我要评论
1
8
关闭 站长推荐上一条 /1 下一条