按键短按灯亮六秒后灭,长按三秒灯亮三秒后灭

2019-07-20 05:45发布

本帖最后由 jiangyy 于 2018-10-10 11:55 编辑

  今天闲着无聊,一个新手请教我一个问题:短按 SW1 后,LED1亮6秒然后灭。长按SW1三秒后松开,LED1亮3秒后灭。闲着无聊,就写了一下。我的思路大概是这样的:外部中断+定时器
1.定时器3
  配置好后定时器3,默认不使能定时器。
void TIM3_Int_Init(u16 arr,u16 psc)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
  TIM_TimeBaseInitStructure.TIM_Period = arr;  
  TIM_TimeBaseInitStructure.TIM_Prescaler=psc;  
  TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
  TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
  TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
  TIM_Cmd(TIM3,DISABLE);
  NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03;
  NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}
2.SW1引脚配置成外部中断
void EXTIX_Init(void)
{
  NVIC_InitTypeDef   NVIC_InitStructure;
  EXTI_InitTypeDef   EXTI_InitStructure;
  KEY_Init(); //这里按键配置就不说了
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
  SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;//LINE0
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;//ʹÄÜLINE0
  EXTI_Init(&EXTI_InitStructure);
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);  
}
  3.中断服务函数处理
(1)定时器中断服务函数
u16 ucTimer = 0;
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
  ucTimer++;
  if(WK_UP)
  {
   if(ucTimer ==300)//3S
   {
    handle_Led(ON,3);
    ucTimer = 0;
    TIM_Cmd(TIM3,DISABLE);
   }
  }
  else
  {
   handle_Led(ON,6);
   ucTimer = 0;
   TIM_Cmd(TIM3,DISABLE);
  }
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
}
  (2)外部中断函数
void EXTI0_IRQHandler(void)
{
delay_ms(10);
if(WK_UP)
{
  TIM_Cmd(TIM3,ENABLE);
}
EXTI_ClearITPendingBit(EXTI_Line0);
}

4.LED函数
void Led_ON(void)
{
  GPIO_ResetBits(GPIOF, GPIO_Pin_9); // 1- ON
}

void Led_OFF(void)
{
  GPIO_SetBits(GPIOF, GPIO_Pin_9); // 0- OFF
}
void handle_Led(u8 ucSwitch, u8 usCnt)
{
if (ucSwitch == ON)
{
  int i;
  for(i = 0; i < usCnt; i++)
  {
    Led_ON();
    delay_ms(1000);
  }
   Led_OFF();
}
else
{
   Led_OFF();
}
}

5.主函数
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
delay_init(168);
uart_init(115200);  
LED_Init();   
EXTIX_Init();   
TIM3_Int_Init(100-1,8400-1); //10ms
while(1)
{
  LED1 = !LED1;
  delay_ms(1000);
}
}

  简单程序,练练手。不知道其他高手有没有其他有效的办法,请分享一下。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
19条回答
jiangyy
2019-07-21 02:37
tgw860910 发表于 2018-10-10 16:59
滴答定时器的调用,在标准库里是这个函数 SysTick_Handler,一般在系统初始化的时候先 SysTick_Config(Sy ...

那不是相当于用一个定时器就可以搞定了,不需要外部中断处理。在定时器中断服务函数里面,我只判断按键是否按下,检测IO口是否一直处于高电平。
u16 ucTimer = 0;
void TIM3_IRQHandler(void)
{
  ucTimer ++;
  if(WAKE_UP)
  {
     if(ucTimer ==300)//3S
    {
     handle_Led(ON,3);
     ucTimer = 0;
    }
  }
}

那就是一直开着定时器,只是用一个全局变量来判断时间是否到了,到了就讲这个全局变量清零,作出灯的操作。和你说的差不多吧?

一周热门 更多>