矩阵LED和矩阵按键

先说矩阵LED,如图:
在这里插入图片描述
下面以行几、列几的表达方法说明
三极管可以当做开关使用
由图可知,如果想让一个LED亮,那么它对应的行和列的三极管都要导通。如果这个矩阵每次只亮一个LED,那么正常写程序没问题。

如果我们想让LED1和LED6亮,其他灯不亮,则需要开启行1、行2、列1、列2,随之带来的问题就是LED2和LED5也会跟着亮起来。

解决方法类似于扫描,因为单片机运行速度很快,可以在很短的时间内开关数次而肉眼看不到。所以我们可以每次只亮一列(排)灯,亮单位时间后关掉同时开启另外一列(排),如此四次一循环就可以让该亮的灯亮起来,不该亮的灯关闭。下附源码(用的STM32F103芯片)

//这个任务放在时间片里跑
//将打开(关闭)一行(一列)封装成了四个小函数
//A[][]是个4X4的数组,对应矩阵16个LED
void TASK_LED(void)
{	
	static uint8_t flag=0;
	static uint8_t H=0;
	int a=0;
	TIM_ClearFlag(TIM3, TIM_FLAG_Update); //清除中断标志位
  switch (flag)  //用switch方法实现轮询
	{
		case 0:
		{
			for(a=0;a<4;a++)
			{
				if(A[H][a])
				{
					line_on(a);  //打开一列
					row_on(H);  //打开一行  这两个函数的定义在后面
				}
			}
			flag=1;  //把标志位改成下一个,类似于指针,下一次进switch会进入下一种情况进行运行 
			break;
		}
		case 1:
		{
			for(a=0;a<4;a++)
			{
				if(A[H][a])
				{
					line_off(a);
					row_off(H);
				}
			}
			flag=2;
			H=1;
			break;
		}	
		case 2:
		{
			for(a=0;a<4;a++)
			{
				if(A[H][a])
				{
					line_on(a);
					row_on(H);
				}
			}
			flag=3;
			break;
		}
		case 3:
		{
			for(a=0;a<4;a++)
			{
				if(A[H][a])
				{
					line_off(a);
					row_off(H);
				}
			}
			flag=4;
			H=2;
			break;
		}		
		case 4:
		{
			for(a=0;a<4;a++)
			{
				if(A[H][a])
				{
					line_on(a);
					row_on(H);
				}
			}
			flag=5;
			break;
		}
		case 5:
		{
			for(a=0;a<4;a++)
			{
				if(A[H][a])
				{
					line_off(a);
					row_off(H);
				}
			}
			flag=6;
			H=3;
			break;
		}		
		case 6:
		{
			for(a=0;a<4;a++)
			{
				if(A[H][a])
				{
					line_on(a);
					row_on(H);
				}
			}
			flag=7;
			break;
		}
		case 7:
		{
			for(a=0;a<4;a++)
			{
				if(A[H][a])
				{
					line_off(a);
					row_off(H);
				}
			}
			flag=0;
			H=0;
			break;
		}		
	}
	
}

void line_on (uint8_t line)
{
	switch (line) //用switch查找拉低引脚的位置
	{
		case 0:
		{
			GPIO_ResetBits(GPIOA,LEDL1_GPIO);
			break;
		}
		case 1:
		{
			GPIO_ResetBits(GPIOA,LEDL2_GPIO);
			break;
		}
		case 2:
		{
			GPIO_ResetBits(GPIOA,LEDL3_GPIO);
			break;
		}
		case 3:
		{
			GPIO_ResetBits(GPIOA,LEDL4_GPIO);
			break;
		}
	}
}
void line_off (uint8_t line)
{
	switch (line)  //用switch查找拉高引脚的位置
	{
		case 0:
		{
			GPIO_SetBits(GPIOA,LEDL1_GPIO); 
			break;
		}
		case 1:
		{
			GPIO_SetBits(GPIOA,LEDL2_GPIO);
			break;
		}
		case 2:
		{
			GPIO_SetBits(GPIOA,LEDL3_GPIO);
			break;
		}
		case 3:
		{
			GPIO_SetBits(GPIOA,LEDL4_GPIO);
			break;
		}
	}
}

void row_on (uint8_t row)
{
		switch (row)  //用switch查找拉高引脚的位置
	{
		case 0:
		{
			GPIO_SetBits(GPIOA,LEDH1_GPIO);
			break;
		}
		case 1:
		{
			GPIO_SetBits(GPIOA,LEDH2_GPIO);
			break;
		}
		case 2:
		{
			GPIO_SetBits(GPIOB,LEDH3_GPIO);
			break;
		}
		case 3:
		{
			GPIO_SetBits(GPIOB,LEDH4_GPIO);
			break;
		}
	}
}

void row_off (uint8_t row)
{
		switch (row)  //用switch查找拉低引脚的位置
	{
		case 0:
		{
			GPIO_ResetBits(GPIOA,LEDH1_GPIO);
			break;
		}
		case 1:
		{
			GPIO_ResetBits(GPIOA,LEDH2_GPIO);
			break;
		}
		case 2:
		{
			GPIO_ResetBits(GPIOB,LEDH3_GPIO);
			break;
		}
		case 3:
		{
			GPIO_ResetBits(GPIOB,LEDH4_GPIO);
			break;
		}
	}
}

矩阵键盘也类似
在这里插入图片描述
可以知道当KEYA为高电平时,KEy1检测的就是高电平,为低电平时,KEY1检测的就是低电平。
也会出现之前所讲过的对角线问题,解决方法依然是轮询
每次打开一列,检测三行,然后关闭这一列打开另一列,如此往复三次为一个循环。
下附源码(也是在时间片里):

//KEY[][]对应一个3X3的数组,对应九个按键
void Key_Scan(uint8_t line)  //实现键盘扫描后标志位置一
{
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)==1)
	{
		KEY[line-1][0]=1;
	}
	else
	{
		KEY[line-1][0]=0;
	}
	
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)==1)
	{
		KEY[line-1][1]=1;
	}
	else
	{
		KEY[line-1][1]=0;
	}
	
	if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_15)==1)
	{
		KEY[line-1][2]=1;
	}
	else
	{
		KEY[line-1][2]=0;
	}
}



void Key_Task(void)  //实现键盘的扫描
{

	 
	switch(Flag_key)
	{
		case 0:
		{
			GPIO_SetBits(GPIOB,GPIO_Pin_10);
			Key_Scan(1);
			GPIO_ResetBits(GPIOB,GPIO_Pin_10);
			Flag_key=1;
			break;
		}
		case 1:
		{
			GPIO_SetBits(GPIOB,GPIO_Pin_11);
			Key_Scan(2);
			GPIO_ResetBits(GPIOB,GPIO_Pin_11);
			Flag_key=2;
			break;
		}
		case 2:
		{
			GPIO_SetBits(GPIOB,GPIO_Pin_12);
			Key_Scan(3);
			GPIO_ResetBits(GPIOB,GPIO_Pin_12);
			Flag_key=0;
			break;
		} 
	}
}
  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值