蓝桥杯嵌入式—基础模块:LED+KEY长短+TIM4定时

一、模块
LED+KEY长短+TIM4定时
二、实现功能
短按KEY1,点亮LED1;长按KEY1,熄灭LED1。
三、代码
1.初始化代码
tx.c

#include "tx.h"

void LED_Init(void){
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOD, ENABLE);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOD, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = 0xff00;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  GPIO_Init(GPIOC, &GPIO_InitStructure);

  GPIOD->ODR|=(1<<2);
  GPIOC->ODR|=0xff00;
  GPIOD->ODR&=~(1<<2); 
}

void KEY_Init(void){
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB, ENABLE);
  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_8;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
}

u8 key_status[4]={1,1,1,1};
u16 key_downtime[4]={0,0,0,0};

void KEY_Driver(void){
  u8 i;
  static u8 backup[4]={1,1,1,1};
  static u16 timethr[4]={1000,1000,1000,1000};
  for(i=0;i<4;i++){
    if(backup[i]!=key_status[i]){
	  if(backup[i]!=0){
	  	Key_action(i+1,0);
	  }
	  backup[i]=key_status[i];
	}
	if(key_downtime[i]>0){
	  if(key_downtime[i]>timethr[i]){
	  	Key_action(i+1,1);
	  	timethr[i]+=200;
	  }
	}
	else
	  timethr[i]=1000;    
  }	
}

void KEY_Scan(void){
  u8 i;
  static u8 key_buf[4]={0xff,0xff,0xff,0xff};
  key_buf[0]=(key_buf[0]<<1)|KEY1;
  key_buf[1]=(key_buf[1]<<1)|KEY2;
  key_buf[2]=(key_buf[2]<<1)|KEY3;
  key_buf[3]=(key_buf[3]<<1)|KEY4;

  for(i=0;i<4;i++){
    if(key_buf[i]==0x00){
	  key_status[i]=0;
	  key_downtime[i]+=4;
	}
	else if(key_buf[i]==0xff){
	  key_status[i]=1;
	  key_downtime[i]=0;
	}
  }
}

void Tim4_Init(u16 arr,u16 psc){
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  NVIC_InitTypeDef NVIC_InitStructure;	

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);

  NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;	
  NVIC_Init(&NVIC_InitStructure);

  TIM_TimeBaseStructure.TIM_Period = arr-1;
  TIM_TimeBaseStructure.TIM_Prescaler = psc-1;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;	
  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
  TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);

  /* TIM2 enable counter */
  TIM_Cmd(TIM4, ENABLE);   

}

tx.h

/*
  程序说明: CT117E嵌入式竞赛板LCD驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT117E嵌入式竞赛板
  日    期: 2011-8-9
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __TX_H
#define __TX_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

#define KEY1 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)
#define KEY2 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8)
#define KEY3 GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1)
#define KEY4 GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_2)

void LED_Init(void);
void KEY_Init(void);
void KEY_Driver(void);
void KEY_Scan(void);
void Tim4_Init(u16 arr,u16 psc);

extern void Key_action(int code,u8 sta);


#endif /* __TX_H */

/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/

2.中断函数
stm32f10x_it.c

extern u8 ms200_flag;
void TIM4_IRQHandler(void)
{
  static u8 ms200_count=0;
  if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
  {
    TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
	KEY_Scan();
	ms200_count++;
	if(ms200_count>=100){
	  ms200_count=0;
	  ms200_flag=1;
	}
  }
}

3.主函数
main.c

#include "stm32f10x.h"
#include "lcd.h"
#include "tx.h"

u32 TimingDelay = 0;

u8 ms200_flag=1;

void Delay_Ms(u32 nTime);

//Main Body
int main(void)
{
	SysTick_Config(SystemCoreClock/1000);

	Delay_Ms(200);
	
	STM3210B_LCD_Init();
	LCD_Clear(Blue);
	LCD_SetBackColor(Blue);
	LCD_SetTextColor(White);
	
	LED_Init();
	KEY_Init();
	Tim4_Init(2000,72);
	
	while(1){
	   KEY_Driver();
	
	}
}

void Key_action(int code,u8 sta){
  if(code==1){
    if(sta==0){	   //短按 开灯
	  GPIOC->ODR&=~(1<<8);
	  GPIOD->ODR|=(1<<2); 	  
	  GPIOD->ODR&=~(1<<2);
	}
	else if(sta==1){	   //长按关灯
	  GPIOC->ODR|=(1<<8);
	  GPIOD->ODR|=(1<<2); 	  
	  GPIOD->ODR&=~(1<<2);
	}
  }

}
void Delay_Ms(u32 nTime)
{
	TimingDelay = nTime;
	while(TimingDelay != 0);	
}

四、总结
哈哈,很神奇!长短按键的检测,但其实原理我没有很懂,是参考别人的。而且,按键检测有点类似于用轮询的方式,不是完全的中断应该。

发布了27 篇原创文章 · 获赞 10 · 访问量 2953

猜你喜欢

转载自blog.csdn.net/fancyZT/article/details/105386426