STM32cubeIDE之外部中断控制LED流水灯(按键控制流水灯方向)

本篇文章将讲述两种方法实现外部中断控制LED流水灯的方法及代码(按键控制流水灯)。

可以根据我的方法进行创新,我会将思路也一同介绍。

首先,第一种:(whlie里面实现,不用定时器,运行完一次之后才能实现反向,只能从头开始亮)

我考虑这个问题时,就会首先想到最简单的while循环,利用while循环来实现。先讲思路,就是我们的程序是会反复进行whlie里面的循环的,然后我们就可以进行延时,逐一点亮LED实现流水灯的效果,这在我之前文章中介绍过,然后我们现在是想每次按键它的方向改变,我们可以定义一个参数,然后按一次按键,这个参数改变一次,每次对应不同的结果,即流水灯不同的流动方向。我们可以利用switch函数来实现(在我C语言的文章中有讲解switch)

具体实操:这个不需要配置定时器等,只需要打开外部中断即可。然后我们先配置一下最基础的,备注一下led引脚和外部中断按键引脚。我之前文章中讲到过如何配置,我这里简单展示和讲解。我用的是STM32F107VCT6的板子,所以对应的引脚是PE9 PE11 PE13 PE14 外部按键对应的引脚是PC6,大家根据自己板子的原理图进行配置,我这里给它们分别备注为D1,D2,D3,D4和K1,方便我们引用。然后再NVIC中打开外部中断。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_20,color_FFFFFF,t_70,g_se,x_16

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_20,color_FFFFFF,t_70,g_se,x_16 

 我们定义一个全局变量n(因为我们要在主函数中用又要在中断中使用,所以需要定义为全局变量),在main函数上面定义即可 例如下面位置

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_14,color_FFFFFF,t_70,g_se,x_16

 代码太长我不截图展示了,直接给大家打出来了

whlie(1)里面

  switch(n)
 {
    case 0:
	        {

			       HAL_GPIO_WritePin(GPIOE,D1_Pin,0);//写低电平,点亮第1个LED
			 	   HAL_Delay(1000);//延时1000毫秒
			 	   HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,GPIO_PIN_SET);
			 	   HAL_GPIO_WritePin(GPIOE,D2_Pin,0);
			 	  HAL_Delay(1000);//延时1000毫秒
			 	   HAL_GPIO_WritePin(GPIOE,GPIO_PIN_11,GPIO_PIN_SET);
			 	   HAL_GPIO_WritePin(GPIOE,D3_Pin,0);
			 	  HAL_Delay(1000);//延时1000毫秒
			 	  HAL_GPIO_WritePin(GPIOE,GPIO_PIN_13,GPIO_PIN_SET);
			 	  HAL_GPIO_WritePin(GPIOE,D4_Pin,0);
			 	  HAL_Delay(1000);//延时1000毫秒
			 	  HAL_GPIO_WritePin(GPIOE,GPIO_PIN_14,GPIO_PIN_SET);
			 	 	break;
			  }
			 	      case 1:
			 	          
			 	      {
			 		 		     HAL_GPIO_WritePin(GPIOE,D4_Pin,0);//写低电平,点亮第1个LED
			 		 		  		 	  HAL_Delay(1000);//延时1000毫秒
			 		 			  		 	  HAL_GPIO_WritePin(GPIOE,D4_Pin,1);//
			 		 			  		 	  //中间不延时,1灯灭�?2灯亮
			 		 			  		 	  HAL_GPIO_WritePin(GPIOE,D3_Pin,0);
			 		 			  		 	  HAL_Delay(1000);//延时1000毫秒
			 		 			  		 	  HAL_GPIO_WritePin(GPIOE,D3_Pin,1);
			 		 			  		 	  HAL_GPIO_WritePin(GPIOE,D2_Pin,0);
			 		 			  		 	  HAL_Delay(1000);//延时1000毫秒
			 		 			  		 	  HAL_GPIO_WritePin(GPIOE,D2_Pin,1);
			 		 			  		 	  HAL_GPIO_WritePin(GPIOE,D1_Pin,0);
			 		 			  		 	  HAL_Delay(1000);//延时1000毫秒
			 		 			  		 	  HAL_GPIO_WritePin(GPIOE,D1_Pin,1);
			 		 			  		   break;
		      }
			 		 			  		            default:
        {
			 		 			  		                break;
		      }


  }

外部中断(外部中断回调函数)

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{

   if(GPIO_Pin==K1_Pin)
   {
	   for(long i =1; i<72000;i++)//消抖
	   {}
		   n=!n;//逻辑非 0或者1

   }
}

我们可以通过分析程序看出,我写了两种情况,一种是case 0 从D1到D4亮

另一种是case 1 从D4到D1亮 

然后我们通过外部中断改变n值来实现这这两种流向的改变,但是这种只能是运行完一次后改变方向,从头开始亮,能部分达到我们的预期

第二种:(利用定时器,能直接反向,完全达到预期)

而且没有应用Delay,利用的是定时器中断

我们一样先将思路:我们先想到了第一种情况的办法,然后我之前也写过定时器控制流水灯的文章,我们结合起来,写两种情况,每种不同方向,但是我们要注意,我们利用定时器实现流水灯是利用了i++,然后if判断,如果我们改变了情况,也就是进入另一个case中的时候 i是多少,我们注意到这点之后,我们就可以判断当时是哪个灯亮了,在此基础上,顺时针方向亮的话是i++,改变方向,我们就可以i--实现

接着我们看具体实操

首先我们要配置一下io口和外部中断,如上,定时器我们可以配置溢出时间间隔,每次溢出都会进入中断回调函数,在之前的文章中有讲,不懂配置的可以去看看前面的文章。我简单展示

因为我的板子是25M频率的,所以我按照如下配置时间间隔为0.5ms

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_20,color_FFFFFF,t_70,g_se,x_16

 打开定时器中断

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_20,color_FFFFFF,t_70,g_se,x_16

 

然后我们定义两个我们要用到的全局变量

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_16,color_FFFFFF,t_70,g_se,x_16

打开定时器中断

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_20,color_FFFFFF,t_70,g_se,x_16 

 

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{	switch(n)
	{
	case 0:
{

	    if(i==1)
	   {
	    	HAL_GPIO_WritePin(GPIOE,D1_Pin,0);
	    	HAL_GPIO_WritePin(GPIOE,D2_Pin,1);
	    	HAL_GPIO_WritePin(GPIOE,D3_Pin,1);
	    	HAL_GPIO_WritePin(GPIOE,D4_Pin,1);
	    }
	    else if(i==2)
   {
	    HAL_GPIO_WritePin(GPIOE,D1_Pin,1);
	   	HAL_GPIO_WritePin(GPIOE,D2_Pin,0);
	   	HAL_GPIO_WritePin(GPIOE,D3_Pin,1);
	   	HAL_GPIO_WritePin(GPIOE,D4_Pin,1);
   }
	    else if(i==3)

	    {
	    	 HAL_GPIO_WritePin(GPIOE,D1_Pin,1);
	    	HAL_GPIO_WritePin(GPIOE,D2_Pin,1);
	    	HAL_GPIO_WritePin(GPIOE,D3_Pin,0);
	    	HAL_GPIO_WritePin(GPIOE,D4_Pin,1);
	    }
	    else  if(i==4)
	    {
	    	 HAL_GPIO_WritePin(GPIOE,D1_Pin,1);
	    	HAL_GPIO_WritePin(GPIOE,D2_Pin,1);
	    	HAL_GPIO_WritePin(GPIOE,D3_Pin,1);
	      HAL_GPIO_WritePin(GPIOE,D4_Pin,0);
        i=0;
	    }
	    i++;
	    break;
}
	case 1 :
{
    if(i==2)
   {
    	HAL_GPIO_WritePin(GPIOE,D1_Pin,0);
    	HAL_GPIO_WritePin(GPIOE,D2_Pin,1);
    	HAL_GPIO_WritePin(GPIOE,D3_Pin,1);
    	HAL_GPIO_WritePin(GPIOE,D4_Pin,1);
    	i=6;
    }
    else if(i==3)
{
    HAL_GPIO_WritePin(GPIOE,D1_Pin,1);
   	HAL_GPIO_WritePin(GPIOE,D2_Pin,0);
   	HAL_GPIO_WritePin(GPIOE,D3_Pin,1);
   	HAL_GPIO_WritePin(GPIOE,D4_Pin,1);
}
    else if(i==4)

    {
    	 HAL_GPIO_WritePin(GPIOE,D1_Pin,1);
    	HAL_GPIO_WritePin(GPIOE,D2_Pin,1);
    	HAL_GPIO_WritePin(GPIOE,D3_Pin,0);
    	HAL_GPIO_WritePin(GPIOE,D4_Pin,1);
    }
    else  if(i==5)
    {
    	 HAL_GPIO_WritePin(GPIOE,D1_Pin,1);
    	HAL_GPIO_WritePin(GPIOE,D2_Pin,1);
    	HAL_GPIO_WritePin(GPIOE,D3_Pin,1);
      HAL_GPIO_WritePin(GPIOE,D4_Pin,0);
    }
    i--;

	    break;
}

	  default:
	    {
		  break;
         }


	}



}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{

	  if(GPIO_Pin==K1_Pin)
	   {
		   for(long i =1; i<72000;i++)
		   {}
		   if (HAL_GPIO_ReadPin(K1_GPIO_Port,K1_Pin)==1)
		   {
			  n=!n;
		   }
		   __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
	   }

}

我们注意在这里面与第一种方法的不同,我们在每次运行结束的时候i--或者i++,所以i++的时候是1234,i--的时候就应该是2345.每次改变的时候i有着对应的i值,所以能实现直接反向,不用从头又开始。

有些才用软件的朋友可能不清楚外部中断和定时器中断写在哪里,其实可以写在begin4里面,如图

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA6L69Ry7pu5jor60=,size_20,color_FFFFFF,t_70,g_se,x_16

 

这样我们就逐步的实现了外部中断控制流水灯。

 

 

  • 33
    点赞
  • 135
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

辽G.默语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值