|
- /*
- 此程序?yàn)?人搶答器。
- 搶答者4人對應(yīng),K1-4的按鈕
- 裁判可操作Ks,Kr,Kc,Ka4個(gè)按鈕
- Ks:按下就進(jìn)入搶答倒計(jì)時(shí)
- Kr:按下復(fù)位,準(zhǔn)備下次搶答
- Kc,Ka:用于調(diào)整倒計(jì)時(shí)。
- 在復(fù)位之前使用,且當(dāng)前的操作是對復(fù)位之后的倒計(jì)時(shí)有用
- 保證沒有人按下除了Kc,Ka之外的按鈕。
- 最大設(shè)置為1分鐘,最小10s
- 按一次Kc加1s
- 操作步驟:按下Kr,后要按住Ka不松的狀態(tài)按Kc加時(shí)間,然后再次按下Kr
- 顯示器第一行顯示倒計(jì)時(shí)的時(shí)間
- 例如:countdown:10s
- 顯示器第二行顯示違規(guī)者和搶答成功者的對應(yīng)按鈕
- 例如:error:0 win:2 表示:無人違規(guī),2號搶答成功
- 例如:error:2 win:0 表示:有人違規(guī),2號違規(guī)
- */
- #include "reg52.h"
- #include "lcd.h"
- #define uchar unsigned char
- #define uint unsigned int
- sbit K1=P1^0;
- sbit K2=P1^1;
- sbit K3=P1^2;
- sbit K4=P1^3;
- sbit Ks=P3^0; //按下就進(jìn)入搶答倒計(jì)時(shí)
- sbit Kr=P3^2; //按下復(fù)位,準(zhǔn)備下次搶答
- sbit Kc=P3^3; //按下調(diào)整倒計(jì)時(shí),注意事項(xiàng)見timeset()
- sbit Ka=P3^4; //配合Kc
- sbit beep=P3^7;
- sbit led=P3^1;
- uchar fallflag=0,sflag=0,jflag=0,sjflag=0;
- uchar win,time=10; //time為倒計(jì)時(shí)秒數(shù),num為程序中控制倒計(jì)時(shí)的變量,win為搶答成功的按鈕
- uchar num,numf; //numf為配合num來顯示lcd
- uchar Disp1[16]="countdown:00s ";
- uchar Disp2[16]="error:0 win:0 ";
- void judge();
- void search();
- void delay(uchar ms)
- {
- uchar y;
- for(;ms>0;ms--)
- for(y=120;y>0;y--);
- }
- void T0_Init()
- {
- TMOD=0X11;
- TH0=(65536-1000)/256;
- TL0=(65536-1000)%256;
- TH1=(65536-1000)/256;
- TL1=(65536-1000)%256;
- ET0=1;
- ET1=1;
- TR0=1; //定時(shí)器0開
- TR1=0; //定時(shí)器1關(guān)
- EA=1;
- }
- /*lcd1602顯示程序*/
- void display(uchar date1,uchar date2)
- {
- uchar i,a;
- LcdInit();
- Disp1[10]=num/10+'0';
- Disp1[11]=num%10+'0';
- Disp2[6]=date1+'0';
- Disp2[12]=date2+'0';
- for(i=0;i<16;i++)
- {
- LcdWriteData(Disp1[i]);
- }
- LcdWriteCom(0x80+0x40);
- for(a=0;a<16;a++)
- {
- LcdWriteData(Disp2[a]);
- }
- }
- /*
- 開始準(zhǔn)備搶答,開始倒計(jì)時(shí)
- */
- void Ks_Scan()
- {
- if(Ks==0)
- {
- delay(10);
- if(Ks==0)
- {
- TR1=1; //開啟倒計(jì)時(shí)
- sjflag=1; //開啟犯規(guī)判斷
- while(num!=0) //如果在期間有人搶答,fallflag=1,此程序執(zhí)行完后,后續(xù)程序會判犯規(guī)
- {
- if(num==numf-1)
- {
- numf=numf-1;
- display(0,0); //不能顯示num=0時(shí)
- }
- }
- sflag=1; //搶答開始
- if(sjflag==0) //有人犯規(guī)
- {
- sflag=0;
- }
- sjflag=0; //關(guān)閉犯規(guī)判斷
- display(0,0); //顯示num=0時(shí)
- beep=0; //蜂鳴
- }
- while(!Ks);
- }
- }
- /*
- 復(fù)位
- */
- void restoration()
- {
- if(Kr==0)
- {
- delay(10);
- if(Kr==0)
- {
- sflag=0;
- sjflag=0;
- jflag=0;
- win=0;
- fallflag=0;
- TR1=0;
- num=time;
- numf=num;
- beep=1;
- led=1;
- display(0,0); //清除顯示屏
- }
- while(!Kr);
- }
- }
- /*
- 在復(fù)位之前使用,且當(dāng)前的操作是對復(fù)位之后的倒計(jì)時(shí)有用
- 保證沒有人按下除了Kc,Ka之外的按鈕。
- 最大設(shè)置為1分鐘,最小10s
- 按一次Kc加1s
- 操作步驟:按下Kr,后要按住Ka不松的狀態(tài)按Kc加時(shí)間,然后再次按下Kr
- */
- void timeset() //改變搶答時(shí)間
- {
- uchar a=0;
- if(Ka==0)
- {
- delay(10);
- if(Ka==0)
- {
- while(!Ka)
- {
- if(Kc==0)
- {
- delay(10);
- if(Kc==0)
- {
- a++;
- }
- while(!Kc);
- }
- }
- time=time+a;
- }
- }
- if(time>=60)
- {
- time=10;
- }
- }
- void main()
- {
- T0_Init();
- while(1)
- {
- Ks_Scan();
- if((sflag==0)&(fallflag==0)) //沒開始沒人搶答
- {
- timeset();
- }
- if((sflag==0)&(fallflag!=0)) //有人違規(guī)搶答
- {
- led=0; //亮燈警告
- beep=1; //關(guān)閉蜂鳴
- display(fallflag,0); //顯示有人犯規(guī),并顯示犯規(guī)按鈕,根據(jù)fallflag
- }
- if((sflag==1)&(fallflag==0)) //無人違規(guī)
- {
- while(jflag==0)
- {
- judge();
- }
- judge(); //防止jflag=1時(shí),judge()沒執(zhí)行
- beep=1; //關(guān)閉蜂鳴
- display(0,win); //顯示搶答成功按鈕,根據(jù)win
- }
- restoration(); //復(fù)位
- }
- }
- /*不停的掃描k1-4的狀態(tài),每隔1ms掃描一次*/
- void timer0() interrupt 1
- {
- TH0=(65536-1000)/256;
- TL0=(65536-1000)%256;
- search();
- }
- void timer1() interrupt 3
- {
- static i;
- TH0=(65536-1000)/256;
- TL0=(65536-1000)%256;
- i++;
- if(i==1000)
- {
- i=0;
- num--;
- //display(0,0); //為什么此時(shí)加上這個(gè)程序就報(bào)warning
- if(num==0) //放在內(nèi)部保證定時(shí)器的準(zhǔn)確性
- {
- TR1=0;
- }
- }
- }
- //先丟后面的代碼
- /*
- 配合定時(shí)器0使用
- 如果k1-4有按鍵按下,fallflag=1
- */
- void search()
- {
- if((K1==0)&(sjflag==1)) //按下Ks開始后(sjflag=1)如果有人按了K1就會進(jìn)入程序
- {
- delay(10);
- if(K1==0)
- {
- fallflag=1;
- sjflag=0; //互鎖,并配合Ks_Scan()中的犯規(guī)判斷語句
- }
- while(!K1);
- }
- if((K2==0)&(sjflag==1))
- {
- delay(10);
- if(K2==0)
- {
- fallflag=2;
- sjflag=0;
- }
- while(!K2);
- }
- if((K3==0)&(sjflag==1))
- {
- delay(10);
- if(K3==0)
- {
- fallflag=3;
- sjflag=0;
- }
- while(!K3);
- }
- if((K4==0)&(sjflag==1))
- {
- delay(10);
- if(K4==0)
- {
- fallflag=4;
- sjflag=0;
- }
- while(!K4);
- }
- }
- void judge()
- {
- if((K1==0)&(jflag==0))
- {
- delay(10);
- if((K1==0)&(jflag==0))
- {
- win=1;
- jflag=1; //鎖住其他按鈕
- }
- while(!K1);
- }
- if((K2==0)&(jflag==0))
- {
- delay(10);
- if((K2==0)&(jflag==0))
- {
- win=2;
- jflag=1; //鎖住其他按鈕
- }
- while(!K2);
- }
- if((K3==0)&(jflag==0))
- {
- delay(10);
- if((K3==0)&(jflag==0))
- {
- win=3;
- jflag=1; //鎖住其他按鈕
- }
- while(!K3);
- }
- if((K4==0)&(jflag==0))
- {
- delay(10);
- if((K4==0)&(jflag==0))
- {
- win=4;
- jflag=1; //鎖住其他按鈕
- }
- while(!K4);
- }
- }
- 以下是“l(fā)cd.c”
- #include "lcd.h"
- /*******************************************************************************
- * 函 數(shù) 名 : Lcd1602_Delay1ms
- * 函數(shù)功能 : 延時(shí)函數(shù),延時(shí)1ms
- * 輸 入 : c
- * 輸 出 : 無
- * 說 名 : 該函數(shù)是在12MHZ晶振下,12分頻單片機(jī)的延時(shí)。
- *******************************************************************************/
- void Lcd1602_Delay1ms(uint c) //誤差 0us
- {
- uchar a,b;
- for (; c>0; c--)
- {
- for (b=199;b>0;b--)
- {
- for(a=1;a>0;a--);
- }
- }
-
- }
- /*******************************************************************************
- * 函 數(shù) 名 : LcdWriteCom
- * 函數(shù)功能 : 向LCD寫入一個(gè)字節(jié)的命令
- * 輸 入 : com
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS //當(dāng)沒有定義這個(gè)LCD1602_4PINS時(shí)
- void LcdWriteCom(uchar com) //寫入命令
- {
- LCD1602_E = 0; //使能
- LCD1602_RS = 0; //選擇發(fā)送命令
- LCD1602_RW = 0; //選擇寫入
-
- LCD1602_DATAPINS = com; //放入命令
- Lcd1602_Delay1ms(1); //等待數(shù)據(jù)穩(wěn)定
- LCD1602_E = 1; //寫入時(shí)序
- Lcd1602_Delay1ms(5); //保持時(shí)間
- LCD1602_E = 0;
- }
- #else
- void LcdWriteCom(uchar com) //寫入命令
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 0; //選擇寫入命令
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = com; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時(shí)序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- LCD1602_DATAPINS = com << 4; //發(fā)送低四位
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時(shí)序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- }
- #endif
- /*******************************************************************************
- * 函 數(shù) 名 : LcdWriteData
- * 函數(shù)功能 : 向LCD寫入一個(gè)字節(jié)的數(shù)據(jù)
- * 輸 入 : dat
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS
- void LcdWriteData(uchar dat) //寫入數(shù)據(jù)
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //選擇輸入數(shù)據(jù)
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = dat; //寫入數(shù)據(jù)
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時(shí)序
- Lcd1602_Delay1ms(5); //保持時(shí)間
- LCD1602_E = 0;
- }
- #else
- void LcdWriteData(uchar dat) //寫入數(shù)據(jù)
- {
- LCD1602_E = 0; //使能清零
- LCD1602_RS = 1; //選擇寫入數(shù)據(jù)
- LCD1602_RW = 0; //選擇寫入
- LCD1602_DATAPINS = dat; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時(shí)序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- LCD1602_DATAPINS = dat << 4; //寫入低四位
- Lcd1602_Delay1ms(1);
- LCD1602_E = 1; //寫入時(shí)序
- Lcd1602_Delay1ms(5);
- LCD1602_E = 0;
- }
- #endif
- /*******************************************************************************
- * 函 數(shù) 名 : LcdInit()
- * 函數(shù)功能 : 初始化LCD屏
- * 輸 入 : 無
- * 輸 出 : 無
- *******************************************************************************/
- #ifndef LCD1602_4PINS
- void LcdInit() //LCD初始化子程序
- {
- LcdWriteCom(0x38); //開顯示
- LcdWriteCom(0x0c); //開顯示不顯示光標(biāo)
- LcdWriteCom(0x06); //寫一個(gè)指針加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //設(shè)置數(shù)據(jù)指針起點(diǎn)
- }
- #else
- void LcdInit() //LCD初始化子程序
- {
- LcdWriteCom(0x32); //將8位總線轉(zhuǎn)為4位總線
- LcdWriteCom(0x28); //在四位線下的初始化
- LcdWriteCom(0x0c); //開顯示不顯示光標(biāo)
- LcdWriteCom(0x06); //寫一個(gè)指針加1
- LcdWriteCom(0x01); //清屏
- LcdWriteCom(0x80); //設(shè)置數(shù)據(jù)指針起點(diǎn)
- }
- #endif
- 以下是“l(fā)cd.h”
- #ifndef __LCD_H_
- #define __LCD_H_
- /**********************************
- 當(dāng)使用的是4位數(shù)據(jù)傳輸?shù)臅r(shí)候定義,
- 使用8位取消這個(gè)定義
- **********************************/
- //#define LCD1602_4PINS
- /**********************************
- 包含頭文件
- **********************************/
- #include <reg52.h>
- //---重定義關(guān)鍵詞---//
- #ifndef uchar
- #define uchar unsigned char
- #endif
- #ifndef uint
- #define uint unsigned int
- #endif
- /**********************************
- PIN口定義
- **********************************/
- #define LCD1602_DATAPINS P2
- sbit LCD1602_E=P0^7;
- sbit LCD1602_RW=P0^6;
- sbit LCD1602_RS=P0^5;
- /**********************************
- 函數(shù)聲明
- **********************************/
- /*在51單片機(jī)12MHZ時(shí)鐘下的延時(shí)函數(shù)*/
- void Lcd1602_Delay1ms(uint c); //誤差 0us
- /*LCD1602寫入8位命令子函數(shù)*/
- void LcdWriteCom(uchar com);
- /*LCD1602寫入8位數(shù)據(jù)子函數(shù)*/
- void LcdWriteData(uchar dat) ;
- /*LCD1602初始化子程序*/
- void LcdInit();
- #endif
復(fù)制代碼 |
評分
-
查看全部評分
|