基于单片机的篮球记分牌.docx
《基于单片机的篮球记分牌.docx》由会员分享,可在线阅读,更多相关《基于单片机的篮球记分牌.docx(23页珍藏版)》请在冰豆网上搜索。
基于单片机的篮球记分牌
篮球记分牌
一.设计要求:
1、比赛开始,比分能够全部清零,数码管前2位、末2位做记分用,当中2位做24秒倒计时用。
2、24秒倒计时时间到,蜂鸣器响、指示灯亮,重新开始倒计时,蜂鸣器停止鸣叫、指示灯灭。
3、比分进行增加后,倒计时从24秒重新开始倒计时。
任意时刻24秒可以重新开始倒计时。
必要时候能够关闭倒计时。
4、利用AT24C02或者单片机内部资源保存比分,支持复位保存,掉电保存功能。
5、其他附加功能。
二.原理图:
三.实验流程图:
四.实验程序:
Main.c文件:
/*********************************************************************************************
函数名:
篮球记分牌
说明:
比赛开始,比分能够全部清零,数码管前2位、末2位做记分用,当中2位做24秒倒计时用。
24秒倒计时时间到,蜂鸣器响、指示灯亮,重新开始倒计时,蜂鸣器停止鸣叫、指示灯灭。
比分进行增加后,倒计时从24秒重新开始倒计时。
任意时刻24秒可以重新开始倒计时。
必要时候能够关闭倒计时。
作者:
完成日期:
2012.12.2
/**********************************************************************************************/
#include
#include
#include"eeprom.h"
#defineucharunsignedchar
#defineuintunsignedint
/***********端口定义*************/
/*数码管段选用P0口,位选用P2口*/
/******指示灯******/
sbitLED=P3^4;
/********蜂鸣器*********/
sbitFMQ=P3^5;
/******数组定义*******/
ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x07f,0x6f};//0,1,2,3,4,5,6,7,8,9
ucharpassword[6];//掉电保存6位数组
/***********变量定义*************/
ucharfen1;//甲队初始得分
ucharfen2;//乙队初始得分
ucharfen3;//甲乙两队上下半场换分
ucharSJ;//时间变量值
ucharcxjs=1;//重新计时标志位
ucharkey;//矩阵键盘按键值
uchartemp;//矩阵键盘P1口寄存变量
uchartime;//中断计数器
/***********************************************************
函数名称:
delay
函数功能:
基本延时程序
入口参数:
无
出口参数:
无
备注:
无
***********************************************************/
voiddelay(ucharx)
{ucharj;
while((x--)!
=0)
{for(j=0;j<125;j++)
{;}
}
}
/***********************************************************
函数名称:
display
函数功能:
数码管显示程序
入口参数:
fen1,fen2,SJ
出口参数:
无
备注:
无
***********************************************************/
voiddisplay(void)
{
ucharm;
for(m=6;m>0;m--)
{
delay
(2);
if(m==6)
{P2=0XFE;
P0=table[fen1/10];}
if(m==5)
{P2=0XFD;
P0=table[fen1%10];}
if(m==4)
{P2=0XFB;
P0=table[SJ/10];}
if(m==3)
{P2=0XF7;
P0=table[SJ%10];}
if(m==2)
{P2=0XEF;
P0=table[fen2/10];}
if(m==1)
{P2=0XDF;
P0=table[fen2%10];}
}
}
/***********************************************************
函数名称:
keyscan
函数功能:
4X4矩阵键盘扫描程序
入口参数:
无
出口参数:
无
备注:
读取的键值赋给了key
***********************************************************/
voidkeyscan(void)
{
temp=P1;
if(temp!
=0xf0)
{
delay(120);
if(temp!
=0xf0)
{
P1=0xfe;
temp=P1;
delay(120);
switch(temp)
{
case(0xee):
key=0;break;
case(0xde):
key=1;break;
case(0xbe):
key=2;break;
case(0x7e):
key=3;break;
}
P1=0xfd;
temp=P1;
delay(120);
switch(temp)
{
case(0xed):
key=4;break;
case(0xdd):
key=5;break;
case(0xbd):
key=6;break;
case(0x7d):
key=7;break;
}
P1=0xfb;
temp=P1;
delay(120);
switch(temp)
{
case(0xeb):
key=8;break;
case(0xdb):
key=9;break;
case(0xbb):
key=10;break;
case(0x7b):
key=11;break;
}
P1=0xf7;
temp=P1;
delay(120);
switch(temp)
{
case(0xe7):
key=12;break;
case(0xd7):
key=13;break;
case(0xb7):
key=14;break;
case(0x77):
key=15;break;
}
}
}
}
/***********************************************************
函数名称:
keydown
函数功能:
4X4矩阵键盘判断程序
入口参数:
无
出口参数:
无
备注:
判断是否有按键按下
***********************************************************/
voidkeydown(void)
{
P1=0xF0;
if(P1!
=0xF0)
{
delay(150);//消抖
if(P1!
=0xF0)
{keyscan();}
}
}
/***********************************************************
函数名称:
timer0init
函数功能:
定时器初始化部分程序
入口参数:
无
出口参数:
无
备注:
设置定时器0工作方式
***********************************************************/
voidtimer0init()
{
TMOD&=0xf0;//定时器0工作方式1
TMOD|=0x01;
}
/***********************************************************
函数名称:
timer0
函数功能:
中断服务程序
入口参数:
无
出口参数:
无
备注:
此程序无调用
***********************************************************/
voidtimer0(void)interrupt1using0
{
TH0=0x15;
TL0=0xa0;
time=time+1;
if(time==20)
{
time=0;
SJ=SJ-1;
if(SJ==0)
{SJ=0;
EA=0;
FMQ=0;
LED=0;}
}
}
/***********************************************************
函数名称:
setpassword
函数功能:
掉电保存程序
入口参数:
无
出口参数:
无
备注:
此程序调用eeprom_eares擦除扇区程序,eeprom_write字节编程程序
***********************************************************/
voidsetpassword()
{
eeprom_eares(0x0000);
eeprom_write(0x0000,fen1/10);
eeprom_write(0x0001,fen1%10);
eeprom_write(0x0002,SJ/10);
eeprom_write(0x0003,SJ%10);
eeprom_write(0x0004,fen2/10);
eeprom_write(0x0005,fen2%10);
}
/***********************************************************
函数名称:
getpassword
函数功能:
读出eeprom内存储值
入口参数:
无
出口参数:
无
备注:
无
***********************************************************/
voidgetpassword()
{
uchari;
for(i=0;i<6;i++)
password[i]=eeprom_read(i);
}
/***********************************************************
函数名称:
main
函数功能:
主程序
入口参数:
无
出口参数:
无
备注:
实现功能:
通过按键开始/停止,暂停/继续计时和对甲乙两队的加分
***********************************************************/
voidmain()
{
LED=1;
FMQ=1;
P2=0xFF;
P1=0xF0;
SJ=24;
fen1=0;
fen2=0;
key=16;
/*定时器设置*/
timer0init();
ET0=1;
TR0=1;
while
(1)
{
display();
keydown();
if(key==0)//开始按键
{
EA=1;
}
if(key==1)//甲队加分按键
{
fen1=fen1+1;
cxjs=0;
}
if(key==2)//乙队加分按键
{
fen2=fen2+1;
cxjs=0;
}
if(key==3)//暂停计时
{EA=0;}
if(key==4)//停止按键
{
fen1=0;
fen2=0;
SJ=24;
EA=0;
FMQ=1;
LED=1;
}
if(key==5)//上下半场换分
{
fen3=fen1;
fen1=fen2;
fen2=fen3;
}
if(cxjs==0)//重新计时
{
SJ=24;
cxjs=1;
}
if(key==6)//保存当前值
{setpassword();}
if(key==7)//调用前次记录
{
getpassword();
fen1=password[0]*10+password[1];
SJ=password[2]*10+password[3];
fen2=password[4]*10+password[5];
EA=0;
}
key=16;//此处赋值key,否则key将一直保留按键后的值
}
}
Eeprom.c文件:
#defineeeprom
#include"eeprom.h"
//-------------------------------------------------------------------------------------------------------
//EEPROM操作
//------------------------------------------------------------------------------------------------------
//定义Flash操作等待时间及允许IAP/ISP/EEPROM操作的常数
//#defineENABLE_ISP0x80//系统工作时钟<30MHz时,对IAP_CONTR寄存器设置此值
//#defineENABLE_ISP0x81//系统工作时钟<24MHz时,对IAP_CONTR寄存器设置此值
#defineENABLE_ISP0x82//系统工作时钟<20MHz时,对IAP_CONTR寄存器设置此值
//#defineENABLE_ISP0x83//系统工作时钟<12MHz时,对IAP_CONTR寄存器设置此值
//#defineENABLE_ISP0x84//系统工作时钟<6MHz时,对IAP_CONTR寄存器设置此值
//#defineENABLE_ISP0x85//系统工作时钟<3MHz时,对IAP_CONTR寄存器设置此值
//#defineENABLE_ISP0x86//系统工作时钟<2MHz时,对IAP_CONTR寄存器设置此值
//#defineENABLE_ISP0x87//系统工作时钟<1MHz时,对IAP_CONTR寄存器设置此值
unionunion_temp16
{
unsignedintun_temp16;
unsignedcharun_temp8[2];
}my_unTemp16;
unsignedchareeprom_read(unsignedintadd);//读一字节,调用前需打开IAP功能
voideeprom_write(unsignedintadd,unsignedcharch);//字节编程,调用前需打开IAP功能
voideeprom_eares(unsignedintadd);//擦除扇区
voidIAP_Disable();//关闭IAP功能
voidIAP_Disable()
{
//关闭IAP功能,清相关的特殊功能寄存器,使CPU处于安全状态,
//一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
IAP_CONTR=0;//关闭IAP功能
IAP_CMD=0;//清命令寄存器,使命令寄存器无命令,此句可不用
IAP_TRIG=0;//清命令触发寄存器,使命令触发寄存器无触发,此句可不用
IAP_ADDRH=0;
IAP_ADDRL=0;
}
//读一字节,调用前需打开IAP功能,入口:
DPTR=字节地址,返回:
A=读出字节
unsignedchareeprom_read(unsignedintadd)
{
IAP_DATA=0x00;
IAP_CONTR=ENABLE_ISP;//打开IAP功能,设置Flash操作等待时间
IAP_CMD=0x01;//IAP/ISP/EEPROM字节读命令
my_unTemp16.un_temp16=add;
IAP_ADDRH=my_unTemp16.un_temp8[0];//设置目标单元地址的高8位地址
IAP_ADDRL=my_unTemp16.un_temp8[1];//设置目标单元地址的低8位地址
//EA=0;
IAP_TRIG=0x5A;//先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
IAP_TRIG=0xA5;//送完A5h后,ISP/IAP命令立即被触发起动
_nop_();
//EA=1;
IAP_Disable();//关闭IAP功能,清相关的特殊功能寄存器,使CPU处于安全状态,
//一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
return(IAP_DATA);
}
//字节编程,调用前需打开IAP功能,入口:
DPTR=字节地址,A=须编程字节的数据
voideeprom_write(unsignedintadd,unsignedcharch)
{
IAP_CONTR=ENABLE_ISP;//打开IAP功能,设置Flash操作等待时间
IAP_CMD=0x02;//IAP/ISP/EEPROM字节编程命令
my_unTemp16.un_temp16=add;
IAP_ADDRH=my_unTemp16.un_temp8[0];//设置目标单元地址的高8位地址
IAP_ADDRL=my_unTemp16.un_temp8[1];//设置目标单元地址的低8位地址
IAP_DATA=ch;//要编程的数据先送进IAP_DATA寄存器
//EA=0;
IAP_TRIG=0x5A;//先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
IAP_TRIG=0xA5;//送完A5h后,ISP/IAP命令立即被触发起动
_nop_();
//EA=1;
IAP_Disable();//关闭IAP功能,清相关的特殊功能寄存器,使CPU处于安全状态,
//一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
}
//擦除扇区,入口:
DPTR=扇区地址
voideeprom_eares(unsignedintadd)
{
IAP_CONTR=ENABLE_ISP;//打开IAP功能,设置Flash操作等待时间
IAP_CMD=0x03;//IAP/ISP/EEPROM扇区擦除命令
my_unTemp16.un_temp16=add;
IAP_ADDRH=my_unTemp16.un_temp8[0];//设置目标单元地址的高8位地址
IAP_ADDRL=my_unTemp16.un_temp8[1];//设置目标单元地址的低8位地址
//EA=0;
IAP_TRIG=0x5A;//先送5Ah,再送A5h到ISP/IAP触发寄存器,每次都需如此
IAP_TRIG=0xA5;//送完A5h后,ISP/IAP命令立即被触发起动
_nop_();
//EA=1;
IAP_Disable();//关闭IAP功能,清相关的特殊功能寄存器,使CPU处于安全状态,
//一次连续的IAP操作完成之后建议关闭IAP功能,不需要每次都关
}
//-------------------------------------------------------------------------------------------------------
Eeprom.h文件:
#ifndef_eeprom_h_
#define_eeprom_h_
#ifdefeeprom
#include
#include"intrins.h"
#defineEXET
#else
#defineEXETextern
#endif
//typedefunsignedcharINT8U;
//typedefunsignedintINT16U;
EXETunsignedchareeprom_read(unsignedintadd);//读一字节,调用前需打开IAP功能
EXETvoideeprom_write(unsignedintadd,unsignedcharch);//字节编程,调用前需打开IAP功能
EXETvoideeprom_eares(unsignedintadd);//擦除扇区
#endif
五.实验仿真:
六.实验实物图:
七.实验总结:
通过这次单片机课程设计,我学到了很多东西。
主要收获有:
1.将理论教学与实践相结合,使我对于单片机的实际应用有了较深刻的认识;
2.使我对单片机应用系统设计的各种方法有所了解;
3.通过分工合作,培养了我和同学之间的合作精神;
4.让我熟悉了电子系统设计的全过程;提高了我对设计课题的分析能力、编程能力及解决实际问题的综合能力。
5.通过实践,增强了我下阶段的学习信心。
存在的问题:
1.对于基础知识掌握的不牢固。
2.缺乏对于电子系统设计测试的概念。
总之,通过这次单片机课程设计,我不但学到了很多知识,而且还看到了自己的不足之处,在以后的学习生活中,我会加以改正的。