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

news2024/12/26 10:48:49

目录

前言

一、为什么能保底省三

二、数显模块的实现

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;
	}
}

五、结语

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

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

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

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

相关文章

C语言分支循环语句详解

分支和循环语句是什么 在我们写程序的时候&#xff0c;总会遇到想一直循环执行某种语句的时候&#xff0c;这时候我们就要使用一种语句叫循环语句&#xff0c;或者带一些判断条件的语句&#xff0c;在C语言中提供了像这些的循环语句和分支语句 if else 语句 这是一种判断语句…

Model-Free Q-Learning for the Tracking Problem of Linear Discrete-Time Systems

Model-Free Q-Learning for the Tracking Problem of Linear Discrete-Time Systems&#xff0c;2024&#xff0c; Chun Li , Jinliang Ding , Senior Member, IEEE, Frank L. Lewis , Life Fellow, IEEE, and Tianyou Chai , Life Fellow, IEEE 对完全未知动力学的线性离散时…

远程桌面连接弹出“出现身份验证错误,要求的函数不受支持”解决办法

windows远程桌面连接,出现如图所示“出现身份验证错误&#xff0c;要求的函数不受支持”错误&#xff0c;无法连接。 解决办法&#xff1a; 打开本地组策略编辑器&#xff0c;按winr组合键输入gpedit.msc命令打开。 选择“计算机配置”--“管理模板”--“系统”--“凭据分配”…

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

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

【正点原子FreeRTOS学习笔记】————(7)任务调度

这里写目录标题 一、开启任务调度器&#xff08;熟悉&#xff09;二、启动第一个任务&#xff08;熟悉&#xff09;2.1&#xff0c;prvStartFirstTask () /* 开启第一个任务 */2.2&#xff0c;vPortSVCHandler () /* SVC中断服务函数 */ 三、任务切换&#xff08;掌握&#xff…

Deconstructing Denoising Diffusion Models for Self-Supervised Learning解读(超详细)

论文题目&#xff1a;Deconstructing Denoising Diffusion Models for Self-Supervised Learning 原文链接&#xff1a;https://arxiv.org/html/2401.14404v1 本文是对何凯明老师的新作进行的详细解读&#xff0c;其中穿插了一些思考&#xff0c;将从以下四个方面对这篇工作进…

波奇学Linux:http协议

2 个简单预备知识 https://www.baidu.com/ -域名-字符串-域名解析--ip地址 http请求和响应 格式画出来&#xff0c;两个工具见一见 https协议绑定端口号443 http协议绑定端口号 80 url 统一资源定位符 所有网络的资源都可以用唯一的一个字符串标识&#xff0c;并且可以获取…

八种顺序读写函数的介绍(fput/getc;fput/gets;fscanf,fprintf;fwrite,fread)

一&#xff1a;读写的含义的解释&#xff1a; 读&#xff08;读出&#xff09;&#xff1a;即从文件里面读出数据----------->和scanf从键盘里面读出数据类似 写&#xff08;写入&#xff09;&#xff1a;即把数据写入文件里面----------->和printf把数据写入到屏幕上类…

13.Java能干什么?以及Java的三大平台

文章目录 一、JavaSE二、JavaME三、JavaEE JAVA从95年以来&#xff0c;已经问世了20多年了&#xff0c;可能比部分同学的年龄还大。 Java到底能干嘛呢&#xff0c;此时就需要讲到Java的三大平台&#xff0c;其实也就是它的三个分类&#xff1a;JavaSE、JavaME、JavaEE。 一、Ja…

PDFgear:一款免费的PDF编辑、格式转化软件

日常办公中&#xff0c;很多朋友都会接触到PDF文件。把文件转化成PDF是保留文件格式、防范别人修改常用的方法。但是很多人会为PDF文件的生成、压缩、编辑和格式转化而头疼&#xff0c;还有人为了能把PDF转化成Word还购买了不少付费的软件。 为了解决大家这个痛点&#xff0c;…

ES6 学习(三)-- es特性

文章目录 1. Symbol1.1 使用Symbol 作为对象属性名1.2 使用Symbol 作为常量 2. Iterator 迭代器2.1 for...of循环2.2 原生默认具备Interator 接口的对象2.3 给对象添加Iterator 迭代器2.4 ... 解构赋值 3. Set 结构3.1 初识 Set3.2 Set 实例属性和方法3.3 遍历3.4 相关面试题 4…

如何着手写一个自己的网站管理客户端

WebHole 项目地址 https://gitee.com/yiyefangzhou24/web-hole 是什么&#xff1f;能干什么&#xff1f; WebHole是一款网站管理软件&#xff0c;类似但不同于菜刀、冰蝎、蚁剑&#xff0c;能通过C/S的工作模式&#xff0c;方便的管理服务器的文件、数据库&#xff0c;并执…

Redis命令介绍

一、redis启动&#xff1a; 本地启动&#xff1a;redis-cli 远程启动&#xff1a;redis-cli -h host -p port -a password Redis 连接命令 1 AUTH password 验证密码是否正确 2 ECHO message 打印字符串 3 PING 查看服务是否运行 4 QUIT 关闭当前连接 5 SELECT index 切换…

VS2022 使用ClaudiaIDE设置自定义图片背景

ClaudiaIDE的下载 第一步&#xff0c;如下图所示&#xff0c;点击&#xff1a;扩展——管理扩展。 第二步&#xff0c;如下图所示&#xff0c;点击&#xff1a;联机——右上角输入ClaudiaIDE搜索——点击下载。 下载后关闭所有VS窗口&#xff0c;然后等待弹出一个安装窗口&…

商密测评必知:国密算法的重要性与应用

国密算法是指由中国国家密码管理局发布的密码算法标准&#xff0c;旨在保障国家信息安全。目前&#xff0c;国家密码管理局已发布了一系列国产商用密码标准算法&#xff0c;包括SM1&#xff08;SCB2&#xff09;、SM2、SM3、SM4、SM7、SM9以及祖冲之密码算法&#xff08;ZUC)等…

P4317 花神的数论题(数位DP)

数组别太小&#xff0c;注意取模的数 #include<bits/stdc.h> using namespace std; using ll long long; using pii pair<int,int>; #define int long long const int N 1e510; const int inf 0x3f3f3f3f; const int mod 1e77; int gcd(int a,int b){return b…

华为OD七日集训第5期 - 按算法分类,由易到难,循序渐进,玩转OD

目录 一、适合人群二、本期训练时间三、如何参加四、七日集训第 3 期五、精心挑选21道高频经典题目&#xff0c;作为入门。第1天、逻辑分析第2天、双指针第3天、数据结构第4天、滑动窗口第5天、并查集第6天、贪心思维第7天、二分查找 大家好&#xff0c;我是哪吒。 最近一直在…

肖恩带你拿捏结构体!

先赞后看&#xff0c;养成习惯&#xff08;&#x1f601;&#xff09;&#xff0c;几天不见&#xff0c;甚是想念&#xff0c;今天肖恩带大家拿捏结构体~~~ 1. 结构体类型的声明 那首先&#xff0c;什么是结构体呢&#xff1f; C语⾔已经提供了内置类型&#xff0c;如&#…

皮肤科医生护肤误区揭秘:不洗脸变美的真相?

在信息过剩的社会&#xff0c;大家不断被各种护肤秘籍、美容宝典所包围。最近&#xff0c;“一周不洗脸皮肤变好”的话题引起热议&#xff0c;而紧随其后关于“女子为护肤一个月不洗脸&#xff0c;结果脸上结满痂痕险严重毁容”的新闻再次引发广泛关注。这让大家纷纷产生了疑惑…

对象存储服务MinIO快速入门

对象存储服务MinIO快速入门 MinIO简介开箱使用快速入门封装MinIO为starter1 创建模块heima-file-starter2 配置类3 封装操作minIO类4 对外加入自动配置5 其他微服务使用 MinIO简介 官网文档 开箱使用 docker run -p 9000:9000 --name minio -d --restartalways -e "MINIO…