基于单片机的羽毛球计分器(含proteus仿真和程序)

目录

完整文本及仿真、程序可私信我获取

前言

第一章 设计任务及方案 

1.1 设计任务 

1.2 总体设计分析

1.3 功能模块方案设计 

1.4 方案确定 

第二章、硬件设计 

2.1 AT89C51 单片机芯片介绍 

2.1.1 主要特性 

2.1.2 管脚说明 

2.1.3 元件清单 

2.2 电路介绍 

2.2.1 电源部分 

2.2.2 按键部分 

2.2.3 显示部分 

2.2.4 时钟、复位电路 

第三章、软件设计 

3.1 程序流程图 

3.2 模块设计 

3.2.1 主函数 

3.2.2 显示函数 

3.2.3 延时函数 

3.2.4 定时器函数 

3.2.5 中断函数 

3.2.6 字符转换函数 

3.2.7 全局变量定义及函数声明 

第四章、仿真与调试 

4.1 调试的环境 

4.2 按键及功能的调试 

总 结 

参考文献 

附 录


完整文本及仿真、程序可私信我获取

前言

        随着物质生活水平的提高,人们越来越重视生命的质量。据调查运动作为一种绿色消费在人民日常消费中所占得比例呈持续上升的趋势,全民健身运动热潮愈演愈烈,健身器材的市场需求也会不断扩大。羽毛球是一项室内、室外都可以进行的体育运动,在我国羽毛球运动是一项很普及的运动,更深受青少年的喜爱。其比赛规则经过多年的改进变得更公正合理,计分方式也变得多元化。近年来随着科技的发展,单片机的应用在不断深入,单片机的集成度高,通用性好,特别是它具有体积小,重量轻,能耗低,价格便宜,可靠性高,抗干扰能力强和使用方便等独特的优点,所以本课题采用单片机AT89C51作为本设计的核心元件。本设计由控制系统,显示模块,按键驱动模块3部分组成。主要编写了主程序,中断程序,显示程序功能模块程序等。实现羽毛球计分器功能。

第一章 设计任务及方案 

1.1 设计任务 

        设计一个羽毛球电子计分器,能用按键控制其启动、计分、停止、清零, 并在LM1602液晶屏上显示且自动输出比赛结果。

1.2 总体设计分析

        根据功能要求及设计成本,控制系统选用AT89C51芯片。采用按钮开关实现功能控制,按照设计的功能模块共选用8个按钮开关,分别实现启动、A队加分、A队减分、B队加分、B队减分、暂停、停止、清零功能。时钟电路由晶体振荡器、晶震控制芯片和电容组成,采用串行数据传输,为掉电保护电源提供可编程的充电功能,并且可以关闭充电功能。复位电路用来使电路恢复到起始状态的电路设备,确保微机系统中电路稳定可靠工作,是电路图中必不可少的一部分。选用LM1602液晶屏作为显示器件,用于记录两队的分数。

1.3 功能模块方案设计 

表1-1 按键功能

按键

功能说明

显示区域

S3

比赛开始

T00:00 A:B  00:00

S1

A队加一分

T00:30 A:B  01:00

S2

B队加一分

T01:00 A:B  01:01

S4

比赛暂停

T02:36 A:B  03:02

S5

A队减一分

T02:38 A:B  02:02

S6

B队减一分

T02:45 A:B  02:01

S7

时间、比分清零

T00:00 A:B  00:00

S8

比赛结束

END

1.4 方案确定 

选定方案描述:

        在像羽毛球这样的竞技比赛中,计分器占着很大的作用。如果我们就只在心里记着双方的比分,显然是不实际的,而且在现在的乒乓球比赛中采用的都是21分制。因此我们不能再用传统的计分方式了。本次课题采用单片机设计了一个羽毛球的计分器,该计分器操作简单,使用安全,方便,能满足广大羽毛球爱好者的需要。    

图1-1 总设计框图

     

第二章、硬件设计 

2.1 AT89C51 单片机芯片介绍 

        单片机就是一块硅片上集成了中央处理器(cpu)存储器和输入输出接口(并行I/O串行通信口)振荡电路,计数器等电路的一块集成电路,这样的一块集成电路具有一台计算机的基本功能,因而被称为单片微型计算机,简称单片机(MCU)。

图2-1 AT89C51 单片机

2.1.1 主要特性 

•与MCS-51 兼容

•4K字节可编程FLASH存储器

•寿命:1000写/擦循环

•数据保留时间:10年

•全静态工作:0Hz-24MHz

•三级程序存储器锁定

•128×8位内部RAM

•32可编程I/O线

•两个16位定时器/计数器

•5个中断源

•可编程串行通道

•低功耗的闲置和掉电模式

•片内振荡器和时钟电路

2.1.2 管脚说明 

VCC:供电电压。

GND:接地。

P0口:P0口为一个8位漏级开路双向I/O口,每脚可吸收8TTL门电流。当P0口的管脚第一次写1时,被定义为高阻输入。P0能够用于外部程序数据存储器,它可以被定义为数据/地址的低八位。在FIASH编程时,P0 口作为原码输入口,当FIASH进行校验时,P0输出原码,此时P0外部必须接上拉电阻。

P1口:P1口是一个内部提供上拉电阻的8位双向I/O口,P1口缓冲器能接收输出4TTL门电流。P1口管脚写入1后,被内部上拉为高,可用作输入,P1口被外部下拉为低电平时,将输出电流,这是由于内部上拉的缘故。在FLASH编程和校验时,P1口作为低八位地址接收。

P2口:P2口为一个内部上拉电阻的8位双向I/O口,P2口缓冲器可接收,输出4个TTL门电流,当P2口被写“1”时,其管脚被内部上拉电阻拉高,且作为输入。并因此作为输入时,P2口的管脚被外部拉低,将输出电流。这是由于内部上拉的缘故。P2口当用于外部程序存储器或16位地址外部数据存储器进行存取时,P2口输出地址的高八位。在给出地址“1”时,它利用内部上拉优势,当对外部八位地址数据存储器进行读写时,P2口输出其特殊功能寄存器的内容。P2口在FLASH编程和校验时接收高八位地址信号和控制信号。

P3口:P3口管脚是8个带内部上拉电阻的双向I/O口,可接收输出4个TTL门电流。当P3口写入“1”后,它们被内部上拉为高电平,并用作输入。作为输入,由于外部下拉为低电平,P3口将输出电流(ILL)这是由于上拉的缘故。

P3口也可作为AT89C51的一些特殊功能口,如下表所示:

口管脚 备选功能

P3.0 RXD(串行输入口)

P3.1 TXD(串行输出口)

P3.2 /INT0(外部中断0)

P3.3 /INT1(外部中断1)

P3.4 T0(计时器0外部输入)

P3.5 T1(计时器1外部输入)

P3.6 /WR(外部数据存储器写选通)

P3.7 /RD(外部数据存储器读选通)

P3口同时为闪烁编程和编程校验接收一些控制信号。

RST:复位输入。当振荡器复位器件时,要保持RST脚两个机器周期的高电平时间。

ALE/PROG:当访问外部存储器时,地址锁存允许的输出电平用于锁存地址的低位字节。在FLASH编程期间,此引脚用于输入编程脉冲。在平时,ALE端以不变的频率周期输出正脉冲信号,此频率为振荡器频率的1/6。因此它可用作对外部输出的脉冲或用于定时目的。然而要注意的是:每当用作外部数据存储器时,将跳过一个ALE脉冲。如想禁止ALE的输出可在SFR8EH地址上置0。此时, ALE只有在执行MOVX,MOVC指令是ALE才起作用。另外,该引脚被略微拉高。如果微处理器在外部执行状态ALE禁止,置位无效。

/PSEN:外部程序存储器的选通信号。在由外部程序存储器取指期间,每个机器周期两次/PSEN有效。但在访问外部数据存储器时,这两次有效的/PSEN信号将不出现。

/EA/VPP:当/EA保持低电平时,则在此期间外部程序存储器(0000H-FFFFH),不管是否有内部程序存储器。注意加密方式1时,/EA将内部锁定为RESET;当/EA端保持高电平时,此间内部程序存储器。在FLASH编程期间,此引脚也用于施加12V编程电源(VPP)。

XTAL1:反向振荡放大器的输入及内部时钟工作电路的输入。

XTAL2:来自反向振荡器的输出。

2.1.3 元件清单 

表2-1 元件清单

序号

元器件代号

名称

型号及参数

1

R×18

电阻

10K

2

C3

瓷片电容

10pF

3

XTAL1

晶振

11.0592M

4

C1-C2

瓷片电容

30PF

5

U1

芯片

AT89C51

6

LM1602

液晶屏

1

7

S1-S8

按钮

8

2.2 电路介绍 

2.2.1 电源部分 

         电源主要采用+5V电源,安全且节能环保,符合设计要求和环保要求。

2.2.2 按键部分 

        按键部分主要由A加分按钮、A误操作按钮、B加分按钮、B误操作按钮、开始计时按钮,暂停按钮,清零按钮,停止按钮八部分组成。其中S1为A加分按钮,S2为B加分按钮,S3为开始计时按钮,S4暂停按钮,S5为A误操作按钮,S6为B误操作按钮,S7为清零按钮,S8为停止按钮。

图2-2 按钮部分

2.2.3 显示部分 

        显示由LM1602液晶屏显示,显示功能区分为三个模块,分别为第一行显示比赛场次及谁获胜,第二行1-6位显示比赛时间,7-16行显示比分。时钟部分构成单片机的最小系统。

图2-3 LM1602液晶屏

2.2.4 时钟、复位电路 

图2-4 时钟、复位电路

第三章、软件设计 

3.1 程序流程图 

        系统的操作过程和工作过程在程序的设计过程中起着很重要的指导作用,因此在软件设计之前应首先分析羽毛球比赛记分器的工作原理。当比赛开始时,先判断是哪队得分,每次加分加1分。如果不小心加错分了,则按键减去多加的分。当比赛开始时,首先按下开始按钮S1显示开始工作,加分和误操作,暂停等按钮可工作。设计程序流程图如图3-1。

图3-1 程序流程图

3.2 模块设计 

3.2.1 主函数 
void main()
{	EA = 1;           //开总中断ConfigTimer0(1);  //配置T0定时1msInitLcd1602();    //初始化液晶while (1){KeyDriver();	//调用按键功能if(k==1)LcdInit();	 //显示字幕}
}
3.2.2 显示函数 
/* 等待液晶准备好 */
void LcdWaitReady()
{unsigned char sta;LCD1602_DB = 0xFF;LCD1602_RS = 0;LCD1602_RW = 1;do {LCD1602_E = 1;sta = LCD1602_DB; //读取状态字LCD1602_E = 0;} while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{LcdWaitReady();LCD1602_RS = 0;LCD1602_RW = 0;LCD1602_DB = cmd;LCD1602_E  = 1;LCD1602_E  = 0;
}
//显示字母及计时器
void LcdInit()
{if(flag1s == 1){sec++;flag1s = 0;}if(sec>=60){ minute++;sec = 0;if(minute>59)minute = 59;}LcdShowStr(0, 1, "T");len = LongToString(str, minute);LcdShowStr(1, 1, str);LcdShowStr(3, 1, ":");len = LongToString(str, sec);LcdShowStr(4, 1, str);LcdShowStr(7, 1, "A:B");len = LongToString(str, a);LcdShowStr(11, 1, str);LcdShowStr(13, 1, ":");len = LongToString(str, b);LcdShowStr(14, 1, str);	   	 
}
/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{LcdWaitReady();LCD1602_RS = 1;LCD1602_RW = 0;LCD1602_DB = dat;LCD1602_E  = 1;LCD1602_E  = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{unsigned char addr;if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址addr = 0x00 + x;  //第一行字符地址从0x00起始elseaddr = 0x40 + x;  //第二行字符地址从0x40起始LcdWriteCmd(addr | 0x80);  //设置RAM地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{LcdSetCursor(x, y);   //设置起始地址while (*str != '\0')  //连续写入字符串数据,直到检测到结束符{LcdWriteDat(*str++);}
}
/* 区域清除,清除从(x,y)坐标起始的len个字符位 */
void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len)
{LcdSetCursor(x, y);   //设置起始地址while (len--)         //连续写入空格{LcdWriteDat(' ');}
}/* 初始化1602液晶 */
void InitLcd1602()
{LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口//  LcdWriteCmd(0x0C);  //显示器开,光标关闭LcdWriteCmd(0x06);  //文字不动,地址自动+1LcdWriteCmd(0x01);  //清屏
}
3.2.3 延时函数 
void delay()
{unsigned int i,j;for(i=0;i<9000;i++)for(j=0;j<4;j++);
}
3.2.4 定时器函数 
/* 配置并启动T0,ms-T0定时时间 */
void ConfigTimer0(unsigned int ms)
{unsigned long tmp;  //临时变量tmp = 11059200 / 12;      //定时器计数频率tmp = (tmp * ms) / 1000;  //计算所需的计数值tmp = 65536 - tmp;        //计算定时器重载值tmp = tmp + 12;           //补偿中断响应延时造成的误差T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节T0RL = (unsigned char)tmp;TMOD &= 0xF0;   //清零T0的控制位TMOD |= 0x01;   //配置T0为模式1TH0 = T0RH;     //加载T0重载值TL0 = T0RL;ET0 = 1;        //使能T0中断
}
3.2.5 中断函数 
/* T0中断服务函数,配置定时器时间 */
void InterruptTimer0() interrupt 1
{static  unsigned count = 0;TH0 = T0RH;  //重新加载重载值TL0 = T0RL;count++;if(count>=1000){count = 0;flag1s = 1;}
}
3.2.6 字符转换函数 
//将数字转换为字符
unsigned char LongToString(unsigned char *str, signed long dat)
{signed char i = 0;signed char len = 0;unsigned char buf[3];	for(i=0;i<2;i++){buf[i] = dat%10;dat = dat/10;}len = i;for(i=1;i>=0;i--){*str++ = buf[i] + '0';}*str = '\0';return len;		
}
3.2.7 全局变量定义及函数声明 
#include <reg52.h>
#define LCD1602_DB  P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E  = P1^5;
unsigned char T0RH = 0;
unsigned char T0RL = 0;
sbit KEY_IN_1  = P2^0;
sbit KEY_IN_2  = P2^1;
sbit KEY_IN_3  = P2^2;
sbit KEY_IN_4  = P2^3;
sbit KEY_IN_5  = P2^4;
sbit KEY_IN_6  = P2^5;
sbit KEY_IN_7  = P2^6;
sbit KEY_IN_8  = P2^7;
bit flag1s = 0;	  //定时1s标志
char a = 0;		  //A的分数
char b = 0;		  //B的分数bit k=1;			//开显示开关
unsigned char minute = 0; //定时器分钟
unsigned char sec = 0;	  //定时器秒
unsigned char len = 0;	  //字符串转换长度
unsigned char str[3];	  //字符转换指针
void InitLcd1602();
void ConfigTimer0(unsigned int ms);
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
unsigned char LongToString(unsigned char *str, signed long dat);
void KeyDriver();
void LcdInit();

第四章、仿真与调试 

4.1 调试的环境 

        在Keil4.0中运行编写的程序,将生成的 .hex文件导入protues7.0中以连接好的电路的单片机中。

4.2 按键及功能的调试 

图4-1 电路原理图

        按下按钮S3表示比赛开始,定时器开始计时,其他按钮允许工作。A队赢球时,按一下S1按钮,A队加一分。B队赢球时,按一下S1按钮,B队加一分。若出现误加分情况,按钮S5\S6分别对A\B队减一分。如比赛过程中出现紧急情况需暂停比赛时,计分器S4按钮可实现暂停功能,其定时器暂停工作,加减分按钮失效,保证比赛的公正性。比赛结束时按钮S8实现停止功能,数据保存。按钮S7实现清零功能,比赛结束,可对下场比赛进行计时。

图4-2 比赛结果仿真图

        当A队获得第一场胜利时,屏幕上会有“1Awin”字样,B队获得第二场胜利,显示“1Awin2Bwin”字样。A队再次获胜后,计分器会自动进入停止状态,加分减分按钮失效,液晶屏显示此次比赛所用时间以及“1Awin2Bwin3Awin”,表示此次比赛A队为获胜方。

总 结 

        通过这两周的课程设计,我发现了自己的很多不足,自己知识的很多漏洞,看到了自己的实践经验还是比较缺乏,在这个过程中,我也曾经因为实践经验的缺乏失落过,也曾经仿真成功而热情高涨。生活就是这样,汗水预示着结果也见证着收获。劳动是人类生存生活永恒不变的话题。虽然这只是一次的极简单的课程制作,可是平心而论,也耗费了我们不少的心血。通过这次课程设计,我想说:为完成这次课程设计我确实很辛苦,但苦中仍有乐,我对单片机的产品开发有了系统的认识,从硬件的设计到软件的设计再到软硬件的联合工作。我懂得了以前没有接触到的知识,通过大量的查阅资料,让我对单片机有了清晰的认识。

软件设计方面不仅得考虑软件设计的合理性,更得从实用性。在软件设计时,查阅了大量软件工程方面的书籍,使得软件的时间复杂度有所降低,而且将软件的功能模块化,利用了模块化的编程思想,根据电路设计出了高效的软件。在软硬件联合工作方面实现了完美的链接,设计出了符合要求且高效率的程序。

以前种种艰辛这时就变成了最甜美的回忆!对我而言,知识上的收获重要,精神上的丰收更加可喜。让我知道了学无止境的道理。我们每一个人永远不能满足于现有的成就,人生就像在爬山,一座山峰的后面还有更高的山峰在等着你。挫折是一份财富,经历是一份拥有。这次课程设计必将成为我人生旅途上一个非常美好的回忆!

参考文献 

[1] 林立,张俊亮.单片机原理及应用——基于Proteus和KeilC[M].北京电子工业出版社,2014

[2] 陈忠平.基于Proteus的51系列单片机设计与仿真[M].北京电子工业出版社,2015

[3] 陈海宴.51单片机原理及应用[M].北京航空航天大学出版社,2010.

[4] 刘守义等.单片机技术基础[M].西安电子科技大学出版社,2007.
[5] 钟富昭等.8051单片机典型模块设计与应用[M].人民邮电出版社,2007.

[6] 隋清江等.基于Proteus的LCDl602接口设计与仿真[J].微计算机信息,2010.7-1:17l-172.

[7] 郭志卓,陈振军.基于单片机控制的电子计分器设计[J].电脑知识与技术,2014,10(12):2861-2863.

[8] 雷道仲,罗政球,廖永忠.基于单片机的球赛计时计分器设计[J].湖南第一师范学报,2009,9(04):164-166.

[9] 王文军.基于C51单片机的多功能计时计分器设计[J].科学与财富,2016,(9):674-674,675. DOI:10.3969/j.issn.1671-2226.2016.09.631.

[10] 牛军,王萍.无线电子打分计分系统的设计与实现[J].南阳理工学院学报,2015,7(04):1-4. 

[11] 王文军.基于C51单片机的多功能计时计分器设计[J].科学与财富,2016,(9):674-674,675. DOI:10.3969/j.issn.1671-2226.2016.09.631.

[12] 耿天寿.单片机控制的计时计分显示系统[C].//第三届全国电子技术应用大会.北京:山西大学,1993:193~196页.

[13] 伍学珍,岑斌.无线数传的计分计时系统[C].//中国通信集成电路技术与应用研讨会论文集.广西水利电力职业技术学院,2005:79-84.

[14] 赵学军,熊发明.球类比赛计时记分操作台的设计[C].//中国自动化学会中南六省(区)第20届学术年会.北京:2003:148-150.

[15] 陈雷,刘茂元.基于单片机计数计时仪的设计与制作[C].//2016年全国高等学校物理基础课程教育学术研讨会论文集.西藏大学,2016:73-77.

附 录 

#include <reg52.h>
#define LCD1602_DB  P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E  = P1^5;
unsigned char T0RH = 0;
unsigned char T0RL = 0;
sbit KEY_IN_1  = P2^0;
sbit KEY_IN_2  = P2^1;
sbit KEY_IN_3  = P2^2;
sbit KEY_IN_4  = P2^3;
sbit KEY_IN_5  = P2^4;
sbit KEY_IN_6  = P2^5;
sbit KEY_IN_7  = P2^6;
sbit KEY_IN_8  = P2^7;
bit flag1s = 0;	  //定时1s标志
char a = 0;		  //A的分数
char b = 0;		  //B的分数bit k=1;			//开显示开关
unsigned char minute = 0; //定时器分钟
unsigned char sec = 0;	  //定时器秒
unsigned char len = 0;	  //字符串转换长度
unsigned char str[3];	  //字符转换指针
void InitLcd1602();
void ConfigTimer0(unsigned int ms);
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
unsigned char LongToString(unsigned char *str, signed long dat);
void KeyDriver();
void LcdInit();void main()
{	EA = 1;           //开总中断ConfigTimer0(1);  //配置T0定时1msInitLcd1602();    //初始化液晶while (1){KeyDriver();	//调用按键功能if(k==1)LcdInit();	 //显示字幕}
}void delay()
{unsigned int i,j;for(i=0;i<9000;i++)for(j=0;j<4;j++);
}
/* 等待液晶准备好 */
void LcdWaitReady()
{unsigned char sta;LCD1602_DB = 0xFF;LCD1602_RS = 0;LCD1602_RW = 1;do {LCD1602_E = 1;sta = LCD1602_DB; //读取状态字LCD1602_E = 0;} while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止
}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 */
void LcdWriteCmd(unsigned char cmd)
{LcdWaitReady();LCD1602_RS = 0;LCD1602_RW = 0;LCD1602_DB = cmd;LCD1602_E  = 1;LCD1602_E  = 0;
}
/* 按键驱动函数,检测按键动作,调度相应动作函数,需在主循环中调用 */
void KeyDriver()
{static bit star = 0;		  //开始比赛unsigned char but = 0;		 //胜利标志static unsigned char cnt = 0; //比赛次数static unsigned char cnta = 0; //A胜利次数static unsigned char cntb = 0; //B胜利次数 if(KEY_IN_3 == 0) {   delay();  star = 1; TR0 = 1;k=1;} if(star == 1){	LcdWriteCmd(0x0C);  //显示器开,光标关闭   		if(KEY_IN_1 ==0)  { a++; delay();}if(KEY_IN_2 ==0)  { b++; delay();}if(KEY_IN_4 ==0)  { TR0 = 0; star=0; delay(); }if(KEY_IN_5 ==0)  { a--; if(a<0)a=0; delay();}if(KEY_IN_6 ==0)  { b--; if(b<0)b=0; delay(); }	     }if(KEY_IN_7 ==0)  { a=0; b=0; sec=0; minute=0; TR0=0;star=0;cnta=0; cntb=0; cnt=0; LcdShowStr(0, 0, "                "); delay();}if(KEY_IN_8 ==0){ a=0;  b=0;   sec=0;   minute=0; LcdShowStr(0, 0, "                ");k=0;cnta=0;cntb=0;cnt=0;LcdWriteCmd(0x01); delay();}	if(a>=21 && (a-b)>=2 ) {cnt++; cnta++; but = 1; a = 0; b = 0; }	if(b>=21 && (b-a)>=2 ) {cnt++; cntb++; but = 2; a = 0; b = 0; }if(cnt==2&&(cnta==2||cntb==2)) {TR0 = 0; star = 0;}switch(cnt){case 1: if(but==1) LcdShowStr(0, 0, "1Awin"); if(but==2) LcdShowStr(0, 0, "1Bwin");break;case 2: if(but==1) LcdShowStr(5, 0, "2Awin"); if(but==2) LcdShowStr(5, 0, "2Bwin");break;case 3: if(but==1) LcdShowStr(10, 0, "3Awin"); if(but==2) LcdShowStr(10, 0, "3Bwin"); TR0=0;star=0;break;default: break;}
}
//显示字母及计时器
void LcdInit()
{if(flag1s == 1){sec++;flag1s = 0;}if(sec>=60){ minute++;sec = 0;if(minute>59)minute = 59;}LcdShowStr(0, 1, "T");len = LongToString(str, minute);LcdShowStr(1, 1, str);LcdShowStr(3, 1, ":");len = LongToString(str, sec);LcdShowStr(4, 1, str);LcdShowStr(7, 1, "A:B");len = LongToString(str, a);LcdShowStr(11, 1, str);LcdShowStr(13, 1, ":");len = LongToString(str, b);LcdShowStr(14, 1, str);	   	 
}//将数字转换为字符
unsigned char LongToString(unsigned char *str, signed long dat)
{signed char i = 0;signed char len = 0;unsigned char buf[3];	for(i=0;i<2;i++){buf[i] = dat%10;dat = dat/10;}len = i;for(i=1;i>=0;i--){*str++ = buf[i] + '0';}*str = '\0';return len;		
}/* 向LCD1602液晶写入一字节数据,dat-待写入数据值 */
void LcdWriteDat(unsigned char dat)
{LcdWaitReady();LCD1602_RS = 1;LCD1602_RW = 0;LCD1602_DB = dat;LCD1602_E  = 1;LCD1602_E  = 0;
}
/* 设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{unsigned char addr;if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址addr = 0x00 + x;  //第一行字符地址从0x00起始elseaddr = 0x40 + x;  //第二行字符地址从0x40起始LcdWriteCmd(addr | 0x80);  //设置RAM地址
}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{LcdSetCursor(x, y);   //设置起始地址while (*str != '\0')  //连续写入字符串数据,直到检测到结束符{LcdWriteDat(*str++);}
}
/* 区域清除,清除从(x,y)坐标起始的len个字符位 */
void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len)
{LcdSetCursor(x, y);   //设置起始地址while (len--)         //连续写入空格{LcdWriteDat(' ');}
}/* 初始化1602液晶 */
void InitLcd1602()
{LcdWriteCmd(0x38);  //16*2显示,5*7点阵,8位数据接口//  LcdWriteCmd(0x0C);  //显示器开,光标关闭LcdWriteCmd(0x06);  //文字不动,地址自动+1LcdWriteCmd(0x01);  //清屏
}/* 配置并启动T0,ms-T0定时时间 */
void ConfigTimer0(unsigned int ms)
{unsigned long tmp;  //临时变量tmp = 11059200 / 12;      //定时器计数频率tmp = (tmp * ms) / 1000;  //计算所需的计数值tmp = 65536 - tmp;        //计算定时器重载值tmp = tmp + 12;           //补偿中断响应延时造成的误差T0RH = (unsigned char)(tmp>>8);  //定时器重载值拆分为高低字节T0RL = (unsigned char)tmp;TMOD &= 0xF0;   //清零T0的控制位TMOD |= 0x01;   //配置T0为模式1TH0 = T0RH;     //加载T0重载值TL0 = T0RL;ET0 = 1;        //使能T0中断
}/* T0中断服务函数,配置定时器时间 */
void InterruptTimer0() interrupt 1
{static  unsigned count = 0;TH0 = T0RH;  //重新加载重载值TL0 = T0RL;count++;if(count>=1000){count = 0;flag1s = 1;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/3004.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动化测试用例设计

知人者智&#xff0c;自知者明。大家好&#xff0c;给大家分享一下关于自动化测试用例的设计心得&#xff0c;首先完整的熟悉业务是第一步要做的&#xff0c;不熟悉业务的前提下不会设计出高效且合理的用例&#xff0c;其次是我们要有明确的测试目标&#xff0c;确保我们写的每…

Redis(单/多)线程

一、 Redis 单线程 与 多线程 怎么说&#xff1f; &#xff08;1&#xff09;重要的版本迭代 redis4 之前仅支持 单线程&#xff0c; redis 4之后慢慢 支持多线程&#xff0c; 直到redis6/7后才稳定 &#xff08;2&#xff09;redis 的 工作线程 是 单线程的 &#xff08…

Python构建学生信息管理系统:构建RESTful API - 学生信息管理系统的后端逻辑

在之前的博客里&#xff0c;我们已经完成了项目初始化&#xff0c;在本篇博客中&#xff0c;我们将深入探讨如何使用Flask框架实现学生信息管理系统的后端逻辑&#xff0c;特别是通过RESTful API来实现学生信息的增删改查&#xff08;CRUD&#xff09;操作。 Flask RESTful AP…

C系统编程:从零手搓一个shell

背景 这么久没更新就是在干这件事&#xff01;&#xff01;因为系统编程已经学的差不多了&#xff0c;所以想找几个项目练练手&#xff0c;之前就一直想写一个自己的shell&#xff01;&#xff01;现在终于有机会实现了。 首先说明一下我的操作系统&#xff1a;Arch linux 服务…

函数的查询

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 在实际使用中经常会需要查询数据库中已有的函数或者某一个函数的内容&#xff0c;下面就介绍一下如何查询函数。 和存储过程类似&#xff0c;这也需要使用到数据字典user_s…

Spring - 4 ( 11000 字 Spring 入门级教程 )

一&#xff1a;Spring IoC&DI 在前⾯的章节中, 我们学习了 Spring Boot 和 Spring MVC 的开发, 可以完成⼀些基本功能的开发了, 但是什么是 Spring 呢? Spring, Spring Boot 和 SpringMVC 又有什么关系呢? 咱们还是带着问题去学习.我们先看什么是Spring 1.1 Spring 是什…

更新至2022年上市公司数字化转型数据合集(四份数据合集)

更新至2022年上市公司数字化转型数据合集&#xff08;四份数据合集&#xff09; 一、2000-2022年上市公司数字化转型数据&#xff08;年报词频、文本统计&#xff09; 二、2007-2022年上市公司数字化转型数据&#xff08;年报和管理层讨论&#xff09;&#xff08;含原始数据…

微前端是如何实现作用域隔离的?

微前端是如何实现作用域隔离的&#xff1f; 一、前言 沙箱&#xff08;Sandbox&#xff09;是一种安全机制&#xff0c;目的是让程序运行在一个相对独立的隔离环境&#xff0c;使其不对外界的程序造成影响&#xff0c;保障系统的安全。作为开发人员&#xff0c;我们经常会同沙…

UE5 GAS开发P35,36,37,38,39 将药水修改为AbilitySystem效果

这几节课都是将药水修改成更方便使用的AbilitySystem效果的Actor,分别为增加血量,增加蓝量,暂时获得最大生命值上限 AuraEffectActor.h // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #…

介绍一个开源IOT组态项目

项目介绍 金合可视化平台是一款强大而操作简便的低代码平台&#xff0c;专为满足物联网领域的可视化开发需求而设计。通过该平台&#xff0c;用户可以利用拖拽配置的方式&#xff0c;轻松创建个性化的可视化大屏&#xff0c;无需熟练的编程技能&#xff0c;大幅提高了开发效率。…

图搜索的经典启发式算法A星(A*、A Star)算法详解

文章目录 1. 引言2. 广度优先搜索3. Dijkstra 算法4. 启发式优先搜索&#xff08;Heuristic&#xff09;4.1 贪心最佳优先搜索4.2 A*搜索 1. 引言 在许多场景中&#xff0c;我们常会遇到一类问题&#xff0c;即“找到一个位置到另一个位置的距离最短&#xff08;用时最少&…

使用 Rust 后,我​​使用 Python 的方式发生了变化

使用 Rust 后&#xff0c;我​​使用 Python 的方式发生了变化 Using type hints where possible, and sticking to the classic “make illegal state unrepresentable” principle. 尽可能使用类型提示&#xff0c;并坚持经典的“使非法状态不可表示”原则。 近年来&#xff…

【Pytorch】(十三)PyTorch模型部署: TorchScript

文章目录 &#xff08;十三&#xff09;PyTorch模型部署Pytorch动态图的优缺点TorchScriptPytorch模型转换为TorchScripttorch.jit.tracetorch.jit.scripttrace和script的区别总结script 和 trace 混合使用保存和加载模型 &#xff08;十三&#xff09;PyTorch模型部署 Pytorc…

科学高效备考AMC8和AMC10竞赛,吃透2000-2024年1850道真题和解析

如何科学、有效地备考AMC8、AMC10美国数学竞赛&#xff1f;多做真题&#xff0c;吃透真题是科学有效的方法之一&#xff0c;通过做真题&#xff0c;可以帮助孩子找到真实竞赛的感觉&#xff0c;而且更加贴近比赛的内容&#xff0c;可以通过真题查漏补缺&#xff0c;更有针对性的…

成功解决ImportError: cannot import name ‘builder‘ from ‘google.protobuf.internal

成功解决ImportError: cannot import name builder from google.protobuf.internal 目录 解决问题 解决思路 解决方法 解决问题 ImportError: cannot import name builder from google.protobuf.internal 解决思路 导入错误:无法从“google.protobuf.internal”导入名称“…

在React函数组件中使用错误边界和errorElement进行错误处理

在React 18中,函数组件可以使用两种方式来处理错误: 使用 ErrorBoundary ErrorBoundary 是一种基于类的组件,可以捕获其子组件树中的任何 JavaScript 错误,并记录这些错误、渲染备用 UI 而不是冻结的组件树。 在函数组件中使用 ErrorBoundary,需要先创建一个基于类的 ErrorB…

网络通信安全

一、网络通信安全基础 TCP/IP协议简介 TCP/IP体系结构、以太网、Internet地址、端口 TCP/IP协议简介如下&#xff1a;&#xff08;from文心一言&#xff09; TCP/IP&#xff08;Transmission Control Protocol/Internet Protocol&#xff0c;传输控制协议/网际协议&#xff0…

用友NC Cloud importhttpscer接口任意文件上传漏洞

声明 本文仅用于技术交流&#xff0c;请勿用于非法用途 由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;文章作者不为此承担任何责任。 一、漏洞描述 用友NC Cloud的importhttpscer接口如果存在任意文件上传…

开源文本嵌入模型M3E

进入正文前&#xff0c;先扯点题外话 这两天遇到一个棘手的问题&#xff0c;在用 docker pull 拉取镜像时&#xff0c;会报错&#xff1a; x509: certificate has expired or is not yet valid 具体是下面&#x1f447;这样的 rootDS918:/volume2/docker/xiaoya# docker pul…

恒峰智慧科技—森林守护者:森林消防泵如何助力灭火?

在茂密的森林中&#xff0c;一场突如其来的火灾可能带来无法估量的破坏。幸运的是&#xff0c;森林消防泵的出现&#xff0c;帮助我们对抗这些威胁。本文将深入探讨森林消防泵如何在灭火工作中发挥重要作用。 一、森林消防泵的功能和重要性&#xff1a; 首先&#xff0c;我们需…