软件分层模块化设计,---抽象与硬件分离

10 篇文章 0 订阅
3 篇文章 0 订阅

软件分层模块化设计–抽象与硬件分离



在这里插入图片描述

以点亮led为例子代码实现

led.h

#ifndef _LED_H_
#define _LED_H_

#include <stdint.h>

#define  LED1  0
#define  LED2  1
#define  LED3  2

/**
***********************************************************
* @brief LED硬件初始化
* @param
* @return 
***********************************************************
*/
void LedDrvInit(void);

/**
***********************************************************
* @brief 点亮LED
* @param ledNo,LED标号,0~2
* @return 
***********************************************************
*/
void TurnOnLed(uint8_t ledNo);

/**
***********************************************************
* @brief 熄灭LED
* @param ledNo,LED标号,0~2
* @return 
***********************************************************
*/
void TurnOffLed(uint8_t ledNo);

#endif

led.c

#include <stdint.h>
#include "gd32f30x.h"

typedef struct
{
    rcu_periph_enum rcu;
    uint32_t gpio;
    uint32_t pin;
} Led_GPIO_t;

static Led_GPIO_t g_gpioList[] =
{
    {RCU_GPIOA, GPIOA, GPIO_PIN_8},
    {RCU_GPIOE, GPIOE, GPIO_PIN_6},
    {RCU_GPIOF, GPIOF, GPIO_PIN_6}
};

#define LED_NUM_MAX (sizeof(g_gpioList) / sizeof(g_gpioList[0]))

/**
***********************************************************
* @brief LED硬件初始化
* @param
* @return 
***********************************************************
*/
void LedDrvInit(void)
{
    for (uint8_t i = 0; i < LED_NUM_MAX; i++)
    {
        rcu_periph_clock_enable(g_gpioList[i].rcu);
        gpio_init(g_gpioList[i].gpio, GPIO_MODE_OUT_PP, GPIO_OSPEED_2MHZ, g_gpioList[i].pin);
        gpio_bit_reset(g_gpioList[i].gpio, g_gpioList[i].pin);
    }
}

/**
***********************************************************
* @brief 点亮LED
* @param ledNo,LED标号,0~2
* @return 
***********************************************************
*/
void TurnOnLed(uint8_t ledNo)
{
    if (ledNo >= LED_NUM_MAX)
    {
        return;
    }
    gpio_bit_set(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}

/**
***********************************************************
* @brief 熄灭LED
* @param ledNo,LED标号,0~2
* @return 
***********************************************************
*/
void TurnOffLed(uint8_t ledNo)
{
    if (ledNo >= LED_NUM_MAX)
    {
        return;
    }
    gpio_bit_reset(g_gpioList[ledNo].gpio, g_gpioList[ledNo].pin);
}

代码分析

这段代码实现了LED驱动的模块化设计,通过分层的方式将硬件相关的初始化和控制与应用逻辑分离开来,增强了代码的可维护性和可移植性。
让我们逐步分析代码的各个部分:
1.头文件包含:

  • #include <stdint.h>:引入标准整数类型,如uint8_t等。
  • #include “gd32f30x.h”:引入芯片相关的头文件,其中可能包含了对芯片特定寄存器的定义和操作函数。
    2.结构体定义:
  • Led_GPIO_t:定义了一个结构体类型,包含LED的相关信息,包括RCU外设、GPIO端口和引脚号。
    3.LED GPIO列表:
  • static Led_GPIO_t g_gpioList[]:定义了一个静态数组,存储了多个LED的GPIO信息,每个元素包含了LED的RCU外设、GPIO端口和引脚号。
    4.LED数量宏定义:
  • #define LED_NUM_MAX (sizeof(g_gpioList) / sizeof(g_gpioList[0])):定义了LED的最大数量,通过计算g_gpioList数组的元素个数来确定LED的数量。
    5.LED硬件初始化函数:
  • void LedDrvInit(void):初始化LED硬件,依次启用每个LED对应的RCU外设,配置相应的GPIO为推挽输出模式,并将LED初始状态设置为熄灭。
    6.点亮LED函数:
  • void TurnOnLed(uint8_t ledNo):点亮指定编号的LED,首先检查编号是否合法,然后将对应GPIO的相应引脚置位。
    7.熄灭LED函数:
  • void TurnOffLed(uint8_t ledNo):熄灭指定编号的LED,首先检查编号是否合法,然后将对应GPIO的相应引脚复位。
    通过这样的设计,可以在应用层面方便地调用TurnOnLed和TurnOffLed函数来控制LED的状态,而不需要关心具体的硬件细节。同时,若要新增或修改LED的引脚配置,只需修改g_gpioList数组即可,无需修改其他代码,提高了代码的灵活性和可维护性。

总结

这段代码展示了LED驱动模块的设计,体现了软件分层模块化设计的几个方面:

结构体封装:

使用结构体 Led_GPIO_t 封装了LED的相关信息,包括使用的 RCC 外设、GPIO 端口和引脚号,使得 LED 相关的信息更具可读性和可维护性。
模块化函数设计:

将 LED 相关的功能函数(初始化、点亮、熄灭)封装成了独立的函数,分别是 LedDrvInit()、TurnOnLed() 和 TurnOffLed(),这样设计使得 LED 功能模块化,易于扩展和维护。
抽象接口:

通过函数的参数传入 LED 的编号,实现了对 LED 控制的抽象,使得调用者不需要了解 LED 具体的引脚编号,只需传入 LED 编号即可控制相应的 LED,提高了代码的可重用性和可移植性。
代码可读性:

使用了宏定义 LED_NUM_MAX 来表示 LED 的数量,增强了代码的可读性和可维护性,若要增加或减少 LED 的数量,只需修改 LED 相关信息的数量,而不需要修改其他代码。
这样的设计使得 LED 驱动模块具有良好的模块化、可扩展性和可维护性,同时提高了代码的可读性和可重用性,使得 LED 控制的实现更加简洁和灵活。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苦梨甜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值