目录
GPIOX状态的读入之按键实验(战舰开发板V3)
C语言中数据类型的另类表示方式
前提:添加头文件“stm32f10x.h” |
u8 是unsigned char |
u16 是unsigned short |
u32 是unsigned int |
快速添加头文件的方式
代码示例
Buzzer.h
#ifndef _BUZZER_H
#define _BUZZER_H
void BUZZER_Init(void);
#define BUZZER PBout(8)
#endif
Buzzer.c
#include "stm32f10x.h"
#include "buzzer.h"
void BUZZER_Init(void)
{
// 使能时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 端口状态配置
GPIO_InitTypeDef GPIOB_InitStruct;
GPIOB_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIOB_InitStruct.GPIO_Pin = GPIO_Pin_8;
GPIOB_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIOB_InitStruct);
// 初始化端口状态
GPIO_ResetBits(GPIOB, GPIO_Pin_8);
}
Led.c
#ifndef _LED_H
#define _LED_H
#include "stm32f10x.h"
void LED_Init(void);
#define LED0 PBout(5)
#define LED1 PEout(5)
#endif
Led.h
#include "stm32f10x.h"
#include "led.h"
void LED_Init(void)
{
// 使能LED相应引脚的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOE, ENABLE);
// 配置LED引脚的模式
GPIO_InitTypeDef GPIOB_InitStruct, GPIOE_InitStruct;
GPIOE_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIOE_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIOE_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIOB_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
GPIOB_InitStruct.GPIO_Pin = GPIO_Pin_5;
GPIOB_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIOB_InitStruct);
GPIO_Init(GPIOE, &GPIOE_InitStruct);
// 配置LED引脚初始电平
GPIO_SetBits(GPIOB, GPIO_Pin_5);
GPIO_SetBits(GPIOE, GPIO_Pin_5);
}
Key.c
#include "key.h"
#include "stm32f10x.h"
#include "delay.h"
void KEY_Init(void)
{
// key的端口时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE, ENABLE);
// key0-2为上拉输入,key3为下拉输入
GPIO_InitTypeDef GPIOE_InitStruct, GPIOA_InitStruct;
GPIOE_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIOE_InitStruct.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;
GPIOE_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIOA_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
GPIOA_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIOA_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIOA_InitStruct);
GPIO_Init(GPIOE, &GPIOE_InitStruct);
// 输入状态不用初始化引脚
}
u8 Read_Only(u8 Order,u8 State);
u8 KEY_Scan(u8 mode)
{
static u8 Record_Bit[4] = {1,1,1,0};
u8 Record_KEY[4] = {KEY0,KEY1,KEY2,KEY3};
u8 Record_KEYPRESS[] = {KEY0_PRESS,KEY1_PRESS,KEY2_PRESS,KEY3_PRESS};
static u8 Is_continue_pressed = 0;
u8 i = 0;
if(mode == 1) Is_continue_pressed = 1;
if((Is_continue_pressed) && (KEY0 | KEY1 | KEY2 | KEY3))
{
if(!KEY0) return KEY0_PRESS;
else if(!KEY1) return KEY1_PRESS;
else if(!KEY2) return KEY2_PRESS;
else if(KEY3) return KEY3_PRESS;
}
else if((~Is_continue_pressed) && (KEY0 | KEY1 | KEY2 | KEY3))
{
for(i=0; i<4; i++)
{
if(Record_Bit[i] != Record_KEY[i])
{
delay_ms(5);
if(Record_Bit[i] != Record_KEY[i])
{
Record_Bit[i] = Record_KEY[i];
return Record_KEYPRESS[i];
}
}
}
return 0; // 一定要加上
}
}
Key.h
#ifndef _KEY_H
#define _KEY_H
void KEY_Init(void);
#include "stm32f10x.h" // Device header
u8 KEY_Scan(u8 mode);
void KEY_Init(void);
u8 Read_Only(u8 Order,u8 State);
// 预定义按键的输入电平
#define KEY0 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_2)
#define KEY1 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3)
#define KEY2 GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_4)
#define KEY3 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)
// 预定义按键的操作功能
#define NONKEY 0
#define KEY0_PRESS 1
#define KEY1_PRESS 2
#define KEY2_PRESS 3
#define KEY3_PRESS 4
#endif
Main.c
#include "stm32f10x.h"
#include "led.h"
#include "key.h"
#include "buzzer.h"
#include "delay.h"
int main()
{
LED_Init();
delay_init();
BUZZER_Init();
KEY_Init();
while(1)
{
u8 key = KEY_Scan(0);
delay_ms(10);
switch(key)
{
case KEY0_PRESS:
LED0 = !LED0; break;
case KEY1_PRESS:
LED1 = !LED1; break;
case KEY2_PRESS:
BUZZER = !BUZZER; break;
case KEY3_PRESS:
{
LED0 = !LED0;
LED1 = !LED1;
break;
}
}
}
}
支持连续按的按键配置原理
不支持连续按的按键配置原理
按键消抖的方法
连续稳定的状态=按键的真实状态(软件消抖)
只有连续的稳定的状态才可以被当作按键的真实状态。
延迟消抖(软件消抖)
延迟消抖的弊端就在于延迟过程中忽略全部的按键状态,仅仅读取延迟后的按键状态;
延迟消抖的优点就是操作简单。
硬件消抖
硬件消抖可以轻松的去掉按键抖动时产生的高频毛刺,但是成本相应的提高了一些。
STM32是没有硬件消抖的。