添加gpio_key

This commit is contained in:
RB 2025-05-24 15:33:24 +08:00
parent 37d6f70055
commit 3da80d5efb
9 changed files with 163 additions and 105 deletions

BIN
.DS_Store vendored

Binary file not shown.

BIN
User/.DS_Store vendored

Binary file not shown.

BIN
User/bsp/.DS_Store vendored

Binary file not shown.

View File

@ -6,6 +6,7 @@
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
static uint32_t led_stats; // 使用位掩码记录每个通道的状态最多支持32LED

View File

@ -2,7 +2,7 @@
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "gpio.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */

BIN
User/device/.DS_Store vendored

Binary file not shown.

View File

@ -1,86 +1,65 @@
/* Includes ----------------------------------------------------------------- */
#include "key_gpio.h"
#include "device.h"
#include <gpio.h>
#include "bsp/gpio_exti.h"
#include "gpio.h"
/* Private define ----------------------------------------------------------- */
#define DEBOUNCE_TIME_MS 20
/* Private macro ------------------------------------------------------------ */
/* Private typedef ---------------------------------------------------------- */
/* Private variables -------------------------------------------------------- */
/* Private function -------------------------------------------------------- */
/* 外部声明标志位(标志位) */
volatile uint8_t key_flag = 0; // 1=按下0=松开
volatile uint8_t key_exti = 0;
volatile uint8_t key_pressed = 0; // 全局标志位
static uint32_t last_debounce_time = 0; // 消抖
static uint32_t key_stats; // 使用位掩码记录每个通道的状态最多支持32LED
/* Private function -------------------------------------------------------- */
static void KEY_Interrupt_Callback(void) {
// 切换标志位状态
/* 外部声明标志位(标志问) */
extern volatile uint8_t key_flag; // 1=按下0=松开
key_flag = !key_flag;
key_exti = 1;
/* 按键状态结构 */
typedef struct {
uint16_t state; // 当前状态
uint32_t press_timestamp; // 按下时间戳
uint8_t last_flag; // 上一次的标志位(用于消抖)
} Key_Status_t;
}
static Key_Status_t key = {
.state = DEVICE_KEY_RELEASED,
.press_timestamp = 0,
.last_flag = 0
};
/* 按键中断处理 */
void Key_Process(void) {
uint32_t now = HAL_GetTick();
uint8_t current_flag = key_flag; // 获取当前标志位
switch(key.state) {
case DEVICE_KEY_RELEASED:
if(current_flag == 1) {
// 首次检测到按下,记录时间戳
if(key.last_flag == 0) {
key.press_timestamp = now;
}
// 消抖确认20ms后仍为按下
if((now - key.press_timestamp) > 20) {
key.state = DEVICE_KEY_PRESSED;
}
}
break;
case DEVICE_KEY_PRESSED:
case DEVICE_KEY_LONG_PRESS:
if(current_flag == 1) {
// 持续按住超过20ms进入HOLD状态
if((now - key.press_timestamp) > 20) {
key.state = DEVICE_KEY_LONG_PRESS;
}
} else {
key.state = DEVICE_KEY_RELEASED; // 松开复位
}
break;
}
key.last_flag = current_flag; // 更新历史状态
}
//获取当前按键状态
uint16_t Get_Key_State(void) {
return key.state;
}
//也许是后续逻辑(跟在前面的代码后面放在循环里)
void KeyTask(void)
/* Exported functions ------------------------------------------------------- */
void KEY_Process(void)
{
//仅按下就执行逻辑
// if( key.state == DEVICE_KEY_PRESSED)
// {
// //循环执行逻辑(按下)
// }
//按住才执行逻辑,松开就停下
if (key.state == DEVICE_KEY_LONG_PRESS)
BSP_GPIO_RegisterCallback(BSP_GPIO_USER_KEY, BSP_GPIO_EXTI_CB, KEY_Interrupt_Callback);
if(key_exti == 1)
{
//执行逻辑
}
else if (key.state == DEVICE_KEY_RELEASED)
uint32_t now = HAL_GetTick();
// 检查是否超过消抖时间
if ((now - last_debounce_time) > DEBOUNCE_TIME_MS) {
// 更新有效状态(假设按下为低电平)
if(key_flag == 0)
{
key_pressed = DEVICE_KEY_RELEASED;
}
if(key_flag == 1)
{
key_pressed = DEVICE_KEY_PRESSED;
}
}
else
{
HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6);
}
last_debounce_time = now; // 重置消抖计时器
key_exti = 0;
}
else
{
//停止逻辑
}
}
}
uint8_t KEY_Get_State(void) {
return key_pressed;
}

View File

@ -1,9 +1,9 @@
#pragma once
#ifndef KEY_GPIO_H
#define KEY_GPIO_H
/* Includes ----------------------------------------------------------------- */
#include <stdint.h>
#include "main.h"
//#include "key_gpio.h"
/* Exported constants ------------------------------------------------------- */
/* Exported macro ----------------------------------------------------------- */
/* Exported types ----------------------------------------------------------- */
@ -13,26 +13,9 @@ typedef enum
{
DEVICE_KEY_RELEASED, //按键释放
DEVICE_KEY_PRESSED, //按键按下
DEVICE_KEY_LONG_PRESS, //按键长按
} DEVICE_KEY_Status_t;
void KEY_Process(void);
uint8_t KEY_Get_State(void);
/* 按键通道定义 */
typedef enum {
DEVICE_KEY_1,
DEVICE_KEY_2,
/* 可根据需要扩展 */
DEVICE_KEY_COUNT
} DEVICE_Key_Channel_t;
/* 按键硬件配置结构体 */
typedef struct {
GPIO_TypeDef *port; // GPIO端口
uint16_t pin; // 引脚编号
uint8_t active_level; // 有效电平GPIO_PIN_SET/RESET
uint32_t trigger_edge; // 中断触发边沿RISING/FALLING
} DEVICE_Key_Config_t;
void Key_Process(void);
uint16_t Get_Key_State(void);
void KeyTask(void);
#endif

View File

@ -1,10 +1,105 @@
# BSP
按照规范开发
# component
按照规范开发
# develop
按照规范开发
# module
按照规范开发
# task
按照规范开发
# 嵌入式 代码
## 软件功能介绍
中心思想:
- 利用好RTOS和中断释放CPU性能保证实时性。
- 一个项目适配不同型号的机器人和不同的操作手。
减少维护的工作量,减少出错的可能性。
## 依赖&环境
- Windows平台下用CubeMX生成项目然后用Keil uvesrion进行编辑、烧写和调试。
## 使用说明
- 环境安装
- [MDK-ARM](https://www.keil.com/) (必备)
- [STM32CubeMX](https://www.st.com/zh/development-tools/stm32cubemx.html) (可选)
- 针对不同板子需要到不同的CubeMX工程文件DevA.ioc、DevC.ioc
- 可选利用CubeMX生成对应的外设初始化代码和Keil工程文件。忽略CAN总线相关错误。
- 每次生成代码后请利用Git丢弃Middlewares文件夹中的所有改变。原因如下。
1. 使用了AC6与CubeMX默认不匹配会影响到FreeRTOS的移植。
2. 使用了比CubeMX更新的FreeRTOS版本降版本会导致部分代码无法编译。
- 因为已经生成过Keil工程文件所以只会覆盖以前生成的代码而不会影响手写的代码。
- 每次生成代码后请在HAL_InitTick函数中添加uwTickPrio = TickPriority;
- 打开MDK-ARM中的DevC.uvprojx即可进行编辑、烧写或调试。
- Keil工程中有两个Target其中Debug用来调试不包含编译器优化等DevC/DevA用来编译输出最终固件。
## 文件目录结构&文件用途说明
| 文件夹 | 来源 | 内容 |
| ---- | ---- | ---- |
| Core | CubeMX | 包含核心代码,外设初始化,系统初始化等 |
| Doc | 开发者 | 文档 |
| Drivers | CubeMX | CMSIS相关库、STM32 HAL |
| Image | 开发者 | 图片 |
| MDK-ARM | CubeMX | Keil uversion 项目相关文件 |
| Middlewares | 开发者 / CubeMX | 中间件 |
| USB_DEVICE | CubeMX | USB相关文件 |
| User | 开发者 | 手动编写的代码 |
| Utils | 开发者 | 使用到的工具如CubeMonitor, Matlab |
| User内 | 内容 |
| ---- | ---- |
| bsp | 文件夹内包含开发板信息基于STM32 HAL对板载的外设进行控制|
| component | 包含各种组件,自成一体,相互依赖,但不依赖于其他文件夹|
| device | 独立于开发板的设备依赖于HAL和bsp|
| module | 对机器人各模块的抽象,各模块一起组成机器人|
| task | 独立的任务module的运行容器也包含通信、姿态解算等 |
## 系统介绍
### 硬件系统框图
| ![步兵嵌入式硬件框图](./Image/步兵嵌入式硬件框图.png?raw=true "步兵嵌入式硬件框图") |
|:--:|
| *步兵嵌入式硬件框图* |
### 软件流程图
| ![步兵嵌入式硬件框图](./Image/嵌入式程序流程图.png?raw=true "步兵嵌入式硬件框图") |
|:--:|
| *步兵嵌入式硬件框图* |
| ![嵌入式程序结构图](./Image/嵌入式程序结构图.png?raw=true "嵌入式程序结构图") |
|:--:|
| *嵌入式程序结构图* |
## 原理介绍
### 云台控制原理
| ![云台控制原理与PX类似](./Image/云台控制原理.png?raw=true "嵌入式程序结构图") |
|:--:|
| *云台控制原理与PX类似* |
### 其他参考文献
- 软件架构参考[PX4 Architectural Overview](https://dev.px4.io/master/en/concept/architecture.html)
- 云台控制参考[PX4 Controller Diagrams](https://dev.px4.io/master/en/flight_stack/controller_diagrams.html)
- 底盘Mixer和CAN的Control Group参考[PX4 Mixing and Actuators](https://dev.px4.io/master/en/concept/mixing.html)
## TODO
- 给BSP USB print加保护允许不同进程的使用。
- 给所有BSP加保护
- device.c里面加上一个Device_Init()在里面初始化所有mutex
- CAN设备代码优化。消息解析发送方向。
- CAN设备动态初始化保存好几组配置。
## Roadmap
1. 在步兵上完成所有功能。