0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

举例说明嵌入式软件如何做分层框架设计

工程师进阶笔记 来源:CSDN技术社区 2022-12-23 09:53 次阅读

前言

为了能够使得产品得到更好的开发速度与以后更好的迭代和移植,框架分层是很有必要的。但如对于中小型项目严格遵循这些原则,势必会消耗过多精力去思考怎么设计系统,这是一个抉择的过程。

一、框架分层是什么?

嵌入式架构中:一般分为硬件架构与软件架构。这里是嵌入式软件设计,也是大多数人接触的设计。

所谓的分层,也可以理解为模块化的设计,但是框架分层的设计一般会遵循以下几点原则

每个模块提供的接口要统一,只能增加,不能改。在设计的时候得考虑好兼容性,使用起来麻烦不麻烦等等。

同一级模块与模块之间相互独立,互不影响,不能相互调用,只能调用它下一层的接口。

不同模块构成不同的层,层与层之间不能跨级调用。

模块中又可以继续分层,可以增减分层,这个需要根据自己的项目需求来进行设置。

一般可以分为:硬件驱动层–>功能模块层–>应用接口层–>业务逻辑层–>应用层

让我们看看这个经典的图,简单了解一下框架分层。

369b1838-8208-11ed-8abf-dac502259ad0.png

从图中不难观察出,设计都是遵循设计的原则的,层与层之间不能相互调用。

二、框架分层的优劣势

1.优势

单一职责:每一层只负责一个职责,职责边界清晰,不会造成跨级调用,在大型项目中,每个人负责的部分不一样,加快整个项目的开发进度。

高内聚:分层是把相同的职责放在同一个层中,所有业务逻辑内聚在领域层。在测试的时候,只需要测试该领域的层即可,一般不需要考虑其他层的问题。

耦合:依赖关系非常简单,上层只能依赖于下层,没有循环依赖。

易维护:面对变更容易修改。在平台更改后,如果只是改了驱动,其他层都不需要动,只需要把驱动层给更改,其他层的功能不需要更改。

易复用:如果功能模块变动了,只需升级相应的功能模块,其他的模块不受影响,应用层也不受影响。

如果想要更好地利用这些优势,那得严格遵循设计的原则。

2.劣势

开发成本高:因为多层分别承担各自的职责,增加功能需要在多个层增加代码,这样难免会增加开发成本。但是合理的抽象,根据自己的项目设置合理的层级是能降低开发成本的。

性能略低:业务流需要经过多层代码的处理,性能会有所消耗。

可扩展性低:因为上下层之间存在耦合度,有些功能变化可能涉及到多层的修改。

有优势也有劣势,需要根据自己的项目需要,进行部分的取舍,如果是中小型项目,可以不需要分层(如果不考虑到以后会迭代的话),或者部分分层就够了,既能利用框架分层的部分优势,也能降低开发成本。

三、一个简单的例子

由于主要讨论的是软件框架的分层设计,这里使用STM32cubemx来进行硬件的初始化,尽可能少考虑到硬件驱动的部分。

以一个智能小灯的作为例子:

功能

按键控制小灯的亮度,等级为:0,1,2,3

串口可以观察当前小灯亮度等级

OLED也可以观察当前小灯亮度等级

下面就是这个例子的一个简单的图示。

这和例子比较简单,业务逻辑层完全可以去除,直接从应用层调用功能模块层,加快开发进度。

36be104a-8208-11ed-8abf-dac502259ad0.png

最后附上一点点代码,就是关于LED如何进行在不同层进行封装

硬件层

首先看HAL库生成提供的代码,这个就是LED硬件层,也就是GPIO层,cubemx已经生成了,在stm32f4xx_hal_gpio.c(我用的是F4),以及有相应的GPIO的驱动了,这里不需要我们进行处理。

37029aa8-8208-11ed-8abf-dac502259ad0.png

硬件层驱动层

看LED部分的驱动,也就是下面的这两个函数

voidMX_TIM1_Init(void);
voidHAL_TIM_MspPostInit(TIM_HandleTypeDef*timHandle);
12
/*TIM1initfunction*/
voidMX_TIM1_Init(void)
{

/*USERCODEBEGINTIM1_Init0*/

/*USERCODEENDTIM1_Init0*/

TIM_ClockConfigTypeDefsClockSourceConfig={0};
TIM_MasterConfigTypeDefsMasterConfig={0};
TIM_OC_InitTypeDefsConfigOC={0};
TIM_BreakDeadTimeConfigTypeDefsBreakDeadTimeConfig={0};

/*USERCODEBEGINTIM1_Init1*/

/*USERCODEENDTIM1_Init1*/
htim1.Instance=TIM1;
htim1.Init.Prescaler=168-1;
htim1.Init.CounterMode=TIM_COUNTERMODE_UP;
htim1.Init.Period=10000;
htim1.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter=0;
htim1.Init.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE;
if(HAL_TIM_Base_Init(&htim1)!=HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource=TIM_CLOCKSOURCE_INTERNAL;
if(HAL_TIM_ConfigClockSource(&htim1,&sClockSourceConfig)!=HAL_OK)
{
Error_Handler();
}
if(HAL_TIM_PWM_Init(&htim1)!=HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger=TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode=TIM_MASTERSLAVEMODE_DISABLE;
if(HAL_TIMEx_MasterConfigSynchronization(&htim1,&sMasterConfig)!=HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode=TIM_OCMODE_PWM1;
sConfigOC.Pulse=0;
sConfigOC.OCPolarity=TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity=TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode=TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState=TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState=TIM_OCNIDLESTATE_RESET;
if(HAL_TIM_PWM_ConfigChannel(&htim1,&sConfigOC,TIM_CHANNEL_2)!=HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode=TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode=TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel=TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime=0;
sBreakDeadTimeConfig.BreakState=TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity=TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput=TIM_AUTOMATICOUTPUT_DISABLE;
if(HAL_TIMEx_ConfigBreakDeadTime(&htim1,&sBreakDeadTimeConfig)!=HAL_OK)
{
Error_Handler();
}
/*USERCODEBEGINTIM1_Init2*/

/*USERCODEENDTIM1_Init2*/
HAL_TIM_MspPostInit(&htim1);

}

voidHAL_TIM_MspPostInit(TIM_HandleTypeDef*timHandle)
{

GPIO_InitTypeDefGPIO_InitStruct={0};
if(timHandle->Instance==TIM1)
{
/*USERCODEBEGINTIM1_MspPostInit0*/

/*USERCODEENDTIM1_MspPostInit0*/

__HAL_RCC_GPIOE_CLK_ENABLE();
/**TIM1GPIOConfiguration
PE11------>TIM1_CH2
*/
GPIO_InitStruct.Pin=GPIO_PIN_11;
GPIO_InitStruct.Mode=GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull=GPIO_NOPULL;
GPIO_InitStruct.Speed=GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate=GPIO_AF1_TIM1;
HAL_GPIO_Init(GPIOE,&GPIO_InitStruct);

/*USERCODEBEGINTIM1_MspPostInit1*/

/*USERCODEENDTIM1_MspPostInit1*/
}

}
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798

对其进行封装,就是我们想要的Led小灯的驱动了,到时候如果需要,改驱动直接改底层就行了。

voidLed_init()
{
MX_TIM1_Init();
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);//启动PWM
}
12345

功能模块层

根据上面的需求要求划分为四个不同等级,同时也需要对LED驱动进行进一步封装,以便满足层与层之间不能跨级调用的原则(到这里是不是发现很麻烦!小项目就不要用啦!)

//ARR计数器设置值为0~10000
#defineLED_GRADE_00
#defineLED_GRADE_13000
#defineLED_GRADE_26000
#defineLED_GRADE_310000
//设置LED亮度功能
voidLed_Set_brightness(intGrade)
{
if(Grade==LED_GRADE_0)
{
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,Grade);
HAL_TIM_PWM_Stop(&htim1,TIM_CHANNEL_2);//关闭PWM输出
}
else
{
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2,Grade);
__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,Grade);
}
}

//启动LED功能
voidLed_Start()
{
Led_init();
}
12345678910111213141516171819202122232425

业务逻辑层

这里仅仅以启动层为例:

voidStart_app()
{
Led_Start();
}
1234

应用层

基本流程是:启动业务逻辑->读取业务逻辑->处理业务逻辑->显示业务逻辑。

四、总结

到这里,一个简单的例子也解释完毕了,通过LED这个简单的例子,已经大概了解到这个设计的复杂了,如果是大型项目,运用起来会很爽,小型的话完全没必要这样分层,太麻烦了,严重减慢开发效率,时间都用在思考如何进行分层才能符合框架分层的原则。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • led
    led
    +关注

    关注

    240

    文章

    23128

    浏览量

    658274
  • 嵌入式
    +关注

    关注

    5068

    文章

    19008

    浏览量

    302991
  • OLED
    +关注

    关注

    119

    文章

    6179

    浏览量

    223806
  • 嵌入式软件
    +关注

    关注

    4

    文章

    240

    浏览量

    26609

原文标题:举例说明嵌入式软件如何做分层框架设计

文章出处:【微信号:工程师进阶笔记,微信公众号:工程师进阶笔记】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    嵌入式里通用微秒计时函数框架设计与实现

    今天给大家分享的是嵌入式里通用微秒(microseconds)计时函数框架设计与实现。
    的头像 发表于 10-14 12:41 1840次阅读

    嵌入式软件分层框架的优劣

    为了能够使得产品得到更好的开发速度与以后更好的迭代和移植,框架分层是很有必要的。但如对于中小型项目严格遵循这些原则,势必会消耗过多精力去思考怎么设计系统,这是一个抉择的过程。
    的头像 发表于 02-21 09:45 1755次阅读

    嵌入式软件的基本构成以及功能

    1:嵌入式系统的基本概念。嵌入式软件的基本构成以及功能;能画出简单的嵌入式系统设计框图,举例说明嵌入式
    发表于 12-14 08:30

    嵌入式软件设计上的程序模块分为哪几类

    嵌入式软件框架设计要考虑哪些因素?嵌入式软件设计上的程序模块分为哪几类?
    发表于 12-24 07:12

    探讨一下嵌入式软件分层设计

    嵌入式软件分层设计嵌入式软件就是某一项目的源码文件集合,源码文件的数量,根据项目复杂程度的不同而有规模和层次的差别。就拿简单的一个芯片厂..
    发表于 02-14 07:19

    嵌入式软件建立统一框架方法的研究

    介绍了嵌入式系统软件的特点#说明要建立统一嵌入式软件系统框架的原因,指出
    发表于 11-07 16:02 27次下载

    嵌入式应用框架EAF详解

    EAF是Embedded Application Framework 的缩写,即嵌入式应用框架嵌入式应用框架是 Application framework的一种, 是在
    发表于 12-02 11:30 2798次阅读

    关于嵌入式应用框架(EAF)的分析

    EAF是Embedded Application Framework 的缩写,即嵌入式应用框架嵌入式应用框架是 Application framework的一种, 是在
    发表于 01-01 09:50 1486次阅读

    嵌入式系统底层软件可移值性设计及开发流程分析

    在阐述嵌入式系统软件设计方法的基础上,介绍嵌入式系统底层软件可移值性设计和硬件抽象层的建立;举例说明利用此思想的
    的头像 发表于 10-04 18:02 2762次阅读
    <b class='flag-5'>嵌入式</b>系统底层<b class='flag-5'>软件</b>可移值性设计及开发流程分析

    嵌入式框架-分层

    原有的代码。接下来嵌入式ARM便和大家分享一下,嵌入式架构那些事儿……01嵌入式系统的基本架构嵌入式系统一般由软件和硬件两个部分组成,基中
    发表于 10-20 16:06 24次下载
    <b class='flag-5'>嵌入式</b><b class='flag-5'>框架</b>-<b class='flag-5'>分层</b>

    嵌入式系统框架----软件

    1.overview 图1-1 嵌入式框架嵌入式系统分为硬件以及软件两大部分,大多数人参与的是
    发表于 10-20 19:21 5次下载
    <b class='flag-5'>嵌入式</b>系统<b class='flag-5'>框架</b>----<b class='flag-5'>软件</b>篇

    嵌入式开发|嵌入式软件框架《二》前后台任务框架-cola os系统

    系列文章目录嵌入式开发|嵌入式软件框架《一》常用的软件框架介绍与选择文章目录系列文章目录前言一、
    发表于 11-03 13:51 18次下载
    <b class='flag-5'>嵌入式</b>开发|<b class='flag-5'>嵌入式</b><b class='flag-5'>软件</b><b class='flag-5'>框架</b>《二》前后台任务<b class='flag-5'>框架</b>-cola os系统

    痞子衡嵌入式嵌入式里通用微秒(microseconds)计时函数框架设计与实现

      大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是嵌入式里通用微秒(microseconds)计时函数框架设计与实现。  在嵌入式软件开发里,计时可以说是非常基础的功
    发表于 11-25 09:21 16次下载
    痞子衡<b class='flag-5'>嵌入式</b>:<b class='flag-5'>嵌入式</b>里通用微秒(microseconds)计时函数<b class='flag-5'>框架设</b>计与实现

    嵌入式软件分层隔离的典范是什么?

    嵌入式软件开发分层、模块化是理想状态,实际开发中因各种限制而有所取舍,但这不妨碍学习参考优秀软件架构,即使有部分思想在项目中落实,也是大有裨益的。
    的头像 发表于 01-20 11:08 1081次阅读
    <b class='flag-5'>嵌入式</b><b class='flag-5'>软件</b><b class='flag-5'>分层</b>隔离的典范是什么?

    聊聊嵌入式软件分层

    今天以控制LED闪烁为例,聊聊嵌入式软件分层
    的头像 发表于 12-28 09:22 634次阅读