main.c
#include "stm32f10x.h" // Device header
#include "Key.h"
#include "LED.h"
#include "Timer.h"
int main(void)
{
Timer_Init();//1ms
LED_Init();
Key_Init();
while(1)
{
switch(KeyFlag)//按下松手即可开始实现功能
{
case KEY0_PRES://1
LED_Green=!LED_Green;
KeyFlag = 0;//注意按键标志清零,防止程序跑飞
break;
}
if(BEEP_TIME>=500)//这里必须写大于,按的某个时刻有可能计数值大于500,这里是定时器计时实现亮灭
{
LED_Red =!LED_Red;
BEEP_TIME =0;
}
}
}
sys.c
sys.h
#ifndef __SYS_H
#define __SYS_H
#include "stm32f10x.h"
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//IO口地址映射
#define GPIOA_ODR_Addr (GPIOA_BASE+12) //0x4001080C
#define GPIOB_ODR_Addr (GPIOB_BASE+12) //0x40010C0C
#define GPIOC_ODR_Addr (GPIOC_BASE+12) //0x4001100C
#define GPIOD_ODR_Addr (GPIOD_BASE+12) //0x4001140C
#define GPIOE_ODR_Addr (GPIOE_BASE+12) //0x4001180C
#define GPIOF_ODR_Addr (GPIOF_BASE+12) //0x40011A0C
#define GPIOG_ODR_Addr (GPIOG_BASE+12) //0x40011E0C
#define GPIOA_IDR_Addr (GPIOA_BASE+8) //0x40010808
#define GPIOB_IDR_Addr (GPIOB_BASE+8) //0x40010C08
#define GPIOC_IDR_Addr (GPIOC_BASE+8) //0x40011008
#define GPIOD_IDR_Addr (GPIOD_BASE+8) //0x40011408
#define GPIOE_IDR_Addr (GPIOE_BASE+8) //0x40011808
#define GPIOF_IDR_Addr (GPIOF_BASE+8) //0x40011A08
#define GPIOG_IDR_Addr (GPIOG_BASE+8) //0x40011E08
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n) BIT_ADDR(GPIOA_ODR_Addr,n) //输出
#define PAin(n) BIT_ADDR(GPIOA_IDR_Addr,n) //输入
#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出
#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入
#define PCout(n) BIT_ADDR(GPIOC_ODR_Addr,n) //输出
#define PCin(n) BIT_ADDR(GPIOC_IDR_Addr,n) //输入
#define PDout(n) BIT_ADDR(GPIOD_ODR_Addr,n) //输出
#define PDin(n) BIT_ADDR(GPIOD_IDR_Addr,n) //输入
#define PEout(n) BIT_ADDR(GPIOE_ODR_Addr,n) //输出
#define PEin(n) BIT_ADDR(GPIOE_IDR_Addr,n) //输入
#define PFout(n) BIT_ADDR(GPIOF_ODR_Addr,n) //输出
#define PFin(n) BIT_ADDR(GPIOF_IDR_Addr,n) //输入
#define PGout(n) BIT_ADDR(GPIOG_ODR_Addr,n) //输出
#define PGin(n) BIT_ADDR(GPIOG_IDR_Addr,n) //输入
#endif
Key.h
#ifndef __KEY_H
#define __KEY_H
#include "stm32f10x.h" // Device header
#include "sys.h"
#define Key0 PEin(4)
#define Key1 PEin(3)
#define Key2 PEin(2)
#define KEY ((Key0) && (Key1) && (Key2))//两个条件都为真时结果才为真,否则为假,我们按键只能按一个,无法同时按,人手速度没有这么快,所以始终无论哪个按键按下KEY都是0
#define KEY0_PRES 1
#define KEY1_PRES 2
#define KEY2_PRES 3
extern uint8_t KeyFlag; //按键标志
void Key_Init(void);
uint8_t Key_Scan(void); /*按键扫描函数*/
#endif
Key.c
#include "stm32f10x.h" // Device header
#include "Key.h"
uint8_t KeyFlag = 0; //按键标志
typedef enum//按键状态
{
KEY_CHECK =0,//检测
KEY_CONFIRM = 1,//确认
KEY_RELEASE = 2//释放
}KEY_STATE;
KEY_STATE KeyState = KEY_CHECK; //初始化按键状态为检测状态,KeyState是变量,KEY_CHECK是数值,初始化为0
void Key_Init()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_6;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStruct);
}
uint8_t Key_Scan(void)
{
static uint8_t KeyFlag = 0; //按键标志
switch(KeyState)//按键状态KeyState为0,1,2其中一个
{
case KEY_CHECK://按键状态:0
if(!KEY)//如果按键值为0,说明按键被按下,切换状态,if是为1才能进入,按键按下了变为0,反转为1才进入
{
KeyState = KEY_CONFIRM;//按键状态从0切换为1
}
break;
case KEY_CONFIRM://按键状态:1
if(!KEY)//判断当前按键值是否为0,确认是否按下
{
KeyState = KEY_RELEASE;//按键状态从1切换为2
if(0 == Key0)//KEY0被按下
{
KeyFlag = KEY0_PRES;//KEY0_PRES=1,KeyFlag=1
}
if(0 == Key1)//KEY1被按下
{
KeyFlag = KEY1_PRES;//KEY1_PRES=2,KeyFlag=2
}
if(0 == Key2)//KEY2被按下
{
KeyFlag = KEY2_PRES;//KEY2_PRES=3,KeyFlag=3
}
}
else//按键没有被按下,返回上一状态
{
KeyState = KEY_CHECK;
}
break;
case KEY_RELEASE://按键状态:2
if(KEY)//当前按键值为1,说明按键已经释放,切换到开始状态
{
KeyState = KEY_CHECK;//按键状态从2切换为0,以便下一次使用
return KeyFlag;//释放以后才把按键数值返回
}
break;
}
return 0;
}
Timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "stm32f10x.h" // Device header
extern volatile uint32_t global_times;
extern volatile uint32_t BEEP_TIME;
void Timer_Init(void);
#endif
Timer.c
#include "stm32f10x.h" // Device header
#include "LED.h"
#include "Key.h"
volatile uint32_t global_times = 0;
volatile uint32_t BEEP_TIME = 0;
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 1000 - 1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM4, ENABLE);
}
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)//1ms
{
global_times++;
BEEP_TIME ++;
if(global_times ==20)//20ms进入检测按键一次
{
KeyFlag =Key_Scan();
global_times=0;
}
TIM_ClearITPendingBit(TIM4, TIM_IT_Update);
}
}
LED.h
#ifndef __LED_H
#define __LED_H
#include "sys.h"
void LED_Init(void);
#define LED_Red PBout(5)
#define LED_Green PEout(5)
#define Beep PCout(12)
#endif
LED.c
#include "stm32f10x.h" // Device header
#include "LED.h"
void LED_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB,&GPIO_InitStruct);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_12;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOC,&GPIO_InitStruct);
GPIO_SetBits(GPIOC,GPIO_Pin_12);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOE,&GPIO_InitStruct);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
}