蓝桥杯单片机数码管+按键+定时器调用底层代码

适用于有一定了解数码管和按键底层的同学进阶使用,当然不了解直接用也没问题,根据题目改参数就好了,借用此代码学习按键和数码管也是极好的!

先来进行按键部分

按键的基本逻辑按照我自己的理解就是按键的一端接地 一端接引脚 当按键按下使两端联通,引脚此时为高电平也会被下拉为低电平。所以检测按键按下时只要检测为高电平的引脚何时被下拉成低电平就好。

我们的代码以矩阵键盘S4 S8 S5 S9为例子

每一列不予设置默认为高电平,每一行循环扫描,也就是将想要进行扫描的行数对应引脚设置为0即低电平。//至于为何要一行一行扫描请自行查询相关资料

我们的按键不能影响到主函数的运行 所以在消抖部分不能采用延时消抖的方式,同时要求我们按下一次按键只执行一次效果。

所以我们设置一个直接的按键检测数组对应对应的行列按键值,为1时松开 为0时为按下,一个记录上一次的按键检测数组,为了不出现按键连续执行的效果。

通过扫描我们的直接按键检测数组和上一次按键检测数组给予我们的主函数返回对应数值,若没有按键按下返回值为0,其他返回值为行数*使用的行的数量+列数+1  当我们按键行列数发生改变时该文件中的相关数据随之要变化,也就是Key_Get和Last_Key_Get,以及我们下面Key_Loop()中的Buff和loop,这样我们就掌握了矩阵按键了,只要在主函数中的中断函数每一毫秒调用一次Key_Loop(),在主函数中接收Key()的值就好了。

#include <STC15F2K60S2.H>
sbit H1=P3^3;
sbit H2=P3^2;
sbit L1=P4^4;
sbit L2=P4^2;	//设置按键的引脚行列
unsigned char Key_Get[2][2]={{1,1},{1,1}};//用于检测按键是否按下的判断参数 前一个下标表示行 后一个下标表示列
unsigned char Last_Key_Get[2][2]={{1,1},{1,1}};//按键不影响主函数运行,按下按键后保证上一刻按键处于没按下的状态判断参数
unsigned char Key()
{
	unsigned char i,j;//扫描行列
	for(i=0;i<2;i++)
	{
		for(j=0;j<2;j++)
		{
			if(Key_Get[i][j]==0 && Last_Key_Get[i][j]==1)//按键按下,且上一刻处于未按下
			{
				Last_Key_Get[i][j]=0;//已经按下 等待松开按键复原
				return i*2+j+1;
			}
		}
	}
	return 0;
}
void Key_Loop()
{
	static unsigned char Buff[2][2]={{0xff},{0xff}};//检测按键按下的中间参数,具有消抖的功能
	static unsigned char loop;//循环扫描行数
	unsigned char i;//扫描用
	Buff[loop][0]=(Buff[loop][0]<<1)|L1;//每一毫秒(中断调用)检测按下 连续无抖的八毫秒按下使其变为0x00
	Buff[loop][1]=(Buff[loop][1]<<1)|L2;
	for(i=0;i<2;i++)
	{
		if(Buff[loop][i]==0xff)//松开按键
		{
			Key_Get[loop][i]=Last_Key_Get[loop][i]=1;	//将直接参数设置为松开状态
		}
		else if(Buff[loop][i]==0x00)
		{
			Key_Get[loop][i]=0;	//将直接参数设置为按下状态
		}
	}
	loop++;//循环扫描行数
	loop%=2;
	switch(loop)
	{
		case 0:H2=1;H1=0;break;//扫描第一行
		case 1:H1=1;H2=0;break;//扫描第二行
	}
}

接下来我们来看数码管部分,我们知道数码管的调用需要将想要的字符转化为相应的段选再在相应的位选中调用。

所以我们用两个指针指向两个数组(一个是我们用来设置每一个数码管对应位的段选码的字符串,一个是我们用来存储段选码等待数码管位选调用显示的存储字符串数组)用str为buff从我们看到的字符转为数码管可以对应显示的段选数据。

当我们定义好buff以后,只需要在主函数的中断函数中调用Nixie_Loop()就可以在数码管上显示我们想要的数据了,这中途的设置需要我们在主函数中定义两个数组,对str进行设置,这一部分很简单,只要有c语言的基础就肯定看的懂,就不赘述了。

#include <STC15F2K60S2.H>
void Nixie_Set(unsigned char* str,unsigned char* buff)//str为要显示的字符串,buff中存储相对的数码管值
{
	unsigned char i,j,temp;
	for(i=1,j=0;i<9;i++,j++)	//i为buff下标 对应1-8号数码管 j对应str下标 指向每一位字符
	{
		switch(str[j])
		{
			case '0':temp=0xc0;break;
			case '1':temp=0xf9;break;
			case '2':temp=0xa4;break;
			case '3':temp=0xb0;break;
			case '4':temp=0x99;break;
			case '5':temp=0x92;break;
			case '6':temp=0x82;break;
			case '7':temp=0xf8;break;
			case '8':temp=0x80;break;
			case '9':temp=0x90;break;
			case ' ':temp=0xff;break;
			case '-':temp=0xbf;break;	//为temp赋值 最终为buff每一位赋值
		}
		if(str[j+1]=='.')
		{
			j++;
			temp&=0x7f;	//当下一位为.时不应该占用数码管一位 应该点亮右下角DP后跳过.
		}
		buff[i]=temp;//赋值
	}
}
void Nixie_Loop(unsigned char* buff)
{
	static unsigned char i=1;//全局参数,扫描对应的数码管位数 每一毫秒调用一位数码管
	P0=0xff;	//消影
	P2=(P2&0x1f)|0xe0;
	P2&=0x1f;
	
	P0=0x01<<(i-1);//位选
	P2=(P2&0x1f)|0xc0;
	P2&=0x1f;
	
	P0=buff[i];//段选
	P2=(P2&0x1f)|0xe0;
	P2&=0x1f;
	
	i++;
	if(i>8) i=1;//循环调用八位数码管
}

最后是主函数,这里就没有什么过多可以解释的部分了,都非常简答,不明白的话评论区大佬会为你解答的。

#include <STC15F2K60S2.H>	//后续的模块都会在这两个模块基础上去写,代码现象按下S4,S8,S5,S9数码管对应显示1234
#include "stdio.h"	//用于设置String,调整数码管显示
#include "Key.h"
#include "Nixie.h"
unsigned char keynum;
unsigned char String[10];
unsigned char String_Buff[9];
void Timer0Init(void)		//1000微秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0=EA=1;	//复制完stc的初始化后 打开ET0定时器0中断开关  EA中断总开关
}
void main()
{
	Timer0Init();//初始化调用 注意不要放入循环
	while(1)
	{
		keynum=Key();//获取按键值
		if(keynum)//当按键不为0 也就是按下状态显示按键值
			sprintf(String,"-------%01d",(unsigned int)keynum);//基础的c语言知识 不赘述
		Nixie_Set(String,String_Buff);//将设置好的String内容转换为对应段选值给String_Buff
	}
}
void T0_LP()	interrupt 1	//定时器0的中断号为1 定时器1中断号为3 定时器2中断号为12 串口中断号为4
{
	Key_Loop();
	Nixie_Loop(String_Buff);//调用String_Buff显示
}

蓝桥杯也是不辜负期待拿到了省一,这一段时间还挺忙的,也没有怎么复习蓝桥杯,好在之前也把国赛题目做的七七八八了,复习了差不多一周多吧,还有两三天就要考国赛了,还挺激动的,虽然都大三了但是还是没有什么拿的出手的技术,想着还是把自己有信心的东西拿出来展示一下。把我精心调整了许多次的底层代码分享出来希望大家可以在更早的时间拿到自己期待的成绩吧,后续还有其他的模块,等我有时间就发出来供大家参考。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值