Eaglewood-开发单片机函数封装技巧

目录

一、核心原则:

(一)、高内聚低耦合:每个函数只做一件事,减少依赖。

(二)、接口清晰:隐藏实现细节。

(三)、可配置性:通过宏、结构体或回调支持灵活扩展。

(四)、可移植性:抽象硬件差异,降低移植成本。

一、模块化设计

五、宏定义配置参数

二、在头文件中宏定义函数

三、使用结构体封装硬件配置

四、回调函数机制

六、错误处理与返回值封装

七、硬件抽象层( HAL)

八、静态函数限制作用域

九、版本兼容性设计

十、使用const优化

十一、状态机封装

十二、封装签名


一、核心原则:

(一)、高内聚低耦合:每个函数只做一件事,减少依赖。

(二)、接口清晰:隐藏实现细节。

(三)、可配置性:通过宏、结构体或回调支持灵活扩展。

(四)、可移植性:抽象硬件差异,降低移植成本。

一、模块化设计

五、宏定义配置参数

核心思想:将功能相关函数代码封装到独立的 .c/.h 文件中,形成模块。并添加注释、签名

以LED模块作为示例

#ifndef __LED_H
#define __LED_H	 
#include "sys.h"
#include "delay.h"
/*  LED_0时钟端口、引脚定义 */
#define LED_0_PIN     GPIO_Pin_5
#define LED_0_PORT		GPIOE
#define LED_0_CLK   	RCC_APB2Periph_GPIOE
/*  LED_1时钟端口、引脚定义 */
#define LED_1_PIN     GPIO_Pin_5
#define LED_1_PORT		GPIOB
#define LED_1_CLK   	RCC_APB2Periph_GPIOB

#define LED0 		PEout(5)
#define LED1		PBout(5)

void LED_INIT(void);//初始化
void LED_CYCLEBLINK( u32 times, u32 frequency);
		 				    
#endif
#include "LED.h"
/*******************************************************************************
* 函 数 名         : LED_INIT
* 函数功能		   	 : LED初始化 
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/  
void LED_INIT(void)
{
 
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd( LED_0_CLK| LED_1_CLK, ENABLE);	 //使能PB,PE端口时钟
	
 GPIO_InitStructure.GPIO_Pin = LED_0_PIN;				 			 //LED0-->PB.5 端口配置
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽输出
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //IO口速度为50MHz
 GPIO_Init( LED_0_PORT, &GPIO_InitStructure);					 //根据设定参数初始化GPIOB.5
 GPIO_SetBits( LED_0_PORT, LED_0_PIN);						 		 //LED0 输出高

 GPIO_InitStructure.GPIO_Pin = LED_1_PIN;	    		 		 //LED1-->PE.5 端口配置, 推挽输出
 GPIO_Init( LED_1_PORT, &GPIO_InitStructure);	  			 //推挽输出 ,IO口速度为50MHz
 GPIO_SetBits( LED_1_PORT, LED_1_PIN); 						 		 //LED1 输出高 
}

 优点:便于移植;代码独立,便于复用和调试。

二、在头文件中宏定义函数

/*  亮输出低电平;灭输出高电平 */
#define ON			1				
#define OFF			0				

#define LED_0(a)	if(a)GPIO_ResetBits( LED_0_PORT, LED_0_PIN);else GPIO_SetBits( LED_0_PORT, LED_0_PIN);
#define LED_1(a)	if(a)GPIO_ResetBits( LED_1_PORT, LED_1_PIN);else GPIO_SetBits( LED_1_PORT, LED_1_PIN);

 

三、使用结构体封装硬件配置

核心思想:通过结构体统一管理硬件参数(如GPIO、UART配置)

//.h
tybedef struct{
    GPIO_TybeDef    *Port;//端口
    uint16_t        Pin;//引脚号
    uint8_t         Mode;//模式
} GPIO_Config;
void GPIO_INIT( const GPIO_CONFIG *cfg){
    GPIO_InitTybe init = {0};
    init.Pin = cfg -> Pin;
    init.Mode = cfg -> Mode;
    HAL_GPIO_Init( cfg -> Port, &init);
}

 优点:配置参数集中管理,修改灵活。

四、回调函数机制

核心思想:通过函数指针实现事件驱动的回调(如中断、定时器触发)。

/*定义回调函数类型*/
typedef void( *TimeCallback)( void);

/*定时器模块封装*/
void Timer_SetCallback( TimerCallback cb){
    /*在中断服务函数中调用cb()*/
}

/*用户自定义回调*/
void MyTimerHandler(){
    LED_Toggle();
}

int main(){
    Timer_SetCallback( MyTimerHandler);
    while(1);
}

 优点:解耦硬件事件与业务逻辑。

六、错误处理与返回值封装

核心思想:统一错误码和返回值处理机制。

typedef enum{
    DRV_OK = 0;
    DRV_ERROR,
    DRV_TIMEOUT
}DrvStatus;

DrvStatus UART_SendData( uint8_t *data, uint16_t len){
    if( HAL_UART_Transmit( &huart1, data, len, 1000) != HAL_OK){
        return GRV_TIMEOUT;
    }
    return DRV_OK;
}

七、硬件抽象层( HAL)

核心思想:将底层硬件操作抽象为统一接口,适配不同硬件。

//hal_adc.h
typedef void ( *ADC_ReadCallback)( uint16_t value);

void HAL_ADC_Init( ADC_ReadCallback cb);
void HAL_ADC_StartConversion( void);

/*不同平台实现*/
#ifdef STM32
    void HAL_ADC_Init(...){ /* STM32 专用代码 */}
#elif defined( ESP32)
    void HAL_ADC_Init(...){ /* ESP32 专用代码 */}
#endif

优点:跨平台代码复用,减少移植工作量。

八、静态函数限制作用域

核心思想:用static限制函数作用域,避免模块内部函数被外部误调用。(static作静态变量有记忆功能)

//adc.c
static void ADC_Calibrate(){
    /* 仅限本文件内使用 */
}

/* 读取数据 */
void ADC_Read(){
    ADC_Calibrate();/* 内部调用 */
}

优点:隐藏实现细节,提高模块安全性。

九、版本兼容性设计

核心思想:通过宏定义或函数重命名保持向后兼容。

//旧版本函数(标记为废弃)
#define ADC_Start() ADC_StartConversion() //兼容旧代码

//新版本函数
void ADC_StartConversion( void){ ... }

 优点:平滑升级,减少代码迁移成本。

十、使用const优化

核心思想:通过const修饰符保护常量数据(如配置表,映射关系)。

//只读LED映射表
const GPIO_Config LED_MAP[] = {
    { GPIOA, GPIO_PIN_5, GPIO_MODE_OUTPUT_PP},
    { GPIOB, GPIO_PIN_#, GPIO_MODE_OUTPUT_PP}
}

优点:防止数据被意外修改,节省RAM。

十一、状态机封装

核心思想:将复杂逻辑封装为状态机函数,提高可读性。

typedef enum{
    STATE_IDLE,
    STATE_RUNNING,
    STATE_ERROR
}SystemState;

void System_UpdateState(){
    Static SystemState state = STATE_IDLE;
    switch( state){
        case STATE_IDLE:
            if( trigger)state = STATE_RUNNING;
            break;
        case STATE_RUNNING:
            /* 执行操作 */
            break;
    }
}

十二、封装签名

核心思想:运用模块化注释方便阅读调用

/*
*    @brief  //作用
*    @param  //参数
*    @retval //返回值
*    @note:补充说明或注意事项
*    @warning:警告信息(如潜在风险)
*    @return:类似@retval,但更常用于简单返回值
*    @see:关联其他函数或文档
*/

优点:提高代码可读性;通过工具自动生成HTML/PDF等格式的API文档;现代IDE(Keil、VSCode)支持会根据注释提供智能提示。

你可能感兴趣的:(嵌入式泛用知识学习笔记,单片机,嵌入式硬件)