0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

舉例說明嵌入式軟件如何做分層框架設計

工程師進階筆記 ? 來源:CSDN技術社區(qū) ? 2022-12-23 09:53 ? 次閱讀

前言

為了能夠使得產(chǎn)品得到更好的開發(fā)速度與以后更好的迭代和移植,框架分層是很有必要的。但如對于中小型項目嚴格遵循這些原則,勢必會消耗過多精力去思考怎么設計系統(tǒng),這是一個抉擇的過程。

一、框架分層是什么?

嵌入式架構中:一般分為硬件架構與軟件架構。這里是嵌入式軟件設計,也是大多數(shù)人接觸的設計。

所謂的分層,也可以理解為模塊化的設計,但是框架分層的設計一般會遵循以下幾點原則

每個模塊提供的接口要統(tǒng)一,只能增加,不能改。在設計的時候得考慮好兼容性,使用起來麻煩不麻煩等等。

同一級模塊與模塊之間相互獨立,互不影響,不能相互調用,只能調用它下一層的接口。

不同模塊構成不同的層,層與層之間不能跨級調用。

模塊中又可以繼續(xù)分層,可以增減分層,這個需要根據(jù)自己的項目需求來進行設置。

一般可以分為:硬件驅動層–>功能模塊層–>應用接口層–>業(yè)務邏輯層–>應用層

讓我們看看這個經(jīng)典的圖,簡單了解一下框架分層。

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

從圖中不難觀察出,設計都是遵循設計的原則的,層與層之間不能相互調用。

二、框架分層的優(yōu)劣勢

1.優(yōu)勢

單一職責:每一層只負責一個職責,職責邊界清晰,不會造成跨級調用,在大型項目中,每個人負責的部分不一樣,加快整個項目的開發(fā)進度。

高內聚:分層是把相同的職責放在同一個層中,所有業(yè)務邏輯內聚在領域層。在測試的時候,只需要測試該領域的層即可,一般不需要考慮其他層的問題。

耦合:依賴關系非常簡單,上層只能依賴于下層,沒有循環(huán)依賴。

易維護:面對變更容易修改。在平臺更改后,如果只是改了驅動,其他層都不需要動,只需要把驅動層給更改,其他層的功能不需要更改。

易復用:如果功能模塊變動了,只需升級相應的功能模塊,其他的模塊不受影響,應用層也不受影響。

如果想要更好地利用這些優(yōu)勢,那得嚴格遵循設計的原則。

2.劣勢

開發(fā)成本高:因為多層分別承擔各自的職責,增加功能需要在多個層增加代碼,這樣難免會增加開發(fā)成本。但是合理的抽象,根據(jù)自己的項目設置合理的層級是能降低開發(fā)成本的。

性能略低:業(yè)務流需要經(jīng)過多層代碼的處理,性能會有所消耗。

可擴展性低:因為上下層之間存在耦合度,有些功能變化可能涉及到多層的修改。

有優(yōu)勢也有劣勢,需要根據(jù)自己的項目需要,進行部分的取舍,如果是中小型項目,可以不需要分層(如果不考慮到以后會迭代的話),或者部分分層就夠了,既能利用框架分層的部分優(yōu)勢,也能降低開發(fā)成本。

三、一個簡單的例子

由于主要討論的是軟件框架的分層設計,這里使用STM32cubemx來進行硬件的初始化,盡可能少考慮到硬件驅動的部分。

以一個智能小燈的作為例子:

功能

按鍵控制小燈的亮度,等級為:0,1,2,3

串口可以觀察當前小燈亮度等級

OLED也可以觀察當前小燈亮度等級

下面就是這個例子的一個簡單的圖示。

這和例子比較簡單,業(yè)務邏輯層完全可以去除,直接從應用層調用功能模塊層,加快開發(fā)進度。

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

最后附上一點點代碼,就是關于LED如何進行在不同層進行封裝

硬件層

首先看HAL庫生成提供的代碼,這個就是LED硬件層,也就是GPIO層,cubemx已經(jīng)生成了,在stm32f4xx_hal_gpio.c(我用的是F4),以及有相應的GPIO的驅動了,這里不需要我們進行處理。

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

硬件層驅動層

看LED部分的驅動,也就是下面的這兩個函數(shù)

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

功能模塊層

根據(jù)上面的需求要求劃分為四個不同等級,同時也需要對LED驅動進行進一步封裝,以便滿足層與層之間不能跨級調用的原則(到這里是不是發(fā)現(xiàn)很麻煩!小項目就不要用啦?。?/p>

//ARR計數(shù)器設置值為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

業(yè)務邏輯層

這里僅僅以啟動層為例:

voidStart_app()
{
Led_Start();
}
1234

應用層

基本流程是:啟動業(yè)務邏輯->讀取業(yè)務邏輯->處理業(yè)務邏輯->顯示業(yè)務邏輯。

四、總結

到這里,一個簡單的例子也解釋完畢了,通過LED這個簡單的例子,已經(jīng)大概了解到這個設計的復雜了,如果是大型項目,運用起來會很爽,小型的話完全沒必要這樣分層,太麻煩了,嚴重減慢開發(fā)效率,時間都用在思考如何進行分層才能符合框架分層的原則。

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • led
    led
    +關注

    關注

    242

    文章

    23277

    瀏覽量

    660873
  • 嵌入式
    +關注

    關注

    5082

    文章

    19126

    瀏覽量

    305200
  • OLED
    +關注

    關注

    119

    文章

    6200

    瀏覽量

    224207
  • 嵌入式軟件
    +關注

    關注

    4

    文章

    240

    瀏覽量

    26646

原文標題:舉例說明嵌入式軟件如何做分層框架設計

文章出處:【微信號:工程師進階筆記,微信公眾號:工程師進階筆記】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    嵌入式里通用微秒計時函數(shù)框架設計與實現(xiàn)

    今天給大家分享的是嵌入式里通用微秒(microseconds)計時函數(shù)框架設計與實現(xiàn)。
    的頭像 發(fā)表于 10-14 12:41 ?1896次閱讀

    嵌入式軟件分層框架的優(yōu)劣

    為了能夠使得產(chǎn)品得到更好的開發(fā)速度與以后更好的迭代和移植,框架分層是很有必要的。但如對于中小型項目嚴格遵循這些原則,勢必會消耗過多精力去思考怎么設計系統(tǒng),這是一個抉擇的過程。
    的頭像 發(fā)表于 02-21 09:45 ?1794次閱讀

    嵌入式軟件的基本構成以及功能

    1:嵌入式系統(tǒng)的基本概念。嵌入式軟件的基本構成以及功能;能畫出簡單的嵌入式系統(tǒng)設計框圖,舉例說明嵌入式
    發(fā)表于 12-14 08:30

    嵌入式軟件設計上的程序模塊分為哪幾類

    嵌入式軟件框架設計要考慮哪些因素?嵌入式軟件設計上的程序模塊分為哪幾類?
    發(fā)表于 12-24 07:12

    探討一下嵌入式軟件分層設計

    嵌入式軟件分層設計嵌入式軟件就是某一項目的源碼文件集合,源碼文件的數(shù)量,根據(jù)項目復雜程度的不同而有規(guī)模和層次的差別。就拿簡單的一個芯片廠..
    發(fā)表于 02-14 07:19

    嵌入式軟件建立統(tǒng)一框架方法的研究

    介紹了嵌入式系統(tǒng)軟件的特點#說明要建立統(tǒng)一嵌入式軟件系統(tǒng)框架的原因,指出
    發(fā)表于 11-07 16:02 ?27次下載

    嵌入式應用框架EAF詳解

    EAF是Embedded Application Framework 的縮寫,即嵌入式應用框架。嵌入式應用框架是 Application framework的一種, 是在
    發(fā)表于 12-02 11:30 ?2852次閱讀

    關于嵌入式應用框架(EAF)的分析

    EAF是Embedded Application Framework 的縮寫,即嵌入式應用框架。嵌入式應用框架是 Application framework的一種, 是在
    發(fā)表于 01-01 09:50 ?1530次閱讀

    嵌入式系統(tǒng)底層軟件可移值性設計及開發(fā)流程分析

    在闡述嵌入式系統(tǒng)軟件設計方法的基礎上,介紹嵌入式系統(tǒng)底層軟件可移值性設計和硬件抽象層的建立;舉例說明利用此思想的
    的頭像 發(fā)表于 10-04 18:02 ?2796次閱讀
    <b class='flag-5'>嵌入式</b>系統(tǒng)底層<b class='flag-5'>軟件</b>可移值性設計及開發(fā)流程分析

    嵌入式框架-分層

    原有的代碼。接下來嵌入式ARM便和大家分享一下,嵌入式架構那些事兒……01嵌入式系統(tǒng)的基本架構嵌入式系統(tǒng)一般由軟件和硬件兩個部分組成,基中
    發(fā)表于 10-20 16:06 ?24次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>框架</b>-<b class='flag-5'>分層</b>

    嵌入式系統(tǒng)框架----軟件

    1.overview 圖1-1 嵌入式框架嵌入式系統(tǒng)分為硬件以及軟件兩大部分,大多數(shù)人參與的是
    發(fā)表于 10-20 19:21 ?5次下載
    <b class='flag-5'>嵌入式</b>系統(tǒng)<b class='flag-5'>框架</b>----<b class='flag-5'>軟件</b>篇

    嵌入式開發(fā)|嵌入式軟件框架《二》前后臺任務框架-cola os系統(tǒng)

    系列文章目錄嵌入式開發(fā)|嵌入式軟件框架《一》常用的軟件框架介紹與選擇文章目錄系列文章目錄前言一、
    發(fā)表于 11-03 13:51 ?18次下載
    <b class='flag-5'>嵌入式</b>開發(fā)|<b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b><b class='flag-5'>框架</b>《二》前后臺任務<b class='flag-5'>框架</b>-cola os系統(tǒng)

    痞子衡嵌入式嵌入式里通用微秒(microseconds)計時函數(shù)框架設計與實現(xiàn)

      大家好,我是痞子衡,是正經(jīng)搞技術的痞子。今天痞子衡給大家分享的是嵌入式里通用微秒(microseconds)計時函數(shù)框架設計與實現(xiàn)。  在嵌入式軟件開發(fā)里,計時可以說是非常基礎的功
    發(fā)表于 11-25 09:21 ?16次下載
    痞子衡<b class='flag-5'>嵌入式</b>:<b class='flag-5'>嵌入式</b>里通用微秒(microseconds)計時函數(shù)<b class='flag-5'>框架設</b>計與實現(xiàn)

    嵌入式軟件分層隔離的典范是什么?

    嵌入式軟件開發(fā)分層、模塊化是理想狀態(tài),實際開發(fā)中因各種限制而有所取舍,但這不妨礙學習參考優(yōu)秀軟件架構,即使有部分思想在項目中落實,也是大有裨益的。
    的頭像 發(fā)表于 01-20 11:08 ?1144次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>軟件</b><b class='flag-5'>分層</b>隔離的典范是什么?

    聊聊嵌入式軟件分層

    今天以控制LED閃爍為例,聊聊嵌入式軟件分層
    的頭像 發(fā)表于 12-28 09:22 ?680次閱讀