目录
如果不想看的可以直接使用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