篮球计分板课设,模块化LCD1602,数码管,矩阵按键,方便移植,使得主函数简洁明了

适合普中的51开发板,也可以用与自己的课设,工程链接失效了记得

 代码,原理图PCB链接

http://链接:https://pan.baidu.com/s/1kcMKkNcIq45z6v0zLAPjeg?pwd=1234 提取码:1234

篮球场计分板
要求:
开机1602显示:

两个按键实现A队的分数加减
两个按键实现B队的分数加减
一个启动键一个暂停键一个按键控制节数一个复位键
(1)开机数码管显示单节比赛时间12分00秒;
(2)矩阵键盘,sw1负责启动,倒计时开始; sw2暂停,sw3清零,清零后显示比赛时间12分00秒,LED显示也清零。
(3)设定每队每次进攻时间为24秒时间,当24秒时间到,进攻方违例,报警LED1~LED3闪烁三次,比赛时间暂停,换方开球进攻并启动计时时间;
(4)单节比赛结束4位数码管闪烁。
(5)进球:分A、B两队进球,两个按键分别表示得分,例如当A队进分球则按下A-SW三下分数加3分,当B队进分球则按下B-SW两下分数加2分 有问题可以加Q3492181286

主函数
 

#include <REGX52.H>
#include "Delay.h"                    //包含Delay头文件
#include "Nixie.h"                    //包含数码管头文件
#include "MatrixKey.h"            //矩阵按键头文件
#include "LCD1602.h"            //液晶屏头文件
#define NixieTable                 //定义数码管

unsigned int a=0,i,b=0;           //a,b分别为A,B队分数,i为节数
unsigned char KeyNum;             //键盘
int min=12;sec=0;sec_24=24;  //开机显示

void Timer1Init()                            //定时器方式1
{
    TMOD|=0X10;
    TH1=0XFC;
    TL1=0X18;    
    ET1=1;
    EA=1;
    TR1=1;        
}
void main()
{
    Timer1Init();                          //定时器初始化
    LCD_Init();                                        //LCD初始化
    LCD_ShowChar(1,2,'A');                //在1行1列显示字符A
    LCD_ShowString(1,8,"VS");            //在1行8列显示字符串VS
    LCD_ShowChar(1,15,'B');                //在1行14列显示字符B
    LCD_ShowNum(2,14,b,3);                //在LCD的2行14列显示b,长度为3位
    LCD_ShowNum(2,1,a,3);                    //在LCD的2行14列显示a,长度为3位
    LCD_ShowNum(2,8,i,1);                    //在LCD的2行8列显示i,长度为1位
    TR1=0;
    while(1)
    {        
        Nixie(1,min/10);        //在数码管的第1位置显示1
        Nixie(2,min%10);        //在数码管的第2位置显示2    
        Nixie(3,sec/10);        //在数码管的第3位置显示0
        Nixie(4,sec%10);        //在数码管的第4位置显示0    
        Nixie(5,sec_24/10);    //在数码管的第5位置显示2
        Nixie(6,sec_24%10);    //在数码管的第6位置显示4
        
        KeyNum=MatrixKey();
            if(KeyNum)
            {
                if(KeyNum==1)    //启动
                {
                    TR1=1;
                }
                    if(KeyNum==2)   //按键2按下比赛时间暂停
                    {
                            TR1=0;        
                    }
                    if(KeyNum==3)  //按键3按下比赛时间复位
                        {
                            min=12;
                            sec=0;
                            sec_24=24;
                        }
                            if(KeyNum==5)   //按键5按下A队分数加1
                            {
                                LCD_ShowNum(2,1,a=a+1,3);
                            }while(KeyNum==5);
                                if(KeyNum==6)   //按键6按下B队分数加1
                                {
                                    LCD_ShowNum(2,14,b=b+1,3);
                                }while(KeyNum==6);
                                    if(KeyNum==4)   //按键4按下节数1
                                    {
                                            LCD_ShowNum(2,8,i=i+1,1);
                                    }while(KeyNum==4);                                
            }
            if(sec_24==0)        //24秒违规后led闪烁三次
            {
                TR1=0;
                sec_24=24;
                P2_3=1;P2_1=1;P2_2=1;
                Delay(500);
                P2_3=0;P2_1=0;P2_2=0;
                Delay(500);
                P2_3=1;P2_1=1;P2_2=1;
                Delay(500);
                P2_3=0;P2_1=0;P2_2=0;
                Delay(500);
                P2_3=1;P2_1=1;P2_2=1;
                Delay(500);
                P2_3=0;P2_1=0;P2_2=0;
                Delay(500);
            }    
            if(min==0)         //12分钟后lcd清零
            {
                LCD_ShowNum(2,1,0,3);
                LCD_ShowNum(2,14,0,3);
                LCD_ShowNum(2,8,0,1);
                P0=0;
                P0=1;
                Delay(500);
                P0=0;
                P0=1;
                Delay(500);
            }
    }
}

void Timer1() interrupt 3    //实现数码管时间变化
{    
    unsigned int i;
    TH1=0XFC;    
    TL1=0X18;
    i++;                 //以上四行为一秒的函数
    if(i==1000)          //1000次计次时间为1秒
    {
        i=0;
        sec--;
        sec_24--;    //秒自减
    }    
    if(sec==0)  
        {
            sec=59;
            min--;    //分自减
        }
}

延时函数<Delay.c>

//延时子函数
void Delay(unsigned int xms)
{
    unsigned char i, j;
    while(xms--)
    {
        i = 2;
        j = 239;
        do
        {
            while (--j);
        } while (--i);
    }
}

<Delay.h>

#ifndef __DELAY_H__
#define __DELAY_H__

void Delay(unsigned int xms);

#endif


数码管配置函数<Nixie.c>

#include <REGX52.H>
#include "Delay.h"    //包含Delay头文件

//数码管段码表
unsigned char NixieTable[10]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};

//数码管显示子函数
void Nixie(unsigned char Location,Number)
{
    switch(Location)        //位码输出
    {
        case 1:P2_4=1;P2_3=1;P2_2=1;break;
        case 2:P2_4=1;P2_3=1;P2_2=0;break;
        case 3:P2_4=1;P2_3=0;P2_2=1;break;
        case 4:P2_4=1;P2_3=0;P2_2=0;break;
        case 5:P2_4=0;P2_3=1;P2_2=1;break;
        case 6:P2_4=0;P2_3=1;P2_2=0;break;
        case 7:P2_4=0;P2_3=0;P2_2=1;break;
        case 8:P2_4=0;P2_3=0;P2_2=0;break;
    }
    
    P0=NixieTable[Number];    //段码输出
    Delay(1);                //显示一段时间
    P0=0x00;                //段码清0,消影
}

<Nixie.h>

#ifndef __NIXIE_H__
#define __NIXIE_H__

void Nixie(unsigned char Location,Number);

#endif

矩阵按键<Key.c>

#include <REGX52.H>
#include "Delay.h"

/**
  * @brief  矩阵键盘读取按键键码
  * @param  无
  * @retval KeyNumber 按下按键的键码值
            如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
  */
unsigned char MatrixKey()
{
    unsigned char KeyNumber=0;
    
    P1=0xFF;
    P1_3=0;
    if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;}
    if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
    if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
    if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
    
    P1=0xFF;
    P1_2=0;
    if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
    if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
    if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
    if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
    
    P1=0xFF;
    P1_1=0;
    if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
    if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
    if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
    if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
    
    P1=0xFF;
    P1_0=0;
    if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
    if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
    if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
    if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
    
    return KeyNumber;
}

<Key.h>

#ifndef __MATRIXKEY_H__
#define __MATRIXKEY_H__

unsigned char MatrixKey();

#endif


LCD1602.c

#include <REGX52.H>

//引脚定义
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_E=P2^7;
#define LCD_DataPort P0

/**
  * @brief  LCD1602延时函数,12MHz调用可延时1ms
  * @param  无
  * @retval 无
  */
void LCD_Delay()        //@12.000MHz 1ms
{
    unsigned char i, j;

    i = 2;
    j = 239;
    do
    {
        while (--j);
    } while (--i);
}

/**
  * @brief  LCD1602写命令
  * @param  Command 要写入的命令
  * @retval 无
  */
void LCD_WriteCommand(unsigned char Command)
{
    LCD_RS=0;
    LCD_RW=0;
    LCD_DataPort=Command;
    LCD_E=1;
    LCD_Delay();
    LCD_E=0;
    LCD_Delay();
}

/**
  * @brief  LCD1602写数据
  * @param  Data 要写入的数据
  * @retval 无
  */
void LCD_WriteData(unsigned char Data)
{
    LCD_RS=1;
    LCD_RW=0;
    LCD_DataPort=Data;
    LCD_E=1;
    LCD_Delay();
    LCD_E=0;
    LCD_Delay();
}

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init(void)
{
    LCD_WriteCommand(0x38);
    LCD_WriteCommand(0x0C);
    LCD_WriteCommand(0x06);
    LCD_WriteCommand(0x01);
}

/**
  * @brief  LCD1602设置光标位置
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @retval 无
  */
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
    if(Line==1)
    {
        LCD_WriteCommand(0x80|(Column-1));
    }
    else
    {
        LCD_WriteCommand(0x80|(Column-1)+0x40);
    }
}

/**
  * @brief  在LCD1602指定位置上显示一个字符
  * @param  Line 行位置,范围:1~2
  * @param  Column 列位置,范围:1~16
  * @param  Char 要显示的字符
  * @retval 无
  */
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char)
{
    LCD_SetCursor(Line,Column);
    LCD_WriteData(Char);
}

/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=0;String[i]!='\0';i++)
    {
        LCD_WriteData(String[i]);
    }
}

/**
  * @brief  返回值=X的Y次方
  */
int LCD_Pow(int X,int Y)
{
    unsigned char i;
    int Result=1;
    for(i=0;i<Y;i++)
    {
        Result*=X;
    }
    return Result;
}

/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData('0'+Number/LCD_Pow(10,i-1)%10);
    }
}

/**
  * @brief  在LCD1602指定位置开始以有符号十进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:-32768~32767
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
    unsigned char i;
    unsigned int Number1;
    LCD_SetCursor(Line,Column);
    if(Number>=0)
    {
        LCD_WriteData('+');
        Number1=Number;
    }
    else
    {
        LCD_WriteData('-');
        Number1=-Number;
    }
    for(i=Length;i>0;i--)
    {
        LCD_WriteData('0'+Number1/LCD_Pow(10,i-1)%10);
    }
}

/**
  * @brief  在LCD1602指定位置开始以十六进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~0xFFFF
  * @param  Length 要显示数字的长度,范围:1~4
  * @retval 无
  */
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    unsigned char SingleNumber;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        SingleNumber=Number/LCD_Pow(16,i-1)%16;
        if(SingleNumber<10)
        {
            LCD_WriteData('0'+SingleNumber);
        }
        else
        {
            LCD_WriteData('A'+SingleNumber-10);
        }
    }
}

/**
  * @brief  在LCD1602指定位置开始以二进制显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~1111 1111 1111 1111
  * @param  Length 要显示数字的长度,范围:1~16
  * @retval 无
  */
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
    unsigned char i;
    LCD_SetCursor(Line,Column);
    for(i=Length;i>0;i--)
    {
        LCD_WriteData('0'+Number/LCD_Pow(2,i-1)%2);
    }
}

LCD1602.h

#ifndef __LCD1602_H__
#define __LCD1602_H__

void LCD_Init(void);
void LCD_ShowChar(unsigned char Line,unsigned char Column,unsigned char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,unsigned char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漏洞嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值