矩阵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
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要使用STM32控制矩阵按键来控制LED,您可以按照以下步骤进行操作: 1. 首先,连接矩阵按键LED到STM32微控制器。确保按键矩阵的行和列引脚连接到适当的GPIO引脚,并将LED连接到另外的GPIO引脚。 2. 在STM32上配置GPIO引脚作为输入和输出。使用STM32的开发工具(如STM32CubeMX)或编程语言(如C语言)配置相应的引脚。 3. 在程序中实现矩阵按键扫描。使用循环遍历按键矩阵的每个行和列,检测是否有按键按下。可以使用外部中断或定时器中断来触发扫描。 4. 根据按键状态控制LED。根据扫描结果,确定哪个按键按下,并相应地控制对应的LED引脚输出高电平或低电平来点亮或熄灭LED。 下面是一个示例代码片段,展示了如何在STM32上实现矩阵按键控制LED的功能(使用STM32 HAL库): ```c #include "stm32f4xx_hal.h" // 定义矩阵按键行和列数 #define ROWS 4 #define COLS 4 // 定义矩阵按键的行和列引脚 GPIO_TypeDef* ROW_PINS[ROWS] = {GPIOA, GPIOB, GPIOC, GPIOD}; uint16_t ROW_PINS_NUM[ROWS] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3}; GPIO_TypeDef* COL_PINS[COLS] = {GPIOE, GPIOF, GPIOG, GPIOH}; uint16_t COL_PINS_NUM[COLS] = {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3}; // 定义LED引脚 GPIO_TypeDef* LED_PORT = GPIOI; uint16_t LED_PIN = GPIO_PIN_0; // 定义矩阵按键状态数组 uint8_t keyStatus[ROWS][COLS] = {0}; // 矩阵按键扫描函数 void scanKeypad(void) { for (int row = 0; row < ROWS; row++) { HAL_GPIO_WritePin(ROW_PINS[row], ROW_PINS_NUM[row], GPIO_PIN_RESET); for (int col = 0; col < COLS; col++) { if (HAL_GPIO_ReadPin(COL_PINS[col], COL_PINS_NUM[col]) == GPIO_PIN_RESET) { keyStatus[row][col] = 1; // 按键按下 } else { keyStatus[row][col] = 0; // 按键未按下 } } HAL_GPIO_WritePin(ROW_PINS[row], ROW_PINS_NUM[row], GPIO_PIN_SET); } } // 控制LED函数 void controlLED(void) { if (keyStatus[0][0] == 1) { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_SET); // 点亮LED } else { HAL_GPIO_WritePin(LED_PORT, LED_PIN, GPIO_PIN_RESET); // 熄灭LED } } int main(void) { HAL_Init(); // 初始化GPIO引脚配置和外部中断/定时器中断配置 while (1) { scanKeypad(); controlLED(); } } ``` 请注意,以上代码仅为示例,您需要根据您的具体硬件和需求进行适当的修改和调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值