蓝桥杯(单片机组)学习笔记(三)--------LED/按键/数码管/蜂鸣器/继电器

基础不是很好,所以程序思路只能说够用就行,之后我会慢慢修改回来完善。
今晚跟人吵架了很难受QWQ
1.LED
在这里插入图片描述
在这里插入图片描述
上一节已经分析过,先操作锁存器P2口,再操作P0口。不过这块板子有些缺陷,要初始化把继电器关了,再把LED关了。偷懒的话把LED初始化放在后面,这样锁存器依然是选中LED的,就可以直接进行LED的操作。(12MHZ)

#include <STC15F2K60S2.H>//流水灯程序
typedef unsigned long u32;
typedef unsigned int uint;	  //对数据类型进行声明定义
typedef unsigned char uchar;

//N ms延时 
void delay_ms(uint n)
{
	uint i,j;
	for (i = n; i>0;i--)
	for (j = 114;j>0;j--);
}

void main(void)
{
	uchar i = 0;
	P2 = 0XA0,P0 = 0X00;//关闭继电器
	P2 = 0X80;P0 = 0XFF;//关LED
	
	while(1)
	{
		for( i = 0;i <8;i++)
		{
			P0 = ~(1<<i);
			delay_ms(1000);
		}
	}
}

2.独立按键
按键之前我研究了很多种办法,比如什么状态标志位判断或者说是三行代码得到TRG。然后经过这么久的洗刷还是觉得比赛就用最简单的消抖按键就行了(毕竟按键也不多,复制粘贴也比较轻松)这个唯一的毛病就是需要占用定时器0(专门拿一个定时器来给按键)。后期如果遇到简单好使的方就补充。(长短按键,如果是一般的,用swich也可以做)

/*长按一个灯亮,短按另一个灯亮*/
#include <STC15F2K60S2.H>
typedef unsigned int uint;
typedef unsigned char uchar;
typedef unsigned long uint32;
sbit key1 = P3^0;
uint key_count;
uchar key_state;
uchar flag_key =0;

void Timer0Init(void);
void delay_ms(uint n)
{
	uint i,j;
	for (i = n; i>0;i--)
	for (j = 114;j>0;j--);
}

void  Key1_scan(void)
{
	if (!key1)
	{
		delay_ms(10);
		if (!key1)
		{
			TR0 = 1;
			while(!key1);
			if (flag_key)
			{
				key_state = 1;
				flag_key = 0;
			}
			else
			{
				key_state = 2;
			}
			
		}
	}
}


void main(void)
{
	uchar i = 0;
	P2 = 0XA0,P0 = 0X00;//关闭继电器
	P2 = 0X80;P0 = 0XFF;//关LED
	Timer0Init();
	while(1)
	{
		 Key1_scan();
		 
		 switch(key_state)
		 {
			
			case 1:P0 = 0xFe;break;
			case 2:P0 = 0Xf7;break;
		 }
	}
	
	
	
}

void Timer0Init(void)		//5毫秒@11.0592MHz
{
	EA = 1;
	ET0 = 1;
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x28;		//设置定时初值
	TF0 = 0;		//清除TF0标志
}

void  Timer0()  interrupt 1 
{
	key_count++;
	if (key_count = 500)
	{
		flag_key = 1;
		key_count = 0;
		TR0 = 0;
	}
}

3.矩阵按键
矩阵按键
跳线帽拔到BTN端。很容易得出这个矩阵按键就是X-Y格式排列的。所以定位行列就可以定位到对应的按键。

C语言中要用到的 switch语句

switch(表达式)
			{
				case(常量表达式1): 语句1; break;
				case(常量表达式2): 语句2; break;
				case(常量表达式3): 语句3; break;
				case(常量表达式4): 语句4; break;
				default:break;//默认..可以省略
			}

程序思路:
先检测是否有按键按下,再判断按键的位置。(用于都是一个口上)

void jzKey(void)
{
	if (P3 != 0xFF)
	{
		Delay10ms();
		if(P3 != 0xFF)
		{
			P3 = 0X0F;//给KEY初值,先检测行
			switch(P3)//先检测行
			{
				case(0x0e): KeyValue=1;break;
				case(0x0d): KeyValue=2;break;
				case(0x0b): KeyValue=3;break;
				case(0x07): KeyValue=4;break;
				
			}
			P3 = 0XF0;//测试列
			switch(P3)
			{
				case(0xe0): KeyValue=KeyValue+12;break;
				case(0xd0): KeyValue=KeyValue+8;break;
				case(0xb0): KeyValue=KeyValue+4;break;
				case(0x70): KeyValue=KeyValue;break;					
			}
			while(!P3);	 //检测按键松手检测
		}
	}

}

发现自己犯了个错,蓝桥杯的板子上的转接口把口的位置变了。在这里插入图片描述
所以按照某位大可爱给的CTRLCV办法,干脆就直接sbit了。

/*代码片段:先判断一行一行的判断*/
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;
sbit L1 = P4^4;//P3^7 = P4^4
sbit L2 = P4^2;//P3^6 = P4^2
sbit L3 = P3^5;
sbit L4 = P3^4;

uchar jzKey(void)
{
	static uchar key_value = 0;
	H1 = 0;
	H2 = H3 = H4 = L1 =L2 =L3 =L4 =1;
	if(!L1)
	{
		Delay10ms();
		if(!L1)
		{
			key_value = 1;
		}while(!L1);
	}
	else if(!L2)//复制修改
	{
		Delay10ms();
		if(!L2)
		{
			key_value = 2;
		}while(!L2);
	}
	else if(!L3)
	{
		Delay10ms();
		if(!L3)
		{
			key_value = 3;
		}while(!L3);
	}
	else if(!L4)
	{
		Delay10ms();
		if(!L4)
		{
			key_value = 4;
		}while(!L4);
	}
	//复制修改
	H2 = 0;
	H1 = H3 = H4 = L1 =L2 =L3 =L4 =1;
	if(!L1)
	{
		Delay10ms();
		if(!L1)
		{
			key_value = 5;
		}while(!L1);
	}
	else if(!L2)
	{
		Delay10ms();
		if(!L2)
		{
			key_value = 6;
		}while(!L2);
	}
	else if(!L3)
	{
		Delay10ms();
		if(!L3)
		{
			key_value = 7;
		}while(!L3);
	}
	else if(!L4)
	{
		Delay10ms();
		if(!L4)
		{
			key_value = 8;
		}while(!L4);
	}
	
	H3 = 0;
	H2 = H3 = H4 = L1 =L2 =L3 =L4 =1;
	if(!L1)
	{
		Delay10ms();
		if(!L1)
		{
			key_value = 9;
		}while(!L1);
	}
	else if(!L2)
	{
		Delay10ms();
		if(!L2)
		{
			key_value = 10;
		}while(!L2);
	}
	else if(!L3)
	{
		Delay10ms();
		if(!L3)
		{
			key_value = 11;
		}while(!L3);
	}
	else if(!L4)
	{
		Delay10ms();
		if(!L4)
		{
			key_value = 12;
		}while(!L4);
	}
	
	H4 = 0;
	H2 = H3 = H1 = L1 =L2 =L3 =L4 =1;
	if(!L1)
	{
		Delay10ms();
		if(!L1)
		{
			key_value = 13;
		}while(!L1);
	}
	else if(!L2)
	{
		Delay10ms();
		if(!L2)
		{
			key_value = 14;
		}while(!L2);
	}
	else if(!L3)
	{
		Delay10ms();
		if(!L3)
		{
			key_value = 15;
		}while(!L3);
	}
	else if(!L4)
	{
		Delay10ms();
		if(!L4)
		{
			key_value = 16;
		}while(!L4);
	}
	return key_value;
}
	

void main()
{
	uchar key = 0;
	All_Init();
	while(1)
	{
		key = jzKey();
		if(key == 6)
		{
			P2 = (P2 & 0X1F | 0X80);
			P0 = 0X00;
			key = 0;
		}
	}	
}


三.数码管

在这里插入图片描述
数码管一般考察都是动态,先位选再段选;
https://blog.csdn.net/zlllg/article/details/82119338可以参考一下这个老哥的博客,先码着明天看~

//数码管动态扫描核心代码

code unsigned char Duan_Data[] = {0Xc0,0xf9,0xa4,0xb0,0X99,0X92,0X82,0XF8,0X80,0X90,0x88,0x83,0xc6,0xa1,0x86,0x8e}; //共阳的段码,会给的不用记
code unsigned char Wei_Data[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};//要记住的 
void Display(int dat)
{
	uchar i,j = 0;
	uchar str[3];
	
	str[0] = dat%10;//个位
	str[1] = dat/10%10;//十位
	str[2] = dat/100;//百位
	
	for(i = 0; i<3;i++)//要显示几位就循几次
	{
		P2 = (P2&0X1F|0XC0);//位
		P0 = Wei_Data[7-i];
		P2= (P2&0X1F|0XE0);//段
		P0 = Duan_Data[str[i]];
		Delay_ms(3);//反复试了几次,比较稳定的延时
		P0 = 0XFF;//消影
	}
}

void main(void)
{
	All_Init();
	while(1)
	{
		Display(321);
	}
}

当要求加小数点的时候,我们知道共阳段选小数点是0X7F ,对特定位清零用&,所以只需要再加上 P0 = Duan_Data[str[i]]&0X7F。

四.蜂鸣器/继电器

在这里插入图片描述

P2 = (P2&0X1F|0XA0);
P0 = 0X10|0X40;//继电器/蜂鸣器开
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值