这是我做的单片机设计,能够满足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)
开发板程序.zip
(2.48 KB, 下载次数: 75)
仿真.zip
(26.15 KB, 下载次数: 91)
|