手动计分器

目录

一、需求分析(从用户角度 UML)

         1.1设计内容

1.2 设计目标

1.3实验平台和工具

1.4 设计的功能分析

1.5 设计的非功能性分析

二、总体设计

         2.1总体方案设计

2.2 演示支持方案(如何利用开发板资源或外接模块,实现功能演示的方案,传感器(或模拟)演示方案)

三、模块设计与实现(介绍本课设钟主要模块的设计思路,实现方法,可以通过流程图,状态图,关键代码,显示效果等多种手段说明)

四、系统集成设计(与其它系统的通信、连接,和相互作用设计,参考结构,根据项目增减)

五、系统测试

5.1 系统测试

5.2 单元测试

5.3 非功能性测试

六、系统测试

          数码管0一直显示为8,多次调试仍然不行,因为单片机内部某模块正在运行,所以即使修              改初始值,数码管0也一直为8。修改数码管上显示两队分数的位数时,S2键功能失效,重              新编写扫描键盘的函数后功能恢复。总体来说,本项目功能较为简单,易于实现。

附录1原理图

附录2 源程序清单


一、需求分析(从用户角度 UML)

1.1设计内容

本项目设计开发一款手动计分器,用户可通过手动控制改变分值与赛程。

1.2 设计目标

1.数码管0123显示A队分数,数码管4567显示B队分数;

2.裁判按动K1键比赛开始,进行计时;

3.裁判按动K2键比赛中止,计时暂停,再次按动K2,比赛继续,计时正常进行;

4.裁判按动K3键比赛终止,程序复位,分数清零,计时归零;

5.按动S1A队加一分,按动S2加两分;按动S3B队加一分,按动S4加两分;

6.按动S5取消A队上次加分,按动S6取消B队上次加分。

1.3实验平台和工具

平台:Keil;

工具:STC89C52单片机

1.4 设计的功能分析

单片机可以实现计分功能,使用动态数码管,LCD1602,独立按键,矩阵键盘4个模块。动态数码管模块用来记录分数,数码管0123显示A队分数,数码管4567显示B队分数;LCD1602用来显示时间;独立按键用来控制赛程;矩阵键盘用来控制分数的加减。

1.5 设计的非功能性分析

通过本程序的设计可设计出一个手动计分器,应用于实际生活中也是非常建议方便。

二、总体设计

2.1总体方案设计

1.赛程控制

K1:比赛开始;

K2:比赛中止;

K3:比赛终止。

2.分数设置

S1:A队加1分;

S2:A队加2分;

S3:B队加1分;

S4:B队加2分;

S5:A队上一次加分撤销;

S6:B队上一次加分撤销;

K3:两队分数清零。

3.时间显示

时间将显示在LCD1602显示屏上。

K2:时间暂停;

K3:时间清零。

2.2 演示支持方案(如何利用开发板资源或外接模块,实现功能演示的方案,传感器(或模拟)演示方案)

在单片机下载完成后,51单片机的最左边一位数码管显示为8,其他位数码管显示为零,LCD1602显示“Time 00:00”。在按下独立按键K1后,时间显示的秒针位开始计时。按下矩阵键盘的S1,数码管3由0变成1,按下矩阵键盘的S3,数码管7由0变成1,按下矩阵键盘的S2数码管3由1变成3,按下矩阵键盘的S4,数码管7由1变成3,按下S5,数码管3由3变成1,按下S6,数码管7由3变成1。

按下K2,计时停止,分数不清零,再次按动K2,计时继续,矩阵键盘功能正常。按动K3,计时清零,分数清零,再次按动K1,比赛开始,计时与分数从0开始。

2.3 单片机资源分配设计(包括RAM资源分配,I/O资源分配)

没有具体要求

三、模块设计与实现(介绍本课设钟主要模块的设计思路,实现方法,可以通过流程图,状态图,关键代码,显示效果等多种手段说明)

3.1分配按键功能

sbit K1=P3^1;     //按键

sbit K2=P3^0;     //按键

sbit WS3=P3^2;     //按键

sbit SW4=P3^3;     //按键

sbit LS138A = P2^2;   //定义138译码器的输入A脚由P2.2控制

sbit LS138B = P2^3;     //定义138译码器的输入脚B由P2.3控制

sbit LS138C = P2^4; //定义138译码器的输入脚C由P2.4控制

3.2LCD1602相关指令

void write_com(uchar com)     //1602液晶写指令

{

rs=0;                       //写指令

lcden=0;                    //使能1602

P0=com;                     //写入指令com

LCD_Delay_us(10);            //延时1ms

lcden=1;                    //使能1602

LCD_Delay_us(20);            //延时2ms  

lcden=0;                 //使能1602

}

// 描述:1602液晶写数据

void write_date(uchar date) //1602液晶写数据

{

rs=1;                        //写数据

lcden=0;                     //使能1602

P0=date;                     //写入数据date

LCD_Delay_us(10);             //延时1ms

lcden=1;                     //使能1602

LCD_Delay_us(20);             //延时2ms

lcden=0;                  //使能1602

}

// 描述:指定x,y写入字符函数

 void W_lcd(unsigned char x,unsigned char y,unsigned char Data)

 {     

 if (y == 0){write_com(0x80 + x);}   //第一行  

 else{write_com(0xc0 + x);}          //第二行

 write_date( Data);                  //写入数据

 }

 //指定x,y写入字符串函数

 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)

 {     

 if (y == 0){write_com(0x80 + x);} //第一行

 else{write_com(0xC0 + x);}         //第二行

 while (*s)                         //

  {write_date( *s); s++;}       //写入数据

 }

// 描述:初始化液晶,及画面初始化

void init_lcd(void)            //初始化液晶,及画面初始化

{

wela=0;                      //写液晶

lcden=0;                     //使能1602

write_com(0x38);             //8 位总线,双行显示,5X7 的点阵字符

LCD_Delay_us(100);           //延时100us

write_com(0x0c);             //开显示,无光标,光标不闪烁

write_com(0x06);             //光标右移动

write_com(0x01);             //清屏

write_com(0x80);             //DDRAM 地址归0

}

3.3动态数码管显示数据

void DIS_SEG(void)//在LED上显示数据

{

          

          dispaly[1]=AA%1000/100;

dispaly[2]=AA%100/10;

dispaly[3]=AA%10;

dispaly[5]=BB%1000/100;

dispaly[6]=BB%100/10;

dispaly[7]=BB%10;

LS138A=0; LS138B=0; LS138C=0;//选择第几位数码管

P0 = tab[dispaly[7]];//显示数据

delayms(1);//延时

LS138A=1; LS138B=0; LS138C=0; //选择第几位数码管

P0 = tab[dispaly[6]];//显示数据

delayms(1);//延时

LS138A=0; LS138B=1; LS138C=0; //选择第几位数码管

P0 = tab[dispaly[5]];//显示数据

delayms(1);//延时

LS138A=1; LS138B=1; LS138C=0;//选择第几位数码管

P0 = 0;//显示数据

delayms(1);//延时

LS138A=0; LS138B=0; LS138C=1; //选择第几位数码管

P0 = tab[dispaly[4]];//显示数据

delayms(1);//延时

LS138A=1; LS138B=0; LS138C=1;//选择第几位数码管

P0 = tab[dispaly[3]];//显示数据

delayms(1);//显示数据

LS138A=0; LS138B=1; LS138C=1;//选择第几位数码管

P0 =tab[dispaly[2]];//显示数据

delayms(1);//延时

LS138A=1; LS138B=1; LS138C=1; //选择第几位数码管

P0 = 0;//显示数据

    delayms(1);//延时

}

3.4反转法扫描按键

u8 key_matrix_flip_scan(void)

{

static u8 key_value=0;

KEY_MATRIX_PORT=0x0f;

if(KEY_MATRIX_PORT!=0x0f)

{

delayms(1);

if(KEY_MATRIX_PORT!=0x0f)

{

KEY_MATRIX_PORT=0x0f;

switch(KEY_MATRIX_PORT)

{

case 0x07: key_value=1;break;

case 0x0b: key_value=2;break;

case 0x0d: key_value=3;break;

case 0x0e: key_value=4;break;

}

KEY_MATRIX_PORT=0xf0;

switch(KEY_MATRIX_PORT)

{

case 0x70: key_value=key_value;break;

case 0xb0: key_value=key_value+4;break;

case 0xd0: key_value=key_value+8;break;

case 0xe0: key_value=key_value+12;break;

}

while(KEY_MATRIX_PORT!=0xf0);

}

}

else

key_value=0;

return key_value;

}

四、系统集成设计(与其它系统通信、连接,和相互作用设计,参考结构,根据项目增减)

没有使用

五、系统测试

5.1 系统测试

5.2 单元测试

1.开始

2.按动K1

 3.按动S1

 4.按动S2

5.按动S3

6.按动S4

7.按动S5

8.按动S6

9.按动K2

10.再次按动S2

11.按动S3

5.3 非功能性测试

六、系统测试

数码管0一直显示为8,多次调试仍然不行,因为单片机内部某模块正在运行,所以即使修改初始值,数码管0也一直为8。修改数码管上显示两队分数的位数时,S2键功能失效,重新编写扫描键盘的函数后功能恢复。总体来说,本项目功能较为简单,易于实现。

附录1原理图

附录2 源程序清单

#include<reg51.h>

#define uint unsigned int

#define uchar unsigned char

#define KEY_MATRIX_PORT P1

#define SMG_A_DP_PORT P0

sbit K1=P3^1;     //按键

sbit K2=P3^0;     //按键

sbit WS3=P3^2;     //按键

sbit SW4=P3^3;     //按键

sbit LS138A = P2^2;   //定义138译码器的输入A脚由P2.2控制

sbit LS138B = P2^3;     //定义138译码器的输入脚B由P2.3控制

sbit LS138C = P2^4; //定义138译码器的输入脚C由P2.4控制

uchar code tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x58,0x00,0x40,0x46,0x80,0xb0,0x79,0x5c,0x50};//共阴数码码表 01010000

                 /* 0    1    2   3    4    5    6    7    8    9     C   无   -     +    .     /.  E    o     r*/

uint  AA=0;//A队

uint  BB=0;//B队

uint  CC=0;//A队备份

uint  DD=0;//B队备份

uchar fen=0;//分

uchar miao=0;//秒

uchar ii;//

uchar dispaly[]={0,0,0,0,0,0,0,0,0,0,0,0};         //显示缓冲

//--------LCD1602-------------------

sbit rs = P2^6;   //1602液晶

sbit wela = P2^5;   //1602液晶

sbit lcden = P2^7;   //1602液晶

//************************************************************************/

// 描述: 延时t us函数

//************************************************************************/

void LCD_Delay_us(unsigned int t)

{

while(t--);                 //t=0,退出

}

//************************************************************************/

// 描述: 延时t ms函数

//************************************************************************/

void LCD_Delay_ms(unsigned int t)

{

unsigned int i,j;

for(i=0;i<t;i++)        //执行t次循环

for(j=0;j<113;j++)      //执行113次循环

;

}

//************************************************************************/

// 描述: 1602液晶写指令

//************************************************************************/

void write_com(uchar com)     //1602液晶写指令

{

rs=0;                       //写指令

lcden=0;                    //使能1602

P0=com;                     //写入指令com

LCD_Delay_us(10);            //延时1ms

lcden=1;                    //使能1602

LCD_Delay_us(20);            //延时2ms  

lcden=0;                 //使能1602

}

//************************************************************************/

// 描述:1602液晶写数据

//************************************************************************/

void write_date(uchar date) //1602液晶写数据

{

rs=1;                        //写数据

lcden=0;                     //使能1602

P0=date;                     //写入数据date

LCD_Delay_us(10);             //延时1ms

lcden=1;                     //使能1602

LCD_Delay_us(20);             //延时2ms

lcden=0;                  //使能1602

}

//************************************************************************/

// 描述:指定x,y写入字符函数

//************************************************************************/

 void W_lcd(unsigned char x,unsigned char y,unsigned char Data)

 {     

 if (y == 0){write_com(0x80 + x);}   //第一行  

 else{write_com(0xc0 + x);}          //第二行

 write_date( Data);                  //写入数据

 }

 //指定x,y写入字符串函数

 void LCD_Write_String(unsigned char x,unsigned char y,unsigned char *s)

 {     

 if (y == 0){write_com(0x80 + x);} //第一行

 else{write_com(0xC0 + x);}         //第二行

 while (*s)                         //

  {write_date( *s); s++;}       //写入数据

 }

//************************************************************************/

// 描述:初始化液晶,及画面初始化

//************************************************************************/

void init_lcd(void)            //初始化液晶,及画面初始化

{

wela=0;                      //写液晶

lcden=0;                     //使能1602

write_com(0x38);             //8 位总线,双行显示,5X7 的点阵字符

LCD_Delay_us(100);           //延时100us

write_com(0x0c);             //开显示,无光标,光标不闪烁

write_com(0x06);             //光标右移动

write_com(0x01);             //清屏

write_com(0x80);             //DDRAM 地址归0

}

//************************************************************************/

// 描述: 延时t ms函数

//************************************************************************/

void delayms(unsigned int t)

{

unsigned int i,j;

for(i=0;i<t;i++)        //执行t次循环

for(j=0;j<120;j++)      //执行113次循环

;

}

void DIS_SEG(void)//在LED上显示数据

{

          

          dispaly[1]=AA%1000/100;

dispaly[2]=AA%100/10;

dispaly[3]=AA%10;

dispaly[5]=BB%1000/100;

dispaly[6]=BB%100/10;

dispaly[7]=BB%10;

LS138A=0; LS138B=0; LS138C=0;//选择第几位数码管

P0 = tab[dispaly[7]];//显示数据

delayms(1);//延时

LS138A=1; LS138B=0; LS138C=0; //选择第几位数码管

P0 = tab[dispaly[6]];//显示数据

delayms(1);//延时

LS138A=0; LS138B=1; LS138C=0; //选择第几位数码管

P0 = tab[dispaly[5]];//显示数据

delayms(1);//延时

LS138A=1; LS138B=1; LS138C=0;//选择第几位数码管

P0 = 0;//显示数据

delayms(1);//延时

LS138A=0; LS138B=0; LS138C=1; //选择第几位数码管

P0 = tab[dispaly[4]];//显示数据

delayms(1);//延时

LS138A=1; LS138B=0; LS138C=1;//选择第几位数码管

P0 = tab[dispaly[3]];//显示数据

delayms(1);//显示数据

LS138A=0; LS138B=1; LS138C=1;//选择第几位数码管

P0 =tab[dispaly[2]];//显示数据

delayms(1);//延时

LS138A=1; LS138B=1; LS138C=1; //选择第几位数码管

P0 = 0;//显示数据

    delayms(1);//延时

}

//************************************************************************/

// 描述: 反转法键盘扫描

//************************************************************************/

u8 key_matrix_flip_scan(void)

{

static u8 key_value=0;

KEY_MATRIX_PORT=0x0f;

if(KEY_MATRIX_PORT!=0x0f)

{

delayms(1);

if(KEY_MATRIX_PORT!=0x0f)

{

KEY_MATRIX_PORT=0x0f;

switch(KEY_MATRIX_PORT)

{

case 0x07: key_value=1;break;

case 0x0b: key_value=2;break;

case 0x0d: key_value=3;break;

case 0x0e: key_value=4;break;

}

KEY_MATRIX_PORT=0xf0;

switch(KEY_MATRIX_PORT)

{

case 0x70: key_value=key_value;break;

case 0xb0: key_value=key_value+4;break;

case 0xd0: key_value=key_value+8;break;

case 0xe0: key_value=key_value+12;break;

}

while(KEY_MATRIX_PORT!=0xf0);

}

}

else

key_value=0;

return key_value;

}

void main()

{ uchar   key=0xff;               //键值初始化

uchar   n=0;   //第1个数可以按1-4次

uchar   m=4; //第2个数可以按1-4次

uchar   x=0;

uchar   j=0;

uchar   stop=0;

init_lcd();   //1602液晶初始化

TMOD=01;//定时器0,,16位定时方式

TH0=65535-50000/256;//50MS

TL0=65535-50000%256;//50MS

EA=1;

ET0=1;

TR0=0;

EA =1;              //开中断

    miao=0;fen=0;

AA=0;

BB=0;

stop=0;

   while(1)

  {

DIS_SEG();//数码管显示

 W_lcd(1,0,'T');

 W_lcd(2,0,'i');

 W_lcd(3,0,'m');

 W_lcd(4,0,'e');

 W_lcd(5,0,' ');

  W_lcd(6,0,fen/10+'0');

  W_lcd(7,0,fen%10+'0');

  W_lcd(8,0,':');

  W_lcd(9,0,miao/10+'0');

W_lcd(10,0,miao%10+'0');

 W_lcd(11,0,' ');

if(K1==0)

{

while(!K1){;}

miao=0;fen=0;TR0=1;//开始

}

if(K2==0)

{

while(!K2){;}

if(stop==0){TR0=0;stop=1;}else{TR0=1;stop=0;}//暂停

}

if(WS3==0)

{

// while(!K3){;}

AA=0;BB=0;fen=0;miao=0;TR0=0;//清零

}

   key=keycheckdown(); /*动态扫描键盘,返回按键对应值,赋给j        key=0到f */

if(0xff!=key) /*若返回值有效,进入内部处理程序*/

{

if(key==1){CC=AA;AA=AA+1;}//加1

if(key==2){CC=AA;AA=AA+2;}//加2

if(key==3){DD=BB;BB=BB+1;}//加1

if(key==4){DD=BB;BB=BB+2;}//加2

if(key==5){AA=CC;}//恢复

if(key==6){BB=DD;}//恢复

do{P1=0xf0;}while(P1!=0xf0); /*等待按键松开*/

}

P0=0X00;

   }  

  }

  //1MS 定时器计数

void T0_time() interrupt 1

{

TH0=(65535-50000)/256;//50MS

TL0=(65535-50000)%256;//50MS

ii++;

if(ii==20)//0.5ms*2=1ms

{ii=0;

miao++;

if(miao>59){miao=0;fen++;if(fen>59){fen=59;miao=59;}}        //秒倒计时

} //分倒计时

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值