一、模块
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);
}
四、总结
哈哈,很神奇!长短按键的检测,但其实原理我没有很懂,是参考别人的。而且,按键检测有点类似于用轮询的方式,不是完全的中断应该。