文章目录
main.c
#include "stm32f10x.h" // Device header
#include "Key.h"
#include "LED.h"
#include "Timer.h"int main(void)
{Timer_Init();//1msLED_Init();Key_Init();while(1){switch(KeyFlag)//按键短按,按下即可开始实现功能,不用松手{case KEY0_PRES://1LED_Green=!LED_Green;KeyFlag = 0;//注意按键标志清零,防止程序跑飞break;case KEY1_PRES://2Beep =!Beep;KeyFlag = 0;//注意按键标志清零,防止程序跑飞break;default:break;}if(BEEP_TIME==500)//500ms执行一次{LED_Red =!LED_Red;BEEP_TIME =0;}}
}
sys.c
sys.h
#ifndef __SYS_H
#define __SYS_H
#include "stm32f10x.h"//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(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 Key3 PEin(6)#define KEY ((Key0) && (Key1))//两个条件都为真时结果才为真,否则为假,我们按键只能按一个,无法同时按,人手速度没有这么快,所以始终无论哪个按键按下KEY都是0
#define KEY0_PRES 1
#define KEY1_PRES 2
extern volatile uint8_t KeyFlag; //按键标志
void Key_Init(void);
void Key_Scan(void); /*按键扫描函数*/#endif
Key.c
#include "stm32f10x.h" // Device header
#include "Key.h"
typedef enum//按键状态
{KEY_CHECK =0,//检测KEY_CONFIRM = 1,//确认KEY_RELEASE = 2//释放
}KEY_STATE;KEY_STATE KeyState = KEY_CHECK; //初始化按键状态为检测状态,KeyState是变量,KEY_CHECK是数值,初始化为0
volatile uint8_t KeyFlag = 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);
}void Key_Scan(void)
{switch(KeyState)//按键状态KeyState为0,1,2其中一个{case KEY_CHECK://按键状态:0if(!KEY)//如果按键值为0,说明按键被按下,切换状态,if是为1才能进入,按键按下了变为0,反转为1才进入{KeyState = KEY_CONFIRM;//按键状态从0切换为1}break;case KEY_CONFIRM://按键状态:1if(!KEY)//判断当前按键值是否为0,确认是否按下{KeyState = KEY_RELEASE;//按键状态从1切换为2if(0 == Key0)//KEY0被按下{KeyFlag = KEY0_PRES;//KEY0_PRES=1,KeyFlag=1}if(0 == Key1)//KEY1被按下{KeyFlag = KEY1_PRES;//KEY1_PRES=2,KeyFlag=2}}else//按键没有被按下,返回上一状态{KeyState = KEY_CHECK;}break;case KEY_RELEASE://按键状态:2if(KEY)//当前按键值为1,说明按键已经释放,切换到开始状态{KeyState = KEY_CHECK;//按键状态从2切换为0,以便下一次使用}break;default:break;}
}
Timer.h
#ifndef __TIMER_H
#define __TIMER_H
#include "stm32f10x.h" // Device headerextern 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 ==10)//20ms进入检测按键一次{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);
}