欧美极品高清xxxxhd,国产日产欧美最新,无码AV国产东京热AV无码,国产精品人与动性XXX,国产传媒亚洲综合一区二区,四库影院永久国产精品,毛片免费免费高清视频,福利所导航夜趣136
標題:
基于51單片機的4人搶答器代碼
[打印本頁]
作者:
18181974358
時間:
2019-4-30 19:37
標題:
基于51單片機的4人搶答器代碼
/*
此程序為4人搶答器。
搶答者4人對應,K1-4的按鈕
裁判可操作Ks,Kr,Kc,Ka4個按鈕
Ks:按下就進入搶答倒計時
Kr:按下復位,準備下次搶答
Kc,Ka:用于調整倒計時。
在復位之前使用,且當前的操作是對復位之后的倒計時有用
保證沒有人按下除了Kc,Ka之外的按鈕。
最大設置為1分鐘,最小10s
按一次Kc加1s
操作步驟:按下Kr,后要按住Ka不松的狀態按Kc加時間,然后再次按下Kr
顯示器第一行顯示倒計時的時間
例如:countdown:10s
顯示器第二行顯示違規者和搶答成功者的對應按鈕
例如:error:0 win:2 表示:無人違規,2號搶答成功
例如:error:2 win:0 表示:有人違規,2號違規
*/
#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; //按下就進入搶答倒計時
sbit Kr=P3^2; //按下復位,準備下次搶答
sbit Kc=P3^3; //按下調整倒計時,注意事項見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為倒計時秒數,num為程序中控制倒計時的變量,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; //定時器0開
TR1=0; //定時器1關
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]);
}
}
/*
開始準備搶答,開始倒計時
*/
void Ks_Scan()
{
if(Ks==0)
{
delay(10);
if(Ks==0)
{
TR1=1; //開啟倒計時
sjflag=1; //開啟犯規判斷
while(num!=0) //如果在期間有人搶答,fallflag=1,此程序執行完后,后續程序會判犯規
{
if(num==numf-1)
{
numf=numf-1;
display(0,0); //不能顯示num=0時
}
}
sflag=1; //搶答開始
if(sjflag==0) //有人犯規
{
sflag=0;
}
sjflag=0; //關閉犯規判斷
display(0,0); //顯示num=0時
beep=0; //蜂鳴
}
while(!Ks);
}
}
/*
復位
*/
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);
}
}
/*
在復位之前使用,且當前的操作是對復位之后的倒計時有用
保證沒有人按下除了Kc,Ka之外的按鈕。
最大設置為1分鐘,最小10s
按一次Kc加1s
操作步驟:按下Kr,后要按住Ka不松的狀態按Kc加時間,然后再次按下Kr
*/
void timeset() //改變搶答時間
{
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)) //有人違規搶答
{
led=0; //亮燈警告
beep=1; //關閉蜂鳴
display(fallflag,0); //顯示有人犯規,并顯示犯規按鈕,根據fallflag
}
if((sflag==1)&(fallflag==0)) //無人違規
{
while(jflag==0)
{
judge();
}
judge(); //防止jflag=1時,judge()沒執行
beep=1; //關閉蜂鳴
display(0,win); //顯示搶答成功按鈕,根據win
}
restoration(); //復位
}
}
/*不停的掃描k1-4的狀態,每隔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); //為什么此時加上這個程序就報warning
if(num==0) //放在內部保證定時器的準確性
{
TR1=0;
}
}
}
//先丟后面的代碼
/*
配合定時器0使用
如果k1-4有按鍵按下,fallflag=1
*/
void search()
{
if((K1==0)&(sjflag==1)) //按下Ks開始后(sjflag=1)如果有人按了K1就會進入程序
{
delay(10);
if(K1==0)
{
fallflag=1;
sjflag=0; //互鎖,并配合Ks_Scan()中的犯規判斷語句
}
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);
}
}
以下是“lcd.c”
#include "lcd.h"
/*******************************************************************************
* 函 數 名 : Lcd1602_Delay1ms
* 函數功能 : 延時函數,延時1ms
* 輸 入 : c
* 輸 出 : 無
* 說 名 : 該函數是在12MHZ晶振下,12分頻單片機的延時。
*******************************************************************************/
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--);
}
}
}
/*******************************************************************************
* 函 數 名 : LcdWriteCom
* 函數功能 : 向LCD寫入一個字節的命令
* 輸 入 : com
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS //當沒有定義這個LCD1602_4PINS時
void LcdWriteCom(uchar com) //寫入命令
{
LCD1602_E = 0; //使能
LCD1602_RS = 0; //選擇發送命令
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = com; //放入命令
Lcd1602_Delay1ms(1); //等待數據穩定
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5); //保持時間
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; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = com << 4; //發送低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 數 名 : LcdWriteData
* 函數功能 : 向LCD寫入一個字節的數據
* 輸 入 : dat
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdWriteData(uchar dat) //寫入數據
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //選擇輸入數據
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = dat; //寫入數據
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5); //保持時間
LCD1602_E = 0;
}
#else
void LcdWriteData(uchar dat) //寫入數據
{
LCD1602_E = 0; //使能清零
LCD1602_RS = 1; //選擇寫入數據
LCD1602_RW = 0; //選擇寫入
LCD1602_DATAPINS = dat; //由于4位的接線是接到P0口的高四位,所以傳送高四位不用改
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
LCD1602_DATAPINS = dat << 4; //寫入低四位
Lcd1602_Delay1ms(1);
LCD1602_E = 1; //寫入時序
Lcd1602_Delay1ms(5);
LCD1602_E = 0;
}
#endif
/*******************************************************************************
* 函 數 名 : LcdInit()
* 函數功能 : 初始化LCD屏
* 輸 入 : 無
* 輸 出 : 無
*******************************************************************************/
#ifndef LCD1602_4PINS
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x38); //開顯示
LcdWriteCom(0x0c); //開顯示不顯示光標
LcdWriteCom(0x06); //寫一個指針加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //設置數據指針起點
}
#else
void LcdInit() //LCD初始化子程序
{
LcdWriteCom(0x32); //將8位總線轉為4位總線
LcdWriteCom(0x28); //在四位線下的初始化
LcdWriteCom(0x0c); //開顯示不顯示光標
LcdWriteCom(0x06); //寫一個指針加1
LcdWriteCom(0x01); //清屏
LcdWriteCom(0x80); //設置數據指針起點
}
#endif
以下是“lcd.h”
#ifndef __LCD_H_
#define __LCD_H_
/**********************************
當使用的是4位數據傳輸的時候定義,
使用8位取消這個定義
**********************************/
//#define LCD1602_4PINS
/**********************************
包含頭文件
**********************************/
#include <reg52.h>
//---重定義關鍵詞---//
#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;
/**********************************
函數聲明
**********************************/
/*在51單片機12MHZ時鐘下的延時函數*/
void Lcd1602_Delay1ms(uint c); //誤差 0us
/*LCD1602寫入8位命令子函數*/
void LcdWriteCom(uchar com);
/*LCD1602寫入8位數據子函數*/
void LcdWriteData(uchar dat) ;
/*LCD1602初始化子程序*/
void LcdInit();
#endif
復制代碼
作者:
YHY232
時間:
2019-5-6 08:20
感覺不錯哦,謝謝大佬分享
作者:
da'da'l'k
時間:
2020-6-20 22:23
寫的很詳細了,謝謝分享
作者:
靜謐零度
時間:
2020-6-21 10:39
有仿真圖嗎?
歡迎光臨 (http://www.raoushi.com/bbs/)
Powered by Discuz! X3.1