代码功能描述
keyrelease.c 是一个基于STM32微控制器和FreeRTOS实时操作系统的按键检测与处理程序。其主要功能是检测多个按键的按下和松开事件,并通过消息队列将按键事件传递给主任务进行处理。以下是代码的详细功能描述:

1. 按键检测 :
   - 检测四个按键的状态: START 、 UP 、 DOWN 和 BTWASH 。
   - 使用GPIO输入模式检测按键的按下和松开事件。
   - 通过状态机机制确保只有在按键松开时才触发事件。
2. 消息队列 :  
   - 使用FreeRTOS的消息队列( xButtonQueue )在任务间传递按键事件。
   - 按键检测任务( ButtonTask )将检测到的按键事件发送到队列。
   - 主任务( MainTask )从队列中接收按键事件并进行处理。
3. 多任务管理 :  
   - 使用FreeRTOS创建两个任务: ButtonTask 和 MainTask 。
   - ButtonTask 负责按键检测,优先级较高(2)。
   - MainTask 负责处理按键事件,优先级较低(1)。
4. 硬件初始化 :
   - 初始化STM32的GPIO引脚,配置为上拉输入模式。
   - 开启GPIOA和GPIOB的时钟。
5. 实时性 :  
   - 按键检测任务每10ms运行一次,确保实时检测按键状态。
   - 使用FreeRTOS的延时函数( vTaskDelay )实现定时检测。

使用方法

1. 硬件连接
- START按键 :连接到GPIOA的Pin 15。
- UP按键 :连接到GPIOB的Pin 5。
- DOWN按键 :连接到GPIOB的Pin 6。
- BTWASH按键 :连接到GPIOB的Pin 8。
- 所有按键的另一端接地,使用上拉输入模式。

2. 代码配置
- FreeRTOS配置 :
  - 确保FreeRTOS的配置文件( FreeRTOSConfig.h )正确设置,包括任务堆栈大小、队列长度等。
- GPIO配置 :
  - 如果需要更改按键引脚,修改 START_PIN 、 UP_PIN 、 DOWN_PIN 和 BTWASH_PIN 的定义。

3. 编译与烧录
- 使用STM32开发环境(如Keil、STM32CubeIDE)编译代码。
- 将编译生成的二进制文件烧录到STM32微控制器中。

4. 运行与调试
- 启动程序后,FreeRTOS调度器会自动运行 ButtonTask 和 MainTask 。
- 按下任意按键, ButtonTask 会检测到松开事件并将其发送到消息队列。
- MainTask 从队列中接收按键事件,并根据按键类型执行相应的处理逻辑。 

5. 扩展与修改
- 添加新按键 :
  1. 在 ButtonType 枚举中添加新按键类型。
  2. 在 ButtonTask 中添加新按键的检测逻辑。
  3. 在 MainTask 的 switch 语句中添加新按键的处理逻辑。
- 修改按键处理逻辑 :
  - 在 MainTask 的 switch 语句中修改对应按键的处理代码。

keyrelease.c
├── 宏定义
│   ├── START_PIN, UP_PIN, DOWN_PIN, BTWASH_PIN
├── 全局变量
│   ├── xButtonQueue (消息队列)
├── 枚举类型
│   ├── ButtonType (按键类型)
├── 任务函数
│   ├── ButtonTask (按键检测任务)
│   ├── MainTask (主任务)
├── 硬件初始化函数
│   ├── Hardware_Init (GPIO初始化)
├── 主函数
│   ├── main (初始化硬件、创建队列和任务、启动调度器)

#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

// 定义按键引脚
#define START_PIN GPIO_Pin_15
#define UP_PIN GPIO_Pin_5
#define DOWN_PIN GPIO_Pin_6
#define BTWASH_PIN GPIO_Pin_8

// 按键队列
QueueHandle_t xButtonQueue;

// 按键枚举
typedef enum {
    BUTTON_START,
    BUTTON_UP,
    BUTTON_DOWN,
    BUTTON_BTWASH,
    BUTTON_NONE
} ButtonType;

// 按键检测任务
void ButtonTask(void *pvParameters) {
    ButtonType button;
    uint8_t start_state = 1, up_state = 1, down_state = 1, btwash_state = 1;
    
    while(1) {
        // 检测按键状态
        uint8_t current_start = GPIO_ReadInputDataBit(GPIOA, START_PIN);
        uint8_t current_up = GPIO_ReadInputDataBit(GPIOB, UP_PIN);
        uint8_t current_down = GPIO_ReadInputDataBit(GPIOB, DOWN_PIN);
        uint8_t current_btwash = GPIO_ReadInputDataBit(GPIOB, BTWASH_PIN);
        
        // 检测START按键按下并松开
        if(start_state && !current_start) { // 按下
            start_state = 0;
        } else if(!start_state && current_start) { // 松开
            start_state = 1;
            button = BUTTON_START;
            xQueueSend(xButtonQueue, &button, 0);
        }
        
        // 检测UP按键按下并松开
        if(up_state && !current_up) {
            up_state = 0;
        } else if(!up_state && current_up) {
            up_state = 1;
            button = BUTTON_UP;
            xQueueSend(xButtonQueue, &button, 0);
        }
        
        // 检测DOWN按键按下并松开
        if(down_state && !current_down) {
            down_state = 0;
        } else if(!down_state && current_down) {
            down_state = 1;
            button = BUTTON_DOWN;
            xQueueSend(xButtonQueue, &button, 0);
        }
        
        // 检测BTWASH按键按下并松开
        if(btwash_state && !current_btwash) {
            btwash_state = 0;
        } else if(!btwash_state && current_btwash) {
            btwash_state = 1;
            button = BUTTON_BTWASH;
            xQueueSend(xButtonQueue, &button, 0);
        }
        
        vTaskDelay(10 / portTICK_PERIOD_MS); // 10ms延时
    }
}

// 主任务
void MainTask(void *pvParameters) {
    ButtonType receivedButton;
    
    while(1) {
        if(xQueueReceive(xButtonQueue, &receivedButton, portMAX_DELAY) == pdPASS) {
            switch(receivedButton) {
                case BUTTON_START:
                    // 处理START按键
                    break;
                case BUTTON_UP:
                    // 处理UP按键
                    break;
                case BUTTON_DOWN:
                    // 处理DOWN按键
                    break;
                case BUTTON_BTWASH:
                    // 处理BTWASH按键
                    break;
                default:
                    break;
            }
        }
    }
}

// 硬件初始化
void Hardware_Init(void) {
    GPIO_InitTypeDef GPIO_InitStructure;
    
    // 开启GPIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
    
    // 配置START按键(PA15)
    GPIO_InitStructure.GPIO_Pin = START_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    // 配置UP(PB5)、DOWN(PB6)、BTWASH(PB8)按键
    GPIO_InitStructure.GPIO_Pin = UP_PIN | DOWN_PIN | BTWASH_PIN;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

int main(void) {
    // 硬件初始化
    Hardware_Init();
    
    // 创建按键队列
    xButtonQueue = xQueueCreate(10, sizeof(ButtonType));
    
    // 创建任务
    xTaskCreate(ButtonTask, "ButtonTask", configMINIMAL_STACK_SIZE, NULL, 2, NULL);
    xTaskCreate(MainTask, "MainTask", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    
    // 启动调度器
    vTaskStartScheduler();
    
    while(1);
}

Logo

「智能机器人开发者大赛」官方平台,致力于为开发者和参赛选手提供赛事技术指导、行业标准解读及团队实战案例解析;聚焦智能机器人开发全栈技术闭环,助力开发者攻克技术瓶颈,促进软硬件集成、场景应用及商业化落地的深度研讨。 加入智能机器人开发者社区iRobot Developer,与全球极客并肩突破技术边界,定义机器人开发的未来范式!

更多推荐