蓝桥杯省三保底代码——数显+按键功能实现

目录

前言

一、为什么能保底省三

二、数显模块的实现

1.数码管显示​编辑

1)断码表

2)位选

3)段选

4)扫描

2.菜单

三、按键功能的实现

1.按键扫描

2.菜单切换

四、完整代码演示

五、结语


前言

上一期介绍全家桶时,跟大家提到:比赛时可以做出来按键切换菜单的部分,这样子起码省三就有了。这篇文章就去教大家如何实现省三保底。当然,这些代码只靠背可能不太够,比赛的时候需要根据题目小改一下才行。

一、为什么能保底省三

数显+按键切换菜单完成,基本就可以拿到省三,这个比赛是看你完成度给你“打分”的,数显和按键功能其实已经占了题目不少的一部分了,这里的数显是指:读取不到有效数据,仅能显示一个不会更新的数据。

如果你能灵活使用底层驱动的那几个外设,读取到有效数据,顺便完成一点LED灯,那冲击省二都有可能,如果你又能灵活地对数据进行处理,完成题目对数据处理方面的要求,基本完成赛题上的所有功能,那基本省一就稳了。

当然,这也只是我个人说的哈,但也确实听不少人说“完成数显+按键切换菜单可以拿省三”“基本完成题目要求的功能就能稳省一”,我也绝不是空穴来风。

我去年参加蓝桥杯时,NE555读取部分没有实现,其他功能基本实现,也顺利进入了国赛。

二、数显模块的实现

这里以第十三届比赛题目为例,介绍一下数显和按键部分的实现。

1.数码管显示

这部分都是十分基础的代码,不过毕竟这篇文章就是“保底省三”的代码,这部分还是有必要详细介绍一下的。

1)断码表

首先,比赛时会给你一个断码表,所以断码自己会使用计算机算即可,没必要记,真需要显示某个符号了,就使用计算机算一算,下面是23年给的断码表

code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e //F
}

前边那个“code”,抄的时候删不删都可以,没影响。现在不管是个人的电脑,或者赛点的电脑,上边的计算机都有程序员模式,可以切换单位键盘,帮助完成断码

2)位选

在让数码管显示数据之前,我们先需要位选,何为位选呢?其实就是选择你要显示那个数码挂的数据。下图中圈住的,就是用于控制位选的锁存器。我们只需要把需要传输的数据放到P0里,在使能锁存器,并失能锁存器(说人话就是开关一下锁存器,让他更新一下数据就好),就可以把P0的数据存到锁存器里了。P0需要放到数据就是,我们要控制哪一个数码管,高电平有效。一般情况下我们都是一次控制一个数码管,所以P0当中只有一个数据是1,其他都是0.

比如P0=0000 0001就是控制第0个数码管(或者说最左边那个),P0=0000 0010就是控制第一个数码管。P0=0000 1111就是同时控制数码管,给P0赋值之后,开关一次锁存器,就可以选中我们要控制的数码管了,接下来的段选,只影响当前被选中的锁存器。

刚才提到开关锁存器,也就是使能和失能锁存器,锁存器的控制端连在了Y6C,高电平有效,我们只需要给Y6C高电平,在给低电平即可完成开关锁存器。

Y6C连接在一个三线八线译码器上如下图(右边的东西这里不过多介绍)

P27,P26,P25是3线输出,Y0到Y7是7线输出。下边P27,P26,P25简称输入:

如果输入000,则选中Y0;如果输入110,也就是二进制的6,则选择Y6,经过有右边的与非门之后,就可以选中Y6C,打开刚才位选的锁存器。

因此,我们只需要给P2的高三位为110就可以打开位选,给高三位000就可以关闭位选。我们可以定义一个宏定义,来实现位选

#define NIXIE_CHECK()    P2|=0xC0;P2&=0xDF;P2&=0x1F;

3)段选

段选与上述位选类似,就是把数码管需要显示的数据放在P0然后再开关一次锁存器即可。也就是下图中左上角的锁存器。P0放的数据,就是我们最开始提到的断码数据。

我们同样使用一个宏定义来完成段选

#define NIXIE_ON()        P2|=0xE0;P2&=0xFF;P2&=0x1F;

4)扫描

为了让数码管显示不同的数据,我们一般是一次性控制一个数码管,如果我们想让八个数码管同时显示不同的数据,就需要扫描。扫描通俗点说就是先控制第一个数码管显示数据,趁着第一个还没熄灭就再去控制第二个数码管显示数据,在控制第三个......完成一轮之后再控制第一个,已知循环下去。

由于它对于时间有要求,所以我们需要把它放在定时器完成扫描。使用location记录当前扫描到第几个数码管了,使用Nixie_num数组记录八个数码管各自需要显示的数据,定时器时间为1ms。

中断服务函如下:

void Timer0_Isr(void) interrupt 1
{
    P0=0x01<<location;NIXIE_CHECK();
    P0=Seg_Table[Nixie_num[location]];NIXIE_ON();
    
    if(++location==8)
        location=0;
}

我们只需在main或者菜单显示函数中给Nixie_num数组对应位置赋值,即可让他显示不同的数据

2.菜单

我们定义一个标志位mod,当mod=0时显示第一个菜单,mod=1时显示第二个菜单以此类推。

这里我们手动添加一个断码表,使之可以显示U和“-”,以及对应的带小数点的数字。

我们注意到题目要求数显部分(第二章开头有介绍),第一位数码管显示的都是U,第二位是当前是第几个菜单,所以我们把这连个单独写出来。注意不需要显示的位需要熄灭,避免切换菜单时不这个菜单不显示的位被异常点亮。

这样我们就可以通过改变mod的值,来显示不同的菜单了

void show_menu(void)
{
    Nixie_num[0]=21;//显示U
    Nixie_num[1]=mod+1;//显示菜单数
    if(mod==0)
    {
        Nixie_num[2]=20;//熄灭
        Nixie_num[3]=20;//熄灭
        Nixie_num[4]=20;//熄灭
        Nixie_num[5]=2;//显示2
        Nixie_num[6]=3+10;//显示3.
        Nixie_num[7]=5;//显示5
    }
    else if(mod==1)
    {
        Nixie_num[2]=20;
        Nixie_num[3]=2;
        Nixie_num[4]=3;
        Nixie_num[5]=22;
        Nixie_num[6]=2;
        Nixie_num[7]=3;
    }
    else if(mod==2)
    {
        Nixie_num[2]=20;
        Nixie_num[3]=20;
        Nixie_num[4]=20;
        Nixie_num[5]=20;
        Nixie_num[6]=2;
        Nixie_num[7]=3;
    }
}

三、按键功能的实现

按键功能要求,以第十三届为例。这里仅完成“切换”按键

1.按键扫描

相信大家单片机入手的第二堂课就是按键(第一堂课应该是点亮LED),这里按键扫描就不过多介绍了,这里放一个我自己用的矩阵按键扫描代码

void get_key(void)
{
    unsigned char key_P3=P3;
    unsigned char key_P4=P4;
    
    P3=0xFF;
    
    P44=0;
    if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=7;}
    else if(P31==0){Delay5ms();while(P31==0);Delay5ms();key_value=6;}
    else if(P32==0){Delay5ms();while(P32==0);Delay5ms();key_value=5;}
    else if(P33==0){Delay5ms();while(P33==0);Delay5ms();key_value=4;}
        
    P42=0;
    if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=11;}
    else if(P31==0){Delay5ms();while(P31==0);Delay5ms();key_value=10;}
    else if(P32==0){Delay5ms();while(P32==0);Delay5ms();key_value=9;}
    else if(P33==0){Delay5ms();while(P33==0);Delay5ms();key_value=8;}
        
    P35=0;
    if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=15;}
    else if(P31==0){Delay5ms();while(P31==0);Delay5ms();key_value=14;}
    else if(P32==0){Delay5ms();while(P32==0);Delay5ms();key_value=13;}
    else if(P33==0){Delay5ms();while(P33==0);Delay5ms();key_value=12;}
        
    P34=0;
    if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=19;}
    else if(P31==0){Delay5ms();while(P31==0);Delay5ms();key_value=18;}
    else if(P32==0){Delay5ms();while(P32==0);Delay5ms();key_value=17;}
    else if(P33==0){Delay5ms();while(P33==0);Delay5ms();key_value=16;}
    
    key_value=0;
    P3=key_P3;
    P4=key_P4;
}

函数末尾把key_value又置为了0,是因为后续所有按键处理都要在按键扫描函数里完成,如果你是刚写完按键扫描,想测试一下的话,可以吧key_value=0给删掉,在main里使用数码管显示key_value的值。

2.菜单切换

简单点说,如果按下了S12,就把菜单从1切换到2或者从2切换到3或者从3切换到1。我们只需要把下面的代码放到上述key_value=0之前即可

    if(key_value==12)
    {
        if(mod==0)
            mod=1;
        else if(mod==1)
            mod=2;
        else if(mod==2)
            mod=0;
    }

可能会有人说,我这样写真的好LOW,不过我感觉,我只是为了应对这个比赛才写这样的代码的,这样写纯属是为了少犯错误,容易修改,仅此而已。你当然也可以把代码写的很华丽,包括阿刚才show_menu函数里的代码,只要能达到预期效果就行。

这里仅仅实现了按键切换菜单,有的按键还有切换参数的功能,需要把数码管显示的数据改为对应的参数,在通过按键对参数进行加减,这里不再介绍。

四、完整代码演示

main.c

#include <stc15.h>
#include <intrins.h>
#include "onewire.h"
#include "ds1302.h"

code unsigned char Seg_Table[] =
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
//0.到9.
0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,
0xFF,//20 熄灭
0xC1,//21 U
0xBF//22 -
};


#define NIXIE_CHECK()	P2|=0xC0;P2&=0xDF;P2&=0x1F;
#define NIXIE_ON()		P2|=0xE0;P2&=0xFF;P2&=0x1F;

unsigned char Nixie_num[]={20,20,20,20,20,20,20,20};
void Timer0_Init(void);		//1毫秒@12.000MHz
void Delay100ms(void);	//@12.000MHz
void get_key(void);
void show_menu(void);

unsigned char location=0;
unsigned char key_value=0;
unsigned char mod=0;

void main()
{
	Timer0_Init();
	EA=1;
	while(1)
	{
		get_key();
		Delay100ms();
	}
}
void Timer0_Isr(void) interrupt 1
{
	P0=0x01<<location;NIXIE_CHECK();
	P0=Seg_Table[Nixie_num[location]];NIXIE_ON();
	
	if(++location==8)
		location=0;
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;			//定时器时钟1T模式
	TMOD &= 0xF0;			//设置定时器模式
	TL0 = 0x20;				//设置定时初始值
	TH0 = 0xD1;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0 = 1;				//使能定时器0中断
}

void Delay100ms(void)	//@12.000MHz
{
	unsigned char data i, j, k;

	_nop_();
	_nop_();
	i = 5;
	j = 144;
	k = 71;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void Delay5ms(void)	//@12.000MHz
{
	unsigned char data i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}
void get_key(void)
{
	unsigned char key_P3=P3;
	unsigned char key_P4=P4;
	
	P3=0xFF;
	
	P44=0;
	if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=7;}
	else if(P31==0){Delay5ms();while(P31==0);Delay5ms();key_value=6;}
	else if(P32==0){Delay5ms();while(P32==0);Delay5ms();key_value=5;}
	else if(P33==0){Delay5ms();while(P33==0);Delay5ms();key_value=4;}
		
	P42=0;
	if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=11;}
	else if(P31==0){Delay5ms();while(P31==0);Delay5ms();key_value=10;}
	else if(P32==0){Delay5ms();while(P32==0);Delay5ms();key_value=9;}
	else if(P33==0){Delay5ms();while(P33==0);Delay5ms();key_value=8;}
		
	P35=0;
	if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=15;}
	else if(P31==0){Delay5ms();while(P31==0);Delay5ms();key_value=14;}
	else if(P32==0){Delay5ms();while(P32==0);Delay5ms();key_value=13;}
	else if(P33==0){Delay5ms();while(P33==0);Delay5ms();key_value=12;}
		
	P34=0;
	if(P30==0){Delay5ms();while(P30==0);Delay5ms();key_value=19;}
	else if(P31==0){Delay5ms();while(P31==0);Delay5ms();key_value=18;}
	else if(P32==0){Delay5ms();while(P32==0);Delay5ms();key_value=17;}
	else if(P33==0){Delay5ms();while(P33==0);Delay5ms();key_value=16;}
	
	//S12
	if(key_value==12)
	{
		if(mod==0)
			mod=1;
		else if(mod==1)
			mod=2;
		else if(mod==2)
			mod=0;
	}
	key_value=0;
	P3=key_P3;
	P4=key_P4;
}
void show_menu(void)
{
	Nixie_num[0]=21;//显示U
	Nixie_num[1]=mod+1;//显示菜单数
	if(mod==0)
	{
		Nixie_num[2]=20;//熄灭
		Nixie_num[3]=20;//熄灭
		Nixie_num[4]=20;//熄灭
		Nixie_num[5]=2;//显示2
		Nixie_num[6]=3+10;//显示3.
		Nixie_num[7]=5;//显示5
	}
	else if(mod==1)
	{
		Nixie_num[2]=20;
		Nixie_num[3]=2;
		Nixie_num[4]=3;
		Nixie_num[5]=22;
		Nixie_num[6]=2;
		Nixie_num[7]=3;
	}
	else if(mod==2)
	{
		Nixie_num[2]=20;
		Nixie_num[3]=20;
		Nixie_num[4]=20;
		Nixie_num[5]=20;
		Nixie_num[6]=2;
		Nixie_num[7]=3;
	}
}

五、结语

不同人写代码的风格不一样,我只是分享了我写的一套省三代码。如果你自己之前有跟其他人学过,现在不妨把代码整理整理,至少做到连续两次,可以写出一模一样的代码,这样可以减少比赛时犯错误。

最后,希望没有准备充分的同学不要放弃,现在冲一冲那个省二省三也不是问题,提前预祝冲击省一的同学,国赛再见!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【容器源码篇】Set容器(HashSet,LinkedHashSet,TreeSet的特点)

文章目录 ⭐容器继承关系&#x1f339;Set容器&#x1f5d2;️HashSet源码解析构造方法public HashSet()public HashSet(Collection<? extends E> c)public HashSet(int initialCapacity, float loadFactor)HashSet(int initialCapacity, float loadFactor, boolean dum…

OpenHarmony实战开发-Web组件的使用

介绍 本篇Codelab使用ArkTS语言实现一个简单的免登录过程&#xff0c;向大家介绍基本的cookie管理操作。主要包含以下功能&#xff1a; 获取指定url对应的cookie的值。设置cookie。清除所有cookie。免登录访问账户中心。 原理说明 本应用旨在说明Web组件中cookie的管理操作。…

蓝桥杯_day6

文章目录 不同路径不同路径II拿金币珠宝的最高价值 不同路径 【题目描述】 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为…

主成成分分析法

问题引入&#xff1a; 公司评价 假设你是一个公司的财务经理&#xff0c;掌握了公司所有数据&#xff0c;如:固定资产、流动资金、借贷的数额和期限、各种税费、工资支出、原料消耗、产值、利润、折扣、职工人数、分工和教育程度等等&#xff0c;你要如何选择关键因素进行汇报…

宝宝灯塔:成都辅助生殖市场研究,海外试管成热门

据宝宝灯塔网介绍&#xff1a;在成都的辅助生殖市场中&#xff0c;生殖医院一直是主体&#xff0c;它们提供专业的医疗服务和治疗&#xff0c;帮助不孕不育人群实现生育梦想。然而&#xff0c;随着科技的进步和市场的变化&#xff0c;互联网企业也开始涉足这一领域&#xff0c;…

盏燕生物科技将出席2024第七届燕窝天然滋补品博览会

参展企业介绍 深圳市盏燕生物科技有限公司&#xff0c;办公室地址位于中国第一个经济特区&#xff0c;鹏城深圳&#xff0c;深圳市龙岗区平湖街道禾花社区富安大道18号亚钢工贸大楼1栋1017A&#xff0c;我公司主要提供一般经营项目是&#xff1a;初级农产品、海产品、化妆品、…

低代码开发能用在哪些行业?

低代码开发平台&#xff08;Low code development platform&#xff09;是无需编码&#xff08;0代码&#xff09;或通过少量代码就可以快速生成应用程序的开发平台。通过可视化进行应用程序开发的方法&#xff0c;使具有不同经验水平的开发人员可以通过图形化的用户界面&#…

computed计算属性、watch侦听器、生命周期

计算属性 点击查看 Vue文档 基础语法 多次使用计算属性&#xff0c;计算属性方法也只执行一次&#xff0c; 调用计算属性的方法不能加() 直接修改计算数学的值 计算属性不能通过双向绑定修改&#xff08;默认不能改&#xff09; 想要修改计算属性&#xff0c;就必须使用计…

夜晚水闸3D可视化:科技魔法点亮水利新纪元

在宁静的夜晚&#xff0c;当城市的霓虹灯逐渐暗淡&#xff0c;你是否曾想过&#xff0c;那些默默守护着城市安全的水闸&#xff0c;在科技的魔力下&#xff0c;正焕发出别样的光彩&#xff1f;今天&#xff0c;就让我们一起走进夜晚水闸3D模型&#xff0c;感受科技为水利带来的…

包子凑数(蓝桥杯,闫氏DP分析法)

题目描述&#xff1a; 小明几乎每天早晨都会在一家包子铺吃早餐。 他发现这家包子铺有 N 种蒸笼&#xff0c;其中第 i 种蒸笼恰好能放 Ai 个包子。 每种蒸笼都有非常多笼&#xff0c;可以认为是无限笼。 每当有顾客想买 X 个包子&#xff0c;卖包子的大叔就会迅速选出若干笼…

计算机网络——29ISP之间的路由选择:BGP

ISP之间的路由选择&#xff1a;BGP 层次路由 一个平面的路由 一个网络中的所有路由器的地位一样通过LS&#xff0c;DV&#xff0c;或者其他路由算法&#xff0c;所有路由器都要知道其他所有路由器&#xff08;子网&#xff09;如何走所有路由器在一个平面 平面路由的问题 …

Liunx安装Nacos

Liunx安装Nacos 1、镜像下载 curl -O https://github.com/alibaba/nacos/releases/download/2.3.1/nacos-server-2.3.1.tar.gz2、解压到指定目录 tar -zxvf nacos-server-2.3.1.tar.gz -C /usr/local3、进入bin文件启动startup.sh文件 cd /usr/local/nacos/binsh startup.s…

精灵传信系统 匿名性系统 支持网站+小程序双端源码

精灵传信支持在线提交发送短信&#xff0c;查看回复短信&#xff0c;在线购买额度&#xff0c;自定义对接易支付&#xff0c;设置违禁词&#xff0c;支持网站小程序双端。 项目 地 址 &#xff1a; runruncode.com/php/19720.html 环境要求: PHP > 73 MySQL>5.6 Ngi…

Redis中的客户端(三)

客户端 身份验证 客户端状态的authenticated属性用于记录客户端是否通过了身份验证: typedef struct redisClient {// ...int authenticated;// ... } redisClient;如果authnticated的值为0&#xff0c;那么表示客户端未通过身份验证&#xff1b;如果authenticated的值为1&a…

分布式处理

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;这是我作为学习笔记原理篇的最后一章&#xff0c;一台计算机在数据中心里是不够的。因为如果只有一台计算机&#xff0c;我们会遇到三个核心问题。第一个核心问题&#xff0c;叫作垂直扩展和水平扩展的选择问题&#xff0c;…

两年测开经历分享的测试开发学习路线

路线大纲 该学习路线一共是7个阶段&#xff0c;循序渐进&#xff0c;学习路线相对比较平缓图片 阶段0 : 前言 路线特点 适用于想转行做功能测试与测试开发的同学 给出目标、学习建议、关键知识点、最优资源以及各类资源推荐&#xff08;视频、书籍、文档、项目、工具等&am…

在宝塔面板中,为自己的云服务器安装SSL证书,为所搭建的网站启用https(主要部分攻略)

前提条件 My HTTP website is running Nginx on Debian 10&#xff08;或者11&#xff09; 时间&#xff1a;2024-3-28 16:25:52 你的网站部署在Debain 10&#xff08;或者11&#xff09;的 Nginx上 安装单域名证书&#xff08;默认&#xff09;&#xff08;非泛域名&#xf…

【TB作品】MSP430G2553,超声波倒车雷达PCB,单片机,超声波SR04,键盘,oled,

题目 硬件&#xff1a;MSP430G2553、 SR04超声波传感器 、3*4键盘、 无源蜂鸣器、oled显示屏 软件 1 、实时显示测量得到的距离 2、按键设置一个报警门限数值&#xff0c;直接输入数值后确认 3、低于报警门限数值就开始报警&#xff0c;而且距离越近蜂鸣器的鸣叫频率越高 程序…

20240321-1-AB测试面试题

AB测试面试题 1. 介绍一下ABTest的步骤 ABtest就是为了测试和验证模型/项目的效果&#xff0c;在app/pc端设计出多个版本&#xff0c;在同一时间维度下&#xff0c;分别用组成相同/相似的群组去随机访问这些版本&#xff0c;记录下群组的用户体验数据和业务数据&#xff0c;最…

Xcode 15 Sandbox: rsync(xxxx) deny(1) file-write-create

设置里面搜索user 把User Script Sanboxing 改为NO 新版本的Xcode 15 编译报该错误 右侧工具栏 项目的workspace 和 pod的 space 都选择为15.0 即可