久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 2310|回復(fù): 11
收起左側(cè)

用51單片機(jī)制作10路數(shù)字搶答器程序修改問(wèn)題

[復(fù)制鏈接]
ID:675815 發(fā)表于 2019-12-31 16:08 | 顯示全部樓層 |閱讀模式
請(qǐng)各位大佬幫忙看下程序要怎么修改才對(duì),謝謝謝謝!此程序已試過(guò)仿真和實(shí)物,現(xiàn)象顯示不對(duì),蜂鳴器一直響,數(shù)碼管四位一起從0-9閃爍循環(huán)。
具體要求:(1)搶答器同時(shí)供 10 名選手或 10 個(gè)代表隊(duì)比賽。 (2)設(shè)置一個(gè)系統(tǒng)清除和搶答控制開(kāi)關(guān) S,該開(kāi)關(guān)由主持人控制。 (3) 搶答器具有鎖存與顯示功能。即選手按動(dòng)按鈕,鎖存相應(yīng)的編號(hào),并在 LED 數(shù)碼管上顯示,同時(shí) 揚(yáng)聲器發(fā)出報(bào)警聲響提示。選手搶答實(shí)行優(yōu)先鎖存,優(yōu)先搶答選手的編號(hào)一直保持到主持人將系統(tǒng)清除為止。 (4)搶答器具有定時(shí)搶答功能,且一次搶答的時(shí)間由主持人設(shè)定(如 20 秒)。當(dāng)主持人啟動(dòng)"開(kāi)始"鍵后, 定時(shí)器進(jìn)行減計(jì)時(shí),同時(shí)揚(yáng)聲器發(fā)出短暫的聲響,聲響持續(xù)的時(shí)間 0.5 秒左右。 (5)參賽選手在設(shè)定的時(shí)間內(nèi)進(jìn)行搶答,搶答有效,定時(shí)器停止工作,顯示器上顯示選手的編號(hào)和搶 答的時(shí)間,并保持到主持人將系統(tǒng)清除為止。 (6)如果定時(shí)時(shí)間已到,無(wú)人搶答,本次搶答無(wú)效,系統(tǒng)報(bào)警并禁止搶答,定時(shí)顯示器上顯示 00。
原理圖如下:
51hei圖片20191231160654.png

程序如下:
#include <reg51.h>     //包含單片機(jī)寄存器的頭文件
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int

uchar LED[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf}; //共陽(yáng)數(shù)碼管:0-9,-
int count,qdtime,num_mark,qdtime1=20;
sbit smg_we1 = P2^0;
sbit smg_we2 = P2^1;
sbit smg_we3 = P2^2;
sbit smg_we4 = P2^3;
//選手相關(guān)區(qū)
sbit LED1=P3^7;
sbit LED2=P3^6;
sbit LED3=P3^5;
sbit LED4=P3^4;
sbit LED5=P3^3;
sbit LED6=P3^2;
sbit LED7=P3^1;
sbit LED8=P3^0;
sbit LED9=P2^6;
sbit LED10=P2^7;//選手搶答“監(jiān)視燈”
sbit S1=P3^7;
sbit S2=P3^6;
sbit S3=P3^5;
sbit S4=P3^4;
sbit S5=P3^3;
sbit S6=P3^2;
sbit S7=P3^1;
sbit S8=P3^0;
sbit S9=P2^6;
sbit S10=P2^7;//選手搶答按鈕
uchar S[]={1,1,1,1,1,1,1,1,1,1};//選手按鈕按下標(biāo)記位,按下后便標(biāo)記為1
//主持人相關(guān)區(qū)
sbit S11=P1^0;//清除
sbit S12=P1^1;//搶答開(kāi)始
sbit S13=P1^2;//加時(shí)間
sbit S14=P1^3;//減時(shí)間
sbit BeepIO= P1^6;
/******************************************
延時(shí)函數(shù)
**********************************************/
void delay10ms()  //@12.000MHz
{
unsigned char i, j;
i = 117;
j = 184;
do
{
  while (--j);
} while (--i);
}

void delay(uint i)//i微秒延時(shí)
{ while(i--) ;}

/************************************************************
蜂鳴器發(fā)音程序區(qū)
**************************************************************/
void BEEP()//提示音
{  unsigned int i;
  for(i=0;i<100;i++)//喇叭發(fā)聲的時(shí)間循環(huán)
   {
   delay(100);     //參數(shù)決定發(fā)聲的頻率,估算值
   BeepIO=!BeepIO;
   }
  BeepIO=1;            //喇叭停止工作,間歇的時(shí)間
  delay(5000);
}
void BEEP2()//警告音
{  unsigned int i;
  for(i=0;i<400;i++)//喇叭發(fā)聲的時(shí)間循環(huán)
   {
   BeepIO=0;
   delay(40);     //參數(shù)決定發(fā)聲的頻率,估算值
   BeepIO=1;
   delay(30);
   }            
  delay(12500);//喇叭停止工作,間歇的時(shí)間         
}
void BEEP3()//搶答成功提示音
{  unsigned int i;
   for(i=0;i<400;i++)//喇叭發(fā)聲的時(shí)間循環(huán)
   {
   BeepIO=0;
   delay(25);     //參數(shù)決定發(fā)聲的頻率
   BeepIO=1;
   delay(25);
   }            
  delay(20000);//喇叭停止工作,間歇的時(shí)間
}
void shumaxs(int n,uchar m)//數(shù)碼管顯示程序
{ int sj1,sj2,dw1,dw2;
P0=0xff;
P1=0x00;
delay(50);
  sj1=n/10;
sj2=n%10;
dw1=m/10;
dw2=m%10;
  P0=LED[sj1];smg_we4=1;delay(20);
  P0=LED[sj2];smg_we3=1;delay(20);
P0=LED[dw1];smg_we2=1;delay(20);
P0=LED[dw2];smg_we1=1;delay(20);  
}
void Timer0_init (void)//T0初始化子函數(shù)
{
TMOD=0x01;//T0設(shè)置為16位定時(shí)方式
  TH0=0x3c;
  TL0=0xb0;//50ms
  ET0=1;  //允許T0中斷
  EA=1;
// TR0=0;     //關(guān)閉定時(shí)開(kāi)關(guān)
}
void timer0() interrupt 1  //倒計(jì)時(shí)
{
   TH0=0x3c;
  TL0=0xb0;     
  count++;
  if(count==20)
  { count=0;
   qdtime--;   
  }
}
void key1()
{ S[1]=1;S[2]=1;S[3]=1;S[4]=1;S[5]=1;S[6]=1;S[7]=1;S[8]=1;S[9]=1;S[10]=1;//選手按鈕按下標(biāo)記位歸零
if(S12==1)
{ delay10ms();if(S12==1)
  { TR0=1;
   {switch(P3&&0xff)
    { case 0x7f: num_mark=1;LED1=0;break;
     case 0xbf: num_mark=2;LED2=0;break;
     case 0xdf: num_mark=3;LED3=0;break;
     case 0xef: num_mark=4;LED4=0;break;
     case 0xf7: num_mark=5;LED5=0;break;
     case 0xfb: num_mark=6;LED6=0;break;
     case 0xfd: num_mark=7;LED7=0;break;
     case 0xfe: num_mark=8;LED8=0;break;
     
    }
    switch(P2&&0xff)
    { case 0x7f: num_mark=9;LED9=0;break;
     case 0xbf: num_mark=10;LED10=0;break;
    }
  }
   if((num_mark!=0)&&(qdtime!=0))  
   { TR0=0;
    shumaxs(qdtime,LED[num_mark]);
    BEEP3();
   }//有人搶答成功則結(jié)束搶答
    if((qdtime==0)&&(num_mark==0))
   { TR0=0;
    shumaxs(0xbf,0xbf);
    BEEP2();
   }
  }
}
}

void key2()
{ if(S11==1)
{delay10ms();if(S11==1) {BeepIO=0;qdtime=0;shumaxs(0xbf,0xc0);}}
if(S12==1)
  {delay10ms();if(S12==1) {BEEP();shumaxs(LED[num_mark],qdtime);}}
if(S13==1)
{ delay10ms();
   if(S13==1)
   {qdtime++;if(qdtime>99) qdtime=0;shumaxs(0xbf,qdtime);}
}
if(S14==1)
{ delay10ms();
   if(S13==1)
    {qdtime--;if(qdtime>99) qdtime=0;shumaxs(0xbf,qdtime);}
}
}
  
void main()
{ qdtime=qdtime1;shumaxs(20,0);
  Timer0_init();//T0初始化
BeepIO=0;//蜂鳴器不響
TR0=0;
while(1)
  {
  LED1=1;LED2=1;LED3=1;LED4=1;LED5=1;LED6=1;LED7=1;LED8=1;LED9=1;LED10=1;//監(jiān)視燈初始化為滅
  key2();
  key1();
}
}

回復(fù)

使用道具 舉報(bào)

ID:648281 發(fā)表于 2020-1-1 20:48 | 顯示全部樓層
你好!
從你描述的情況來(lái)看,程序?qū)?yīng)要求的錯(cuò)誤還很多;
只能根據(jù)你的要求,把程序分功能模塊逐段調(diào)試。
回復(fù)

使用道具 舉報(bào)

ID:332444 發(fā)表于 2020-1-2 08:36 | 顯示全部樓層
用蛋騙雞直接驅(qū)動(dòng)數(shù)碼管出現(xiàn)的問(wèn)題,必須要用三極管或鎖存器驅(qū)動(dòng)數(shù)碼管,你這是常見(jiàn)的驅(qū)動(dòng)設(shè)計(jì)問(wèn)題
回復(fù)

使用道具 舉報(bào)

ID:675815 發(fā)表于 2020-1-2 14:21 | 顯示全部樓層
51hei**1140 發(fā)表于 2020-1-1 20:48
你好!
從你描述的情況來(lái)看,程序?qū)?yīng)要求的錯(cuò)誤還很多;
只能根據(jù)你的要求,把程序分功能模塊逐段調(diào)試。

好的,謝謝!
回復(fù)

使用道具 舉報(bào)

ID:675815 發(fā)表于 2020-1-2 14:21 | 顯示全部樓層
xianfajushi 發(fā)表于 2020-1-2 08:36
用直接驅(qū)動(dòng)數(shù)碼管出現(xiàn)的問(wèn)題,必須要用三極管或鎖存器驅(qū)動(dòng)數(shù)碼管,你這是常見(jiàn)的驅(qū)動(dòng)設(shè)計(jì)問(wèn)題

好的,謝謝
回復(fù)

使用道具 舉報(bào)

ID:1137639 發(fā)表于 2025-4-17 15:44 | 顯示全部樓層
你好! 從你描述的情況來(lái)看,程序?qū)?yīng)要求的錯(cuò)誤還很多; 只能根據(jù)你的要求,把程序分功能模塊逐段調(diào)試。
回復(fù)

使用道具 舉報(bào)

ID:332444 發(fā)表于 2025-4-19 08:36 | 顯示全部樓層
622323wjl 發(fā)表于 2025-4-17 15:44
你好! 從你描述的情況來(lái)看,程序?qū)?yīng)要求的錯(cuò)誤還很多; 只能根據(jù)你的要求,把程序分功能模塊逐段調(diào)試。

這個(gè)帖子也翻找出來(lái)了,許多年了未知題主還關(guān)注不,看看我當(dāng)時(shí)回復(fù)挺搞笑的,不知道怎么想的!電路圖中數(shù)碼管沒(méi)錯(cuò),代碼用阻塞不是很好選擇,雖然是獨(dú)立按鍵,但是整組使用時(shí)可以不單獨(dú)定義,整組判斷可對(duì)應(yīng)一個(gè)按鍵操作,賦值255判斷是否不等于255就有按鍵按下,特定值對(duì)應(yīng)一個(gè)按鍵,另外2個(gè)按鍵可獨(dú)立定義,按鍵寫中斷不是很好選擇,尤其還有阻塞參與其中,按鍵要求盡量快判斷結(jié)束,不影響數(shù)碼管顯示時(shí)間。
回復(fù)

使用道具 舉報(bào)

ID:332444 發(fā)表于 2025-4-19 08:42 | 顯示全部樓層
當(dāng)時(shí)提出用鎖存器也是一個(gè)辦法,現(xiàn)在看來(lái)從軟件上能解決,那是要重寫這個(gè)程序。
回復(fù)

使用道具 舉報(bào)

ID:1109793 發(fā)表于 2025-4-19 15:28 | 顯示全部樓層
這種按鍵判定方式有問(wèn)題,假設(shè)同一時(shí)刻有多個(gè)按鍵按下,那么接P3高位的就優(yōu)先被判定,然而事實(shí)上極大可能是相對(duì)低位的按鍵先按下,只是在你讀取之前,相對(duì)高位的按鍵也按下了,此時(shí)你讀到的是2個(gè)位為0的數(shù)據(jù),但是你在先判定了高位的就是后按下的那個(gè)之后便不再理會(huì)相對(duì)低位的那個(gè)開(kāi)關(guān)了,雖然這個(gè)時(shí)間很短,參賽者只能認(rèn)倒霉,但是這種情況還是極有可能的。
回復(fù)

使用道具 舉報(bào)

ID:1137639 發(fā)表于 2025-4-19 22:34 | 顯示全部樓層
以下是對(duì)該程序的問(wèn)題分析及修改建議:

### 一、程序問(wèn)題分析
1. **按鍵檢測(cè)與消抖**
    - 在`key1`和`key2`函數(shù)中,按鍵檢測(cè)部分雖然有簡(jiǎn)單的延時(shí)消抖(`delay10ms()` ),但不夠完善。對(duì)于按鍵釋放的檢測(cè)沒(méi)有處理,可能導(dǎo)致按鍵誤觸發(fā)。比如在`key1`函數(shù)中,當(dāng)檢測(cè)到`S12`按鍵按下并進(jìn)行一系列操作后,沒(méi)有等待按鍵釋放就繼續(xù)檢測(cè)其他按鍵,可能會(huì)在按鍵還未完全釋放時(shí)再次檢測(cè)到按鍵按下,造成邏輯混亂。
    - `switch`語(yǔ)句中對(duì)端口數(shù)據(jù)的處理邏輯有誤。在`switch(P3&&0xff)`和`switch(P2&&0xff)`中,這種寫法不能準(zhǔn)確獲取端口的實(shí)際電平狀態(tài)。應(yīng)該直接使用`P3`和`P2`進(jìn)行判斷,即`switch(P3)`和`switch(P2)` 。
2. **定時(shí)器相關(guān)問(wèn)題**
    - 在`timer0`中斷函數(shù)中,只對(duì)倒計(jì)時(shí)進(jìn)行了處理,沒(méi)有對(duì)定時(shí)時(shí)間到且無(wú)人搶答的情況進(jìn)行全面處理。當(dāng)`qdtime`減為0時(shí),應(yīng)該禁止后續(xù)的搶答操作,而當(dāng)前代碼沒(méi)有相關(guān)設(shè)置。
    - `count`變量用于計(jì)數(shù)中斷次數(shù)以實(shí)現(xiàn)倒計(jì)時(shí),但在初始化時(shí)沒(méi)有清零,可能導(dǎo)致初始倒計(jì)時(shí)不準(zhǔn)確。
3. **數(shù)碼管顯示問(wèn)題**
    - `shumaxs`函數(shù)中,數(shù)碼管位選邏輯存在問(wèn)題。在給不同位數(shù)碼管賦值時(shí),位選信號(hào)沒(méi)有及時(shí)關(guān)閉,可能會(huì)導(dǎo)致數(shù)碼管顯示混亂。比如在給高位數(shù)碼管賦值后,沒(méi)有關(guān)閉其位選信號(hào)就給低位數(shù)碼管賦值,會(huì)使數(shù)碼管顯示出現(xiàn)重疊或錯(cuò)誤的現(xiàn)象。
    - 數(shù)碼管顯示程序沒(méi)有考慮到不同情況下顯示的切換邏輯。例如,在無(wú)人搶答定時(shí)時(shí)間到的情況下,應(yīng)該顯示特定的標(biāo)識(shí)(如“00” ),但當(dāng)前代碼在這種情況下顯示處理不夠完善。
4. **搶答邏輯問(wèn)題**
    - 選手搶答標(biāo)記數(shù)組`S`的使用邏輯有誤。在`key1`函數(shù)中,每次檢測(cè)到搶答開(kāi)始(`S12`按下 )就將所有選手的標(biāo)記位歸零,這會(huì)導(dǎo)致之前已經(jīng)按下?lián)尨鸢粹o的選手標(biāo)記被清除,無(wú)法實(shí)現(xiàn)優(yōu)先鎖存的功能。
    - 沒(méi)有對(duì)多個(gè)選手同時(shí)搶答的情況進(jìn)行處理。當(dāng)多個(gè)選手同時(shí)按下?lián)尨鸢粹o時(shí),當(dāng)前代碼不能準(zhǔn)確判斷并鎖存最先搶答的選手編號(hào)。

### 二、修改建議
1. **按鍵檢測(cè)與消抖改進(jìn)**
    - 在`key1`和`key2`函數(shù)中,完善按鍵檢測(cè)邏輯,增加按鍵釋放檢測(cè)。例如,在檢測(cè)到按鍵按下并進(jìn)行操作后,添加一個(gè)循環(huán)等待按鍵釋放:
```c
while(S12 == 1); // 等待S12按鍵釋放
```
    - 修正`switch`語(yǔ)句中對(duì)端口數(shù)據(jù)的判斷方式,直接使用端口值進(jìn)行判斷,如:
```c
switch(P3)
{
    case 0x7f: num_mark = 1; LED1 = 0; break;
    case 0xbf: num_mark = 2; LED2 = 0; break;
    // 其他case語(yǔ)句類似
}
switch(P2)
{
    case 0x7f: num_mark = 9; LED9 = 0; break;
    case 0xbf: num_mark = 10; LED10 = 0; break;
}
```
2. **定時(shí)器相關(guān)改進(jìn)**
    - 在`timer0`中斷函數(shù)中,當(dāng)`qdtime`減為0時(shí),添加禁止搶答的邏輯,例如設(shè)置一個(gè)標(biāo)志位:
```c
if(count == 20)
{
    count = 0;
    qdtime--;
    if(qdtime == 0)
    {
        // 設(shè)置禁止搶答標(biāo)志位,比如定義一個(gè)全局變量 no_answer_flag = 1;
        no_answer_flag = 1;
    }
}
```
    - 在初始化時(shí),將`count`變量清零:
```c
void Timer0_init (void)
{
    TMOD = 0x01;
    TH0 = 0x3c;
    TL0 = 0xb0;
    ET0 = 1;
    EA = 1;
    count = 0; // 初始化count為0
    // TR0 = 0;
}
```
3. **數(shù)碼管顯示改進(jìn)**
    - 在`shumaxs`函數(shù)中,修改數(shù)碼管位選邏輯,確保在給一位數(shù)碼管賦值后及時(shí)關(guān)閉其位選信號(hào),再給下一位數(shù)碼管賦值:
```c
void shumaxs(int n, uchar m)
{
    int sj1, sj2, dw1, dw2;
    P0 = 0xff;
    P1 = 0x00;
    delay(50);
    sj1 = n / 10;
    sj2 = n % 10;
    dw1 = m / 10;
    dw2 = m % 10;

    P0 = LED[sj1]; smg_we4 = 1; delay(20); smg_we4 = 0; // 關(guān)閉位選信號(hào)
    P0 = LED[sj2]; smg_we3 = 1; delay(20); smg_we3 = 0;
    P0 = LED[dw1]; smg_we2 = 1; delay(20); smg_we2 = 0;
    P0 = LED[dw2]; smg_we1 = 1; delay(20); smg_we1 = 0;
}
```
    - 在主程序和相關(guān)函數(shù)中,完善不同情況下數(shù)碼管顯示的邏輯。例如,在無(wú)人搶答定時(shí)時(shí)間到的情況下,修改`shumaxs`函數(shù)的調(diào)用參數(shù)以顯示“00”:
```c
if((qdtime == 0) && (num_mark == 0))
{
    TR0 = 0;
    shumaxs(0, 0); // 顯示00
    BEEP2();
}
```
4. **搶答邏輯改進(jìn)**
    - 修正選手搶答標(biāo)記數(shù)組`S`的使用邏輯。在檢測(cè)到有選手搶答后,只修改該選手對(duì)應(yīng)的標(biāo)記位,而不是將所有標(biāo)記位歸零。例如:
```c
if(S1 == 0) { S[1] = 0; num_mark = 1; LED1 = 0; }
else if(S2 == 0) { S[2] = 0; num_mark = 2; LED2 = 0; }
// 其他選手類似
```
    - 增加對(duì)多個(gè)選手同時(shí)搶答的處理邏輯。可以記錄最早檢測(cè)到的搶答選手編號(hào),例如在檢測(cè)到有選手搶答時(shí),記錄當(dāng)前時(shí)間(通過(guò)定時(shí)器計(jì)數(shù)值等方式 ),比較不同選手搶答時(shí)的時(shí)間,優(yōu)先鎖存時(shí)間最早的選手編號(hào)。

通過(guò)以上修改,可以在一定程度上解決程序中存在的問(wèn)題,使其更符合搶答器的功能要求。在實(shí)際調(diào)試過(guò)程中,還需要進(jìn)一步根據(jù)具體現(xiàn)象進(jìn)行優(yōu)化和調(diào)整。
回復(fù)

使用道具 舉報(bào)

ID:332444 發(fā)表于 2025-4-21 14:28 | 顯示全部樓層
xiaobendan001 發(fā)表于 2025-4-19 15:28
這種按鍵判定方式有問(wèn)題,假設(shè)同一時(shí)刻有多個(gè)按鍵按下,那么接P3高位的就優(yōu)先被判定,然而事實(shí)上極大可能是 ...

如果整組判斷就不會(huì)出現(xiàn)因程序造成的不公平問(wèn)題。
回復(fù)

使用道具 舉報(bào)

ID:1109793 發(fā)表于 2025-4-21 14:40 | 顯示全部樓層
xianfajushi 發(fā)表于 2025-4-21 14:28
如果整組判斷就不會(huì)出現(xiàn)因程序造成的不公平問(wèn)題。

按鍵比較多,不可能同時(shí)。
而且讀取時(shí)間間隔也必須越小越好,比如納秒級(jí)別。
否則就只能是對(duì)每個(gè)按鍵引入中斷,在中斷里面固定證據(jù)。然后再判定,這樣會(huì)好一些。
再不行就只有純硬件了。
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 日韩av.com | 99re视频 | 国产精品资源在线观看 | 亚洲电影成人 | 国产精品不卡视频 | 久久里面有精品 | 国产成人99久久亚洲综合精品 | 成人免费在线播放 | 国产一区二区三区视频免费观看 | 久久久精品一区 | 亚洲一区视频在线 | 日韩在线小视频 | 国产一区二区在线免费观看 | 日韩福利| 国产精品99久久久久久宅男 | 亚洲成年影院 | 国产亚洲精品久久yy50 | 一区二区成人在线 | 久久精品欧美视频 | 国产综合久久 | 欧美日韩一区在线播放 | 日韩在线视频免费观看 | 亚洲视频在线观看一区二区三区 | 国产精品久久久久久久7电影 | 免费黄网站在线观看 | 亚洲一区视频在线 | 天天插天天射天天干 | 黄色大片在线播放 | 国产专区免费 | 91精品国产日韩91久久久久久 | 一区二区三区欧美 | 国产一级视频 | 97人人超碰 | 国产一区二区在线免费观看 | 精品国产成人 | 亚洲欧美日韩精品久久亚洲区 | 亚洲视频在线看 | 一级黄色片免费 | 久草99 | 国产一区亚洲二区三区 | 成人在线电影网站 |