一.CUBEMX配置GPIO

二.代码语句

(1)读取GPIO状态

HAL_GPIO_ReadPin(GPIOE, GPIO_PIN_10) == GPIO_PIN_RESET
//读取GPIO状态,判断是否为高电平

(2)翻转小灯

HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_13);//小灯反转

(3)配置小灯高低电平

HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_RESET);//小灯高低电平设置

(5)利用标签配置引脚示例

给引脚打标签,无需通过引脚号定位引脚,可以通过标签定位

HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin);

(6)一次设置三小灯状态示例

HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);

三.实验

1.三个按键分别控制三个灯

(按PE10(KEY2)亮灯PE13,按PE11亮PE14,按PE12亮PE14)

/* USER CODE BEGIN PFP */
uint8_t key(uint16_t GPIO_Pin);//声明函数
/* USER CODE END PFP */

//检测按键是否(被按+松开)的函数
/* USER CODE BEGIN 4 */
uint8_t key(uint16_t GPIO_Pin)
{
    if(HAL_GPIO_ReadPin(GPIOE, GPIO_Pin) == GPIO_PIN_RESET)//按键被按下
    {
        HAL_Delay(50); //延时防抖动
        if(HAL_GPIO_ReadPin(GPIOE, GPIO_Pin) == GPIO_PIN_RESET)
        {
       
            while(HAL_GPIO_ReadPin(GPIOE, GPIO_Pin) == GPIO_PIN_RESET);
           //按键持续被按,则在循环中,直到松开按键,返回1
            return 1; 
        }
    }
    return 0; 
}
/* USER CODE END 4 */
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */


//主循环
		if(key(GPIO_PIN_10))
		{
		HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_13);//翻转小灯
		}
		if(key(GPIO_PIN_11))
		{
		HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_14);
		}
		if(key(GPIO_PIN_12))
		{
		HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_15);
		}
	
  }
  /* USER CODE END 3 */

2.一个按键循环打开三个灯

(PE10按一下PE13亮,再按PE14亮,再按PE15亮)

只修改主循环

/* USER CODE BEGIN PD */
uint8_t i=0;
//i声明成全局变量
/* USER CODE END PD */
	    if(key(GPIO_PIN_10))
		{
			i++;
		}
		
		switch(i)
		{
			case 1:
			{
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
			break;
			}
			case 2:
			{
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13|GPIO_PIN_15,GPIO_PIN_SET);
		
			break;
			}
			case 3:
			{
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_15,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13|GPIO_PIN_14,GPIO_PIN_SET);
			i=0;
			break;
			}
		}	
  }
  /* USER CODE END 3 */

3.长按小灯亮起,松开灯灭

   /* USER CODE BEGIN 3 */
    HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin);
	if( HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
	{
	HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_RESET);
	}
	else
	{
	HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_SET);
	}
  }
  /* USER CODE END 3 */

4.一个按键切换三种亮灯花样

		if(key(GPIO_PIN_10))
		{
			i++;
		}
 
		
		switch(i)
		{
			case 1://流水灯
			{
			while(!(key(GPIO_PIN_10)==1))
			{
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_RESET);
			HAL_Delay(100);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_SET);
			HAL_Delay(100);	
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14,GPIO_PIN_RESET);
			HAL_Delay(100);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14,GPIO_PIN_SET);
			HAL_Delay(100);	
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_15,GPIO_PIN_RESET);
			HAL_Delay(100);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_15,GPIO_PIN_SET);
			HAL_Delay(100);	
			}
			i++;
		    break;
			}
			
			case 2://14常亮,13、15轮流闪烁
			{
			while(!(key(GPIO_PIN_10)==1))
			{	
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13|GPIO_PIN_14,GPIO_PIN_RESET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_15,GPIO_PIN_SET);
			HAL_Delay(100);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_SET);
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_RESET);

			HAL_Delay(100);
		    }
			i++;
		    break;
			}
			
			case 3://13、14轮流闪烁两下,15不亮
			{
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
	
					while(!(key(GPIO_PIN_10)==1))
				{	
		
					uint8_t u;
					for(u=0;u<3;u++)
					{
					HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_13);
					HAL_Delay(100);	
					}
					for(u=0;u<3;u++)
					{
					HAL_GPIO_TogglePin(GPIOE, GPIO_PIN_14);
					HAL_Delay(100);	
					}
				}
			i++;
		    break;
			}
		
			case 4://全部熄灭
			{
				while(!(key(GPIO_PIN_10)==1))
			{	
			HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15,GPIO_PIN_SET);
			}
			i=1;
		    break;
			}
		}
		

	
  }
  /* USER CODE END 3 */

(1)问题:

有时按按键以后小灯形式无变化。

while(!(key(GPIO_PIN_10)==1)) 循环,这个循环会持续阻塞程序,直到再次按下按键才会退出。
例如在 case 1 中,流水灯循环时,程序被卡在 while 里,此时即使按下按键,key() 函数虽然能检测到按键,但外层的 if(key(GPIO_PIN_10)) 根本没有机会执行(因为程序没跳出 while 循环)。
只有当 while 循环退出后(即再次按下按键),i 才会加 1,切换到下一个模式。

(2)解决:

/* USER CODE BEGIN 3 */
// 主循环中先检测按键,按下则切换模式
if(key(GPIO_PIN_10))
{
    i++;  // 每次按键按下,切换到下一个模式
    if(i > 4)  // 边界判断:超过最大模式则回到1
        i = 1;
    
    // 切换模式时,先关闭所有灯,避免状态残留
    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);
    HAL_Delay(50);  // 短暂延时,确保状态切换明显
}

// 根据当前模式执行对应逻辑(非阻塞,每次循环执行一次)
switch(i)
{
    case 1: 
    {
        static uint8_t flow_step = 0;  // 静态变量记录流水灯步骤
        static uint32_t flow_last_time = 0;
        
        // 每隔100ms切换一次灯,避免用HAL_Delay阻塞
        if(HAL_GetTick() - flow_last_time > 100)
        {
            flow_last_time = HAL_GetTick();
            
            // 先关闭所有灯
            HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);
            
            // 按步骤点亮对应灯
            switch(flow_step)
            {
                case 0: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, GPIO_PIN_RESET); break;
                case 1: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14, GPIO_PIN_RESET); break;
                case 2: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_15, GPIO_PIN_RESET); break;
            }
            
            flow_step++;
            if(flow_step >= 3)
                flow_step = 0;
        }
        break;
    }
    
    case 2:  // 14常亮,13、15轮流闪烁
    {
        static uint32_t blink_last_time = 0;
        static uint8_t blink_state = 0;
        
        // 14常亮
        HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14, GPIO_PIN_RESET);
        
        // 每隔100ms切换13和15的状态
        if(HAL_GetTick() - blink_last_time > 100)
        {
            blink_last_time = HAL_GetTick();
            blink_state = !blink_state;
            
            HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, blink_state ? GPIO_PIN_SET : GPIO_PIN_RESET);
            HAL_GPIO_WritePin(GPIOE, GPIO_PIN_15, blink_state ? GPIO_PIN_RESET : GPIO_PIN_SET);
        }
        break;
    }
    
    case 3:  // 13、14轮流闪烁两下,15不亮
    {
        static uint8_t flash_step = 0;
        static uint32_t flash_last_time = 0;
        static uint8_t count = 0;
        
        // 15始终不亮
        HAL_GPIO_WritePin(GPIOE, GPIO_PIN_15, GPIO_PIN_SET);
        
        if(HAL_GetTick() - flash_last_time > 100)
        {
            flash_last_time = HAL_GetTick();
            flash_step++;
            
            if(flash_step % 2 == 1)  // 奇数次:闪烁13
            {
                HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, GPIO_PIN_RESET);
                HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14, GPIO_PIN_SET);
            }
            else  // 偶数次:关闭13
            {
                HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, GPIO_PIN_SET);
                if(count < 2)  // 只闪烁2次
                {
                    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14, GPIO_PIN_RESET);
                    count++;
                }
                else  // 闪烁完成后重置计数
                {
                    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14, GPIO_PIN_SET);
                    count = 0;
                    flash_step = 0;
                }
            }
        }
        break;
    }
    
    case 4:  // 全部熄灭
    {
        HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15, GPIO_PIN_SET);
        break;
    }
}
/* USER CODE END 3 */

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐