這是我做的單片機設計,能夠滿足A,B隊加分、減分,節數的加減,比賽的暫停,24S計時等功能。如果要拓展功能的話可以在函數中增加。兩個程序一個是仿真的,一個是可以燒到單片機開發板里的,因為我的接口有一點不一樣。主要的程序還是在論壇上借鑒了一個帖子的。
籃球計分計時器仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
單片機源程序如下:
- #include<reg52.h>
- #define uint unsigned int
- #define uchar unsigned char
- uchar code table[]="!! BASKETBALL !!";
- uchar code table1[]="!! A VS B !!" ;
- unsigned char code KEY_CODE[] =
- {
- 0xEE,0xED,0xEB,0xE7,
- 0xDE,0xDD,0xDB,0xD7,
- 0xBE,0xBD,0xBB,0xB7,
- 0x7E,0x7D,0x7B,0x77
- };
- sbit lcdrs = P3^5; //RS端
- sbit lcden = P3^4; //EN端
- sbit lcdrw=P3^6;
- uchar flag,ms,mg,ss,sg,ds,dg,as,ag,bs,bg,num=0,num2,js=1,C,D,t,min=0; //ds,dg.24秒倒計時
- int sec=0,dd=24;
- //==========定義延時函數===========
- void delayms(uint xms)
- {
- uint i,j;
- for(i=xms;i>0;i--)
- for(j=110;j>0;j--);
- }
- void Read_Busy()
- {
- uchar busy;
- P0=0xff;
- lcdrs=0;
- lcdrw=1;
- do
- {
- lcden=1;
- busy=P0;
- lcden=0;
- }
- while(busy &0x80);
- }
- //========定義LCD的數據模式========
- void write_data(uchar date) //定義為數據模式
- {
- Read_Busy();
- lcdrs=1;
- delayms(5);
- lcdrw=0; //清屏
- delayms(5);
- P0=date;
- delayms(5);
- lcden=1;
- delayms(5);
- lcden=0;
- }
- //=======定義LCD的命令模式=========
- void write_com(uchar com) //定義為命令模式
- {
- Read_Busy();
- delayms(5);
- lcdrs=0;
- delayms(5); //RS=0 寫命令
- lcdrw=0;
- delayms(5);
- P0=com;
- delayms(5); //稍作延時以待數據穩定
- lcden=1; //E=1
- delayms(5);
- lcden=0; //E=0 當E由1變0時LCD執行命令 以完成高脈沖
- }
- //=======LCD顯示屏初始化===========
- void lcd_init() //LCD顯示屏的初始化
- {
- lcden=0; //E=0
- delayms(5);
- write_com(0x38);
- delayms(5);
- write_com(0x0c); //00001100開整體顯示,光標關,無閃爍
- delayms(5);
- write_com(0x06); //00000110符后,地址指針加一
- delayms(5);
- write_com(0x01); //00000001清屏
- }
- //======LCD顯示屏的初始化2(輸出Qtr,A:,B:T-等)
- void init()
- { delayms(5);
- lcden=0; //E=0
- delayms(5);
- write_com(0x83); //節數顯示
- write_data(' ');
- write_data('Q');
- write_data('t');
- write_data('r');
- delayms(5);
- write_com(0x88); //時間顯示
- write_data('T');
- write_data('_');
- delayms(5);
- write_com(0x8c);
- write_data(':');
- delayms(5);
- write_com(0x80+0x42); //A隊
- write_data('A');
- write_data(':');
- delayms(5);
- write_com(0x80+0x48); //B隊
- write_data('B');
- write_data(':');
- delayms(5);
- }
- //======啟動時顯示程序======
- void init_start()
- {
- delayms(5);
- lcd_init();
- lcden=0; //E=0
- write_com(0x80+0x10);
- delayms(5); //在第一行10位置顯示
- for(num2=0;num2<16;num2++) //寫第二行字
- {
- write_data(table[num2]);
- delayms(5);
- }
- write_com(0x80+0x50); //在第一行50位置輸出
- for(num2=0;num2<17;num2++)
- {
- write_data(table1[num2]); //輸出第一行
- delayms(5);
- }
- for(num2=0;num2<16;num2++)
- {
- write_com(0x18); //移動顯示的字符
- delayms(200);
- }
- }
- //========顯示程序=========
- void display(uchar min,int sec,uchar C,uchar D,uchar js,int dd)
- {
- ss=sec/10; //秒的十位
- sg=sec%10; //秒的個位
- ms=min/10; //分的十位
- mg=min%10; //分的個位
- ds=dd/10; //倒計時的十位
- dg=dd%10; //倒計時的個位
- as=C/10; //A隊分數的十位
- ag=C%10; //A隊分數的個位
- bs=D/10; //B對分數的十位
- bg=D%10; //B隊分數的個位
- delayms(5);
- write_com(0x82);
- write_data(0x30+js);
- delayms(5);
- write_com(0x8a);
- write_data(0x30+ms);
- write_data(0x30+mg);
- delayms(5);
- write_com(0x8d);
- write_data(0x30+ss);
- write_data(0x30+sg);
- delayms(5);
- write_com(0x80+0x44);
- write_data(0x30+as);
- write_data(0x30+ag);
- delayms(5);
- write_com(0x80+0x4a);
- write_data(0x30+bs);
- write_data(0x30+bg);
- delayms(5);
- write_com(0x80+0x4d);
- write_data(0x30+ds);
- write_data(0x30+dg);
- delayms(5);
- }
- //======定時器0,控制本節顯示時間====
- void T0_time()interrupt 1 //定時器0控制LCD顯示示時間
- {
- TH0=(65536-45872)/256; // 重裝初值
- TL0=(65536-45872)%256;
- num++;
- if(num==20)
- {
- num=0;
- sec--;
- dd--;
- if(sec<0)
- {
- sec=59;
- min--;
- }
- if(dd<0)
- {
- delayms(10);
- dd=24;
- }
- }
- }
- void app_handle(uchar eventCode)
- {
- switch(eventCode)
- {
- //======START/PAUSE=====
- case 0x8:
- delayms(5);
- if(flag==0)
- {
- lcd_init();//清屏設置屬性
- delayms(5);
- init();//顯示Qrt,A,B等基本數據
- }
- flag=1;
- TR0=~TR0;
- delayms(5);
- display(min,sec,C,D,js,dd);
- delayms(5);
- while(min==0&&sec==0)
- {
- TR0=0; //定時器0暫停
- delayms(5);
- min=11;
- sec=60;
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- delayms(5);
- }
- break;
-
- //======A隊分數顯示=======
- case 0x0:
- delayms(5);
- C--;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- delayms(5);
- break; //加分出錯可糾正
- case 0x1:
- delayms(5);
- C++;
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- delayms(5);
- break;
-
- case 0x2:
- delayms(5);
- C+=2;
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- delayms(5);
- break;
- case 0x3:
- delayms(5);
- C+=3;
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- break;
-
- //======B隊分數顯示=====
- case 0x4:
- delayms(5);
- D--;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- break;
- //加分出錯時可糾正
- case 0x5:
- delayms(5);
- D++;
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- break;
-
- case 0x6:
- delayms(5);
- D+=2;
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- break;
- case 0x7:
- delayms(5);
- D+=3;
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- break;
-
- //======比賽24s倒計時====
- case 0x9:
- delayms(5);
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- break;
- //======比賽節數======
- case 0xa:
- if(js<4)
- {
- delayms(5);
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- min=11;
- sec=60;
- TR0=1;
- js++;
- delayms(5);
- display(min,sec,C,D,js,dd);
- }
- break;
- //======加時賽=======
- case 0xb:
- delayms(5);
- while(js==4&&C==D)
- {
- delayms(5);
- dd=24;
- delayms(10);
- TR0=1;
- delayms(5);
- display(min,sec,C,D,js,dd);
- min=4;
- sec=60;
- js++;
- delayms(5);
- display(min,sec,C,D,js,dd);
- }
- break;
-
- default:break;
- }
- }
- uchar KEY_getCode(void)
- {
- uchar lineCode = 0x00;
- ……………………
- …………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
所有資料51hei提供下載:
PROTEUS程序.zip
(2.38 KB, 下載次數: 99)
2018-1-16 14:55 上傳
點擊文件名下載附件
開發板程序.zip
(2.48 KB, 下載次數: 75)
2018-1-16 14:55 上傳
點擊文件名下載附件
仿真.zip
(26.15 KB, 下載次數: 91)
2018-1-16 14:54 上傳
點擊文件名下載附件
|