stm32安富莱BSP学习(按键驱动)

目录

1 学习架构的设计

1.1 函数设计

1.1  宏定义

1.3 按键ID结构体

1.4 按键对象结构体定义

1.5 fifo对象结构体定义                                                                                                              

1.6 按键码值定义

2 移植

2.1 硬件连接

2.2  宏与变量的分析

2.2.1  引脚宏定义

2.2.2 按键函数 

3 函数分析

3.1 判断按键是否按下函数

3.2 FIFO的原理

3.3 按键初始化变量

3.4 FIFO压入键值函数

3.5 FIFO读取函数

3.6 FIFO读取函数 单独指针

3.7 清空按键FIFO

3.8 按键GPIO初始化

3.9 扫描按键(很重要)

3.10 扫描按键函数


如果不想看的可以直接使用git把我的代码下载出来,里面工程挺全的,后期会慢慢的补注释之类的

stm32学习笔记: stm32学习笔记源码 (gitee.com)(出差是公司电脑改的代码,有锁所以不能上传,只能回去了拿自己电脑上传了)

如果不会使用git快速下载可以选择直接下载压缩包或者去看看git的使用

git的使用git的使用(下载及上传_gitcode怎么下载代码-优快云博客

有错误的地方欢迎大家多多指出,方便我修改错误,以及提升自己

然后定时器中断的部分需要看的话链接如下,只想直接用的话可以不用管:
stm32安富莱串口FIFO-优快云博客                        

1 学习架构的设计

首先看一下结构设计:写的安富莱BSP设计文章,基本都是我拿来学习架构设计思想和c函数写法的。

首先直接看.h文件吧,一般架构都是直接搭的,h文件,从上到下,每段代码都会写的

1.1 函数设计

先看一下函数有哪些

/* 供外部调用的函数声明 */
void bsp_InitKey(void);
void bsp_KeyScan(void);
void bsp_PutKey(uint8_t _KeyCode);
uint8_t bsp_GetKey(void);
uint8_t bsp_GetKey2(void);
uint8_t bsp_GetKeyState(KEY_ID_E _ucKeyID);
void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t  _RepeatSpeed);
void bsp_ClearKey(void);

1 、应该是init整个的初始化函数    2 、按键扫描函数 

3 、fifo压入键值函数  这里有个形参   ,应该是通过这个参数来判断是哪个按键被按下了

4 、读取按键函数  5 读取按键函数2 

 6 、获取按键状态   这个类型是一个结构体的形参,传入按键的ID号,将按键操作抽象为一个结构体,里面带有当前按键状态的参数,可以直接通过参数来判断是否按下。

7、设置按键参数通过id号来更改长按时间设置,以及连发设置

8、清除按键值

1.1  宏定义

首先是设定了一下按键的最大个数:这个个数用来判断是哪个按键的时候很好用。

#define KEY_COUNT    10	   					/* 按键个数, 8个独立建 + 2个组合键 */

之后是一些按键的宏定义,在判断哪个按键按下时,可以直接用宏来写,这样提高可读性


/* 根据应用程序的功能重命名按键宏 */
#define KEY_DOWN_K1		KEY_1_DOWN
#define KEY_UP_K1		KEY_1_UP
#define KEY_LONG_K1		KEY_1_LONG

#define KEY_DOWN_K2		KEY_2_DOWN
#define KEY_UP_K2		KEY_2_UP
#define KEY_LONG_K2		KEY_2_LONG

#define KEY_DOWN_K3		KEY_3_DOWN
#define KEY_UP_K3		KEY_3_UP
#define KEY_LONG_K3		KEY_3_LONG

#define JOY_DOWN_U		KEY_4_DOWN		/* 上 */
#define JOY_UP_U		KEY_4_UP
#define JOY_LONG_U		KEY_4_LONG

#define JOY_DOWN_D		KEY_5_DOWN		/* 下 */
#define JOY_UP_D		KEY_5_UP
#define JOY_LONG_D		KEY_5_LONG

#define JOY_DOWN_L		KEY_6_DOWN		/* 左 */
#define JOY_UP_L		KEY_6_UP
#define JOY_LONG_L		KEY_6_LONG

#define JOY_DOWN_R		KEY_7_DOWN		/* 右 */
#define JOY_UP_R		KEY_7_UP
#define JOY_LONG_R		KEY_7_LONG

#define JOY_DOWN_OK		KEY_8_DOWN		/* ok */
#define JOY_UP_OK		KEY_8_UP
#define JOY_LONG_OK		KEY_8_LONG

#define SYS_DOWN_K1K2	KEY_9_DOWN		/* K1 K2 组合键 */
#define SYS_UP_K1K2	    KEY_9_UP
#define SYS_LONG_K1K2	KEY_9_LONG

#define SYS_DOWN_K2K3	KEY_10_DOWN		/* K2 K3 组合键 */
#define SYS_UP_K2K3  	KEY_10_UP
#define SYS_LONG_K2K3	KEY_10_LONG

1.3 按键ID结构体

然后定义了一个按键的结构体,里面写了各个按键的名称,用来检测按键是否按下。

/* 按键ID, 主要用于bsp_KeyState()函数的入口参数 */
typedef enum
{
	KID_K1 = 0,
	KID_K2,
	KID_K3,
	KID_JOY_U,
	KID_JOY_D,
	KID_JOY_L,
	KID_JOY_R,
	KID_JOY_OK
}KEY_ID_E;
/*
	按键滤波时间50ms, 单位10ms。
	只有连续检测到50ms状态不变才认为有效,包括弹起和按下两种事件
	即使按键电路不做硬件滤波,该滤波机制也可以保证可靠地检测到按键事件
*/
#define KEY_FILTER_TIME   5
#define KEY_LONG_TIME     100			/* 单位10ms, 持续1秒,认为长按事件 */

之后写了两个define  一个是滤波时间,一个是判断长按时间(因为最后的按键函数是被10ns中断调用的,所以这里的单位是10ms)。

1.4 按键对象结构体定义

/*
	每个按键对应1个全局的结构体变量。
*/
typedef struct
{
	/* 下面是一个函数指针,指向判断按键手否按下的函数 */
	uint8_t (*IsKeyDownFunc)void); /* 按键按下的判断函数,1表示按下 */

	uint8_t  Count;			/* 滤波器计数器 */
	uint16_t LongCount;		/* 长按计数器 */
	uint16_t LongTime;		/* 按键按下持续时间, 0表示不检测长按 */
	uint8_t  State;			/* 按键当前状态(按下还是弹起) */
	uint8_t  RepeatSpeed;	/* 连续按键周期 */
	uint8_t  RepeatCount;	/* 连续按键计数器 */
}KEY_T;

上面是一个按键的结构体:里面有一些按键的基本特征(然后就是面向对象,把对象的特征描述出来,尽量可复用),

最开始是一个函数指针,用来存放每个按键的判断函数。

首先两个计数器:一个滤波的,一个长按计数的。之后是一个长按计数时间,当长按时间>=了长按时间后才能判断为长按了,之后是一个按键状态,按下为1弹起为0。

之后一个是连续周期,一个是连续按键计数器  :这两个东西我没理解用途,后面具体写代码的时候再说了。

1.5 fifo对象结构体定义                                                                                                                        

/* 按键FIFO用到变量 */
#define KEY_FIFO_SIZE	10
typedef struct
{
	uint8_t Buf[KEY_FIFO_SIZE];		/* 键值缓冲区 */
	uint8_t Read;					/* 缓冲区读指针1 */
	uint8_t Write;					/* 缓冲区写指针 */
	uint8_t Read2;					/* 缓冲区读指针2 */
}KEY_FIFO_T;

之后构体对象,一个是fifo的结构体,fifo原理后面写了哦不了解的可以跳到fifo的原理那一节看看。

1  就是一个值的缓冲区,后面写FIFO的时候大家对照看,2 读指针  3写指针 

4 读指针2   在某些情况下,可能有两个任务都需要访问按键缓冲区,为了避免键值被其中一个任务取空,我们添加了第2个读指针Read2。

1.6 按键码值定义

之后是按键的码值,把所有按键的码值枚举出来,通过轮训来判断是否有按键按下了,如果按下,就把变量直接压入fifo,弹起来了也是同理。

/*
	定义键值代码, 必须按如下次序定时每个键的按下、弹起和长按事件

	推荐使用enum, 不用#define,原因:
	(1) 便于新增键值,方便调整顺序,使代码看起来舒服点
	(2) 编译器可帮我们避免键值重复。
*/
typedef enum
{
	KEY_NONE = 0,			/* 0 表示按键事件 */

	KEY_1_DOWN,				/* 1键按下 */
	KEY_1_UP,				/* 1键弹起 */
	KEY_1_LONG,				/* 1键长按 */

	KEY_2_DOWN,				/* 2键按下 */
	KEY_2_UP,				/* 2键弹起 */
	KEY_2_LONG,				/* 2键长按 */

	KEY_3_DOWN,				/* 3键按下 */
	KEY_3_UP,				/* 3键弹起 */
	KEY_3_LONG,				/* 3键长按 */

	KEY_4_DOWN,				/* 4键按下 */
	KEY_4_UP,				/* 4键弹起 */
	KEY_4_LONG,				/* 4键长按 */

	KEY_5_DOWN,				/* 5键按下 */
	KEY_5_UP,				/* 5键弹起 */
	KEY_5_LONG,				/* 5键长按 */

	KEY_6_DOWN,				/* 6键按下 */
	KEY_6_UP,				/* 6键弹起 */
	KEY_6_LONG,				/* 6键长按 */

	KEY_7_DOWN,				/* 7键按下 */
	KEY_7_UP,				/* 7键弹起 */
	KEY_7_LONG,				/* 7键长按 */

	KEY_8_DOWN,				/* 8键按下 */
	KEY_8_UP,				/* 8键弹起 */
	KEY_8_LONG,				/* 8键长按 */

	/* 组合键 */
	KEY_9_DOWN,				/* 9键按下 */
	KEY_9_UP,				/* 9键弹起 */
	KEY_9_LONG,				/* 9键长按 */

	KEY_10_DOWN,			/* 10键按下 */
	KEY_10_UP,				/* 10键弹起 */
	KEY_10_LONG,			/* 10键长按 */
}KEY_ENUM;

2 移植

2.1 硬件连接

确定自己板子的硬件连接,到时候好更改代码

我这里两个按键都是高有效的。 引脚为PA6 与PC13

2.2  宏与变量的分析

2.2.1  引脚宏定义

/*
	安富莱STM32-V4 按键口线分配:
		K1 键      : PC13   (低电平表示按下)
		K2 键      : PA0    ( --- 高电平表示按下)
		K3 键      : PG8    (低电平表示按下)
		摇杆UP键   : PG15   (低电平表示按下)
		摇杆DOWN键 : PD3    (低电平表示按下)
		摇杆LEFT键 : PG14   (低电平表示按下)
		摇杆RIGHT键: PG13   (低电平表示按下)
		摇杆OK键   : PG7    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值