当前位置: 首页 > news >正文

通用外设驱动模型(四步法)

在这里插入图片描述

举例:GPIO配置步骤

1、使能时钟
__HAL_RCC_GPIOx_CLK_ENABLE()
2、设置工作模式
HAL_GPIO_Init()
3、设置输出状态(可选)
HAL_GPIO_WritePin() 
HAL_GPIO_TogglePin()
4、读取输入状态(可选)
HAL_GPIO_ReadPin()

在这里插入图片描述

模块化编程

led.h

#ifndef _LED_H
#define _LED_H
#include "./SYSTEM/sys/sys.h"/******************************************************************************************/
/* 引脚 定义 */#define LED0_GPIO_PORT                  GPIOB
#define LED0_GPIO_PIN                   GPIO_PIN_5
#define LED0_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)             /* PB口时钟使能 */#define LED1_GPIO_PORT                  GPIOE
#define LED1_GPIO_PIN                   GPIO_PIN_5
#define LED1_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)             /* PE口时钟使能 *//******************************************************************************************/
/* LED端口定义 */
#define LED0(x)   do{ x ? \HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(LED0_GPIO_PORT, LED0_GPIO_PIN, GPIO_PIN_RESET); \}while(0)      /* LED0翻转 */#define LED1(x)   do{ x ? \HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(LED1_GPIO_PORT, LED1_GPIO_PIN, GPIO_PIN_RESET); \}while(0)      /* LED1翻转 *//* LED取反定义 */
#define LED0_TOGGLE()   do{ HAL_GPIO_TogglePin(LED0_GPIO_PORT, LED0_GPIO_PIN); }while(0)        /* 翻转LED0 */
#define LED1_TOGGLE()   do{ HAL_GPIO_TogglePin(LED1_GPIO_PORT, LED1_GPIO_PIN); }while(0)        /* 翻转LED1 *//******************************************************************************************/
/* 外部接口函数*/
void led_init(void);                                                                            /* 初始化 */#endif

led.c

#include "./BSP/LED/led.h"/*** @brief       初始化LED相关IO口, 并使能时钟* @param       无* @retval      无*/
void led_init(void)
{GPIO_InitTypeDef gpio_init_struct;LED0_GPIO_CLK_ENABLE();                                 /* LED0时钟使能 */LED1_GPIO_CLK_ENABLE();                                 /* LED1时钟使能 */gpio_init_struct.Pin = LED0_GPIO_PIN;                   /* LED0引脚 */gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;            /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                    /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;          /* 高速 */HAL_GPIO_Init(LED0_GPIO_PORT, &gpio_init_struct);       /* 初始化LED0引脚 */gpio_init_struct.Pin = LED1_GPIO_PIN;                   /* LED1引脚 */HAL_GPIO_Init(LED1_GPIO_PORT, &gpio_init_struct);       /* 初始化LED1引脚 */LED0(1);                                                /* 关闭 LED0 */LED1(1);                                                /* 关闭 LED1 */
}

mian.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/delay/delay.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"int main(void)
{HAL_Init();                                 /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9);         /* 设置时钟,72M */delay_init(72);                             /* 初始化延时函数 */led_init();                                 /* 初始化LED */while(1){LED0(0);                                /* LED0 亮 */LED1(1);                                /* LED1 灭 */delay_ms(500);LED0(1);                                /* LED0 灭 */LED1(0);                                /* LED1 亮 */delay_ms(500);}
}

按键控制灯的亮灭

按键
key.h

#ifndef __KEY_H
#define __KEY_H#include "./SYSTEM/sys/sys.h"/******************************************************************************************/
/* 引脚 定义 */#define KEY0_GPIO_PORT                  GPIOE
#define KEY0_GPIO_PIN                   GPIO_PIN_4
#define KEY0_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */#define KEY1_GPIO_PORT                  GPIOE
#define KEY1_GPIO_PIN                   GPIO_PIN_3
#define KEY1_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */#define KEY2_GPIO_PORT                  GPIOE
#define KEY2_GPIO_PIN                   GPIO_PIN_2
#define KEY2_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOE_CLK_ENABLE(); }while(0)   /* PE口时钟使能 */#define WKUP_GPIO_PORT                  GPIOA
#define WKUP_GPIO_PIN                   GPIO_PIN_0
#define WKUP_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOA_CLK_ENABLE(); }while(0)   /* PA口时钟使能 *//******************************************************************************************/#define KEY0        HAL_GPIO_ReadPin(KEY0_GPIO_PORT, KEY0_GPIO_PIN)     /* 读取KEY0引脚 */
#define KEY1        HAL_GPIO_ReadPin(KEY1_GPIO_PORT, KEY1_GPIO_PIN)     /* 读取KEY1引脚 */
#define KEY2        HAL_GPIO_ReadPin(KEY2_GPIO_PORT, KEY2_GPIO_PIN)     /* 读取KEY2引脚 */
#define WK_UP       HAL_GPIO_ReadPin(WKUP_GPIO_PORT, WKUP_GPIO_PIN)     /* 读取WKUP引脚 */#define KEY0_PRES    1              /* KEY0按下 */
#define KEY1_PRES    2              /* KEY1按下 */
#define KEY2_PRES    3              /* KEY2按下 */
#define WKUP_PRES    4              /* KEY_UP按下(即WK_UP) */void key_init(void);                /* 按键初始化函数 */
uint8_t key_scan(uint8_t mode);     /* 按键扫描函数 */#endif

key.c

#include "./BSP/KEY/key.h"
#include "./SYSTEM/delay/delay.h"/*** @brief       按键初始化函数* @param       无* @retval      无*/
void key_init(void)
{GPIO_InitTypeDef gpio_init_struct;KEY0_GPIO_CLK_ENABLE();                                     /* KEY0时钟使能 */KEY1_GPIO_CLK_ENABLE();                                     /* KEY1时钟使能 */KEY2_GPIO_CLK_ENABLE();                                     /* KEY2时钟使能 */WKUP_GPIO_CLK_ENABLE();                                     /* WKUP时钟使能 */gpio_init_struct.Pin = KEY0_GPIO_PIN;                       /* KEY0引脚 */gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */HAL_GPIO_Init(KEY0_GPIO_PORT, &gpio_init_struct);           /* KEY0引脚模式设置,上拉输入 */gpio_init_struct.Pin = KEY1_GPIO_PIN;                       /* KEY1引脚 */gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */HAL_GPIO_Init(KEY1_GPIO_PORT, &gpio_init_struct);           /* KEY1引脚模式设置,上拉输入 */gpio_init_struct.Pin = KEY2_GPIO_PIN;                       /* KEY2引脚 */gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */gpio_init_struct.Pull = GPIO_PULLUP;                        /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */HAL_GPIO_Init(KEY2_GPIO_PORT, &gpio_init_struct);           /* KEY2引脚模式设置,上拉输入 */gpio_init_struct.Pin = WKUP_GPIO_PIN;                       /* WKUP引脚 */gpio_init_struct.Mode = GPIO_MODE_INPUT;                    /* 输入 */gpio_init_struct.Pull = GPIO_PULLDOWN;                      /* 下拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;              /* 高速 */HAL_GPIO_Init(WKUP_GPIO_PORT, &gpio_init_struct);           /* WKUP引脚模式设置,下拉输入 */}/*** @brief       按键扫描函数* @note        该函数有响应优先级(同时按下多个按键): WK_UP > KEY2 > KEY1 > KEY0!!* @param       mode:0 / 1, 具体含义如下:*   @arg       0,  不支持连续按(当按键按下不放时, 只有第一次调用会返回键值,*                  必须松开以后, 再次按下才会返回其他键值)*   @arg       1,  支持连续按(当按键按下不放时, 每次调用该函数都会返回键值)* @retval      键值, 定义如下:*              KEY0_PRES, 1, KEY0按下*              KEY1_PRES, 2, KEY1按下*              KEY2_PRES, 3, KEY2按下*              WKUP_PRES, 4, WKUP按下*/
uint8_t key_scan(uint8_t mode)
{static uint8_t key_up = 1;  /* 按键按松开标志 */uint8_t keyval = 0;if (mode) key_up = 1;       /* 支持连按 */if (key_up && (KEY0 == 0 || KEY1 == 0 || KEY2 == 0 || WK_UP == 1))  /* 按键松开标志为1, 且有任意一个按键按下了 */{delay_ms(10);           /* 去抖动 */key_up = 0;if (KEY0 == 0)  keyval = KEY0_PRES;if (KEY1 == 0)  keyval = KEY1_PRES;if (KEY2 == 0)  keyval = KEY2_PRES;if (WK_UP == 1) keyval = WKUP_PRES;}else if (KEY0 == 1 && KEY1 == 1 && KEY2 == 1 && WK_UP == 0) /* 没有任何按键按下, 标记按键松开 */{key_up = 1;}return keyval;              /* 返回键值 */
}

蜂鸣器
beep.h

#ifndef __BEEP_H
#define __BEEP_H#include "./SYSTEM/sys/sys.h"/******************************************************************************************/
/* 引脚 定义 */#define BEEP_GPIO_PORT                  GPIOB
#define BEEP_GPIO_PIN                   GPIO_PIN_8
#define BEEP_GPIO_CLK_ENABLE()          do{ __HAL_RCC_GPIOB_CLK_ENABLE(); }while(0)   /* PB口时钟使能 *//******************************************************************************************//* 蜂鸣器控制 */
#define BEEP(x)         do{ x ? \HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN, GPIO_PIN_SET) : \HAL_GPIO_WritePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN, GPIO_PIN_RESET); \}while(0)/* BEEP状态翻转 */
#define BEEP_TOGGLE()   do{ HAL_GPIO_TogglePin(BEEP_GPIO_PORT, BEEP_GPIO_PIN); }while(0)     /* BEEP = !BEEP */void beep_init(void);   /* 初始化蜂鸣器 */#endif

beep.c

#include "./BSP/BEEP/beep.h"/*** @brief       初始化BEEP相关IO口, 并使能时钟* @param       无* @retval      无*/
void beep_init(void)
{GPIO_InitTypeDef gpio_init_struct;BEEP_GPIO_CLK_ENABLE();                             /* BEEP时钟使能 */gpio_init_struct.Pin = BEEP_GPIO_PIN;               /* 蜂鸣器引脚 */gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;        /* 推挽输出 */gpio_init_struct.Pull = GPIO_PULLUP;                /* 上拉 */gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;      /* 高速 */HAL_GPIO_Init(BEEP_GPIO_PORT, &gpio_init_struct);   /* 初始化蜂鸣器引脚 */BEEP(0);                                            /* 关闭蜂鸣器 */
}

main.c

#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/BEEP/beep.h"
#include "./BSP/KEY/key.h"int main(void)
{uint8_t key;HAL_Init();                             /* 初始化HAL库 */sys_stm32_clock_init(RCC_PLL_MUL9);     /* 设置时钟, 72Mhz */delay_init(72);                         /* 延时初始化 */led_init();                             /* 初始化LED */key_init();                             /* 初始化按键 */beep_init();                            /* 初始化蜂鸣器 */LED0(0);                                /* 先点亮LED0 */while(1){key = key_scan(0);                  /* 得到键值 */if (key){switch (key){case WKUP_PRES:             /* 控制蜂鸣器 */BEEP_TOGGLE();          /* BEEP状态取反 */break;case KEY2_PRES:             /* 控制LED0(RED)翻转 */LED0_TOGGLE();          /* LED0状态取反 */break;case KEY1_PRES:             /* 控制LED1(GREEN)翻转 */LED1_TOGGLE();          /* LED1状态取反 */break;case KEY0_PRES:             /* 同时控制LED0, LED1翻转 */LED0_TOGGLE();          /* LED0状态取反 */LED1_TOGGLE();          /* LED1状态取反 */break;}}else{delay_ms(10);}}
}

相关文章:

  • 微信小程序地图缩放scale隐性bug
  • [AI Tools] Dify 平台插件开发全解:如何构建 Tools 插件并解析输出逻辑
  • OpenCV中适用华为昇腾(Ascend)后端的逐元素操作(Per-element Operations)
  • 【质量管理】TRIZ因果链分析:解码质量问题的“多米诺效应“
  • 经典计算核心问题在于多项式时间内无法求解
  • 重庆工商职业学院“户卫者”团队为建筑外墙检测技术推广创新赋能
  • PostgreSQL创建只读账号
  • 自适应混合索引创建与管理:一种智能数据库优化机制的研究
  • PH热榜 | 2025-05-09
  • 『Python学习笔记』ubuntu解决matplotlit中文乱码的问题!
  • 鸿蒙电脑:五年铸剑开新篇,国产操作系统新引擎
  • 华为防火墙双机热备(负载分担)
  • 华为欧拉(EulerOS)系统全栈软件部署指南:从 Redis 到 MySQL 实战详解
  • 计算机视觉】OpenCV项目实战:eye_mouse_movement:基于opencv实战眼睛控制鼠标
  • Oracle — 数据管理
  • Faiss 索引深度解析:从基础到实战
  • 文旅田园康养小镇规划设计方案PPT(85页)
  • RabbitMQ-高级特性1
  • 如何避免双击时触发单击事件
  • Springboot+Vue+Mybatis-plus-Maven-Mysql项目部署
  • 重庆大学通报本科生发14篇SCI论文处理结果
  • 上海国际电影节推出三大官方推荐单元,精选十部优秀影片
  • 优秀“博主”在上海杨浦购房最高补贴200万元,有何条件?
  • 第32届梅花奖终评启幕,上海京剧院《智取威虎山》满堂彩
  • 洞天寻隐·学林纪丨玉洞桃源:仇英青绿山水画中的洞天与身体
  • A股低开高走全线上涨:军工股再度领涨,两市成交12934亿元