|
100黑幣
我做了一個八路搶答器,proteus仿真時一點問題都沒有。但是實物做出來后一點都不正確。甚至連開始都開始不了。是我設計有問題還是什么啊,有沒有大神指點下。下附代碼和圖片
#include <reg51.h>
#include <intrins.h>
#include <stdlib.h>
sbit k0 = P0^0; //二位數碼管第一位選擇腳
sbit k2 = P0^2; //二位數碼管第二位選擇腳
sbit k4 = P0^4;
//P2端口 數碼管段選
//P1端口 八位選手搶答
sbit start = P3^7;//開始搶答按鈕連接管腳
sbit end = P3^5; //結束搶答按鈕連接管腳
sbit beep=P3^3;//蜂鳴器連接管腳
unsigned char duanxuan[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};//數碼管段碼:0123456789
unsigned char qd_num=0; //搶答選手號
unsigned char qd_time=0; //搶答倒計時間
unsigned char timeout_num=0; //定時器產生中斷次數
unsigned char work_status = 0; //工作狀態,下面幾個為工作狀態定義的宏
#define START_QD_STATUS 0
#define WAIT_QD_STATUS 1
#define ACK_QD_STATUS 2
/*******延時2ms函數*******/
void delay2ms(void) //誤差 0us
{
unsigned char a,b;
for(b=4;b>0;b--)
for(a=248;a>0;a--);
}
/*******延時10ms函數*******/
void delay10ms(void)
{
unsigned char a,b,i;
for(a=5;a>0;a--)
for(b=4;b>0;b--)
for(i=248;i>0;i--);
}
/******延時50ms函數,參數num為延時多少個50ms******/
void delay50ms(unsigned int num) //誤差 0us
{
unsigned char a,b;
unsigned char i=0;
for(i=0; i<num; i++)
{
for(b=173;b>0;b--)
for(a=143;a>0;a--);
}
}
/******初始化定時器0******/
void InitTimer0(void)//50ms
{
TMOD = 0x01;//定時器工作模式1
TH0 = 0x3C; //定時器裝值高8位
TL0 = 0x0B0;//定時器裝值低8位
EA = 1; //使能總中斷
ET0 = 1; //使能定時器0中斷
TR0 = 1; //啟動定時器
}
/*******關閉定時器0*******/
void end_Timer0(void)
{
ET0 = 0;//關閉定時器0中斷
TR0 = 0;//停止定時器0
}
/*****初始化函數*****/
void init(void)
{
k0 = 0;
k2 = 0;
k4 = 0;
beep = 0;//上電時由于該腳為高,而為高時蜂鳴器會叫,故初始化為低
}
/*******等待開始搶答狀態*******/
void start_qd_status(void)
{
if(start == 0)//檢測到開始搶答按鈕按下
{
work_status = WAIT_QD_STATUS;//工作狀態設置為等待答題狀態
qd_num = 0; //回答選手號為0,等待選手按下
qd_time = 9; //9s搶答時間
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
}
}
/*******開始按鈕按下后,等待選手搶答狀態函數*******/
void wait_qd_status(void)
{
if(qd_time == 0)//無人搶答,搶答時間已到
{
end_Timer0();//停止定時器0
//蜂鳴器給出無人搶答警報
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
work_status = START_QD_STATUS;//無人搶答后恢復原始狀態,設置工作狀態為開始搶答狀態
}
if(end == 0)//檢測到結束按鍵
{
end_Timer0();//停止定時器0
qd_num = 0;//回答選手號為0
qd_time = 0;//搶答時間清0
work_status = START_QD_STATUS;//工作狀態置開始搶答狀態
}
/********搶答成功********/
if(P1!=0xff) //P1口電位發生變化,表示有按鍵按下
{
delay10ms(); //延時防抖
switch(P1)//檢測哪位選手按下搶答按鈕
{
case 0xfe://1號
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
qd_num = 1;//回答選手號為1
qd_time = 30;
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
work_status = ACK_QD_STATUS;
break;
case 0xfd://2號
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
qd_num = 2;//回答選手號為2
qd_time = 30;
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
work_status = ACK_QD_STATUS;
break;
case 0xfb://3號
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
qd_num = 3;//回答選手號為3
qd_time = 30;
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
work_status = ACK_QD_STATUS;
break;
case 0xf7://4號
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
qd_num = 4;//回答選手號為4
qd_time = 30;
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
work_status = ACK_QD_STATUS;
break;
case 0xef://5號
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
qd_num = 5;//回答選手號為5
qd_time = 30;
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
work_status = ACK_QD_STATUS;
break;
case 0xdf://6號
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
qd_num = 6;//回答選手號為6
qd_time = 30;
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
work_status = ACK_QD_STATUS;
break;
case 0xbf://7號
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
qd_num = 7;//回答選手號為7
qd_time = 30;
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
work_status = ACK_QD_STATUS;
break;
case 0x7f://8號
beep = 1; //蜂鳴器響
delay50ms(20);
beep = 0;
qd_num = 8;//回答選手號為8
qd_time = 30;
timeout_num=0; //中斷次數清0
InitTimer0(); //開啟定時器0
work_status = ACK_QD_STATUS;
break;
default:
break;
}
}
}
/*******選手回答問題狀態*******/
void ack_qd_status()
{
unsigned char i = 0;
if(qd_time == 0)//答題超時
{
end_Timer0();//結束定時器0
qd_num = 0;
qd_time = 0;
for(i=0;i<3;i++)//選手回答問題超時警報
{
beep = 1;
delay50ms(5);
beep = 0;
delay50ms(5);
}
work_status = START_QD_STATUS;//設置工作狀態為開始搶答狀態
}
if(end == 0)//結束按鍵按下
{
end_Timer0();//結束定時器0
qd_num = 0;
qd_time = 0;
work_status = START_QD_STATUS;//設置工作狀態為開始搶答狀態
}
}
/******數碼管顯示函數
二位數碼管顯示倒計時時間
一位數碼管顯示搶答選手號******/
void display(unsigned char qd_time, unsigned char qd_num)
{
P2 = duanxuan[qd_time/10];//顯示時間十位
k0 = 1; //打開第一位數碼管位選
delay2ms();
k0 = 0;
P2 = duanxuan[qd_time%10];//顯示時間個位
k2 = 1; //打開第二位數碼管位選
delay2ms();
k2 = 0;
P2 = duanxuan[qd_num%10];//顯示選手號
k4 = 1; //打開第三位數碼管位選
delay2ms();
k4 = 0;
}
/******主函數******/
void main()
{
init();//初始化
while(1)
{
switch(work_status)//工作狀態判斷
{
case START_QD_STATUS://開始搶答狀態
start_qd_status();
break;
case WAIT_QD_STATUS://等待選手搶答狀態
wait_qd_status();
break;
case ACK_QD_STATUS://選手回答狀態
ack_qd_status();
break;
default:
break;
}
display(qd_time, qd_num);//數碼管顯示
}
}
/******定時器0中斷處理函數******/
void Timer0Interrupt(void) interrupt 1
{
timeout_num++;
TH0 = 0x3C;
TL0 = 0x0B0;
if(timeout_num==20)
{
timeout_num=0;
qd_time--;
}
}
|
|