點擊上方藍字談思汽車
獲取更多汽車網絡安全資訊

為了能夠使得產品得到更好的開發速度與以后更好的迭代和移植,框架分層是很有必要的。但如對于中小型項目嚴格遵循這些原則,勢必會消耗過多精力去思考怎么設計系統,這是一個抉擇的過程。?
?
在嵌入式架構中:一般分為硬件架構與軟件架構。這里是嵌入式軟件設計,也是大多數人接觸的設計。
一般可以分為:硬件驅動層–>功能模塊層–>應用接口層–>業務邏輯層–>應用層

?
如果想要更好地利用這些優勢,那得嚴格遵循設計的原則。
開發成本高:因為多層分別承擔各自的職責,增加功能需要在多個層增加代碼,這樣難免會增加開發成本。但是合理的抽象,根據自己的項目設置合理的層級是能降低開發成本的。
性能略低:業務流需要經過多層代碼的處理,性能會有所消耗。
可擴展性低:因為上下層之間存在耦合度,有些功能變化可能涉及到多層的修改。
?
由于主要討論的是軟件框架的分層設計,這里使用STM32cubemx來進行硬件的初始化,盡可能少考慮到硬件驅動的部分。
按鍵控制小燈的亮度,等級為:0,1,2,3
串口可以觀察當前小燈亮度等級
OLED也可以觀察當前小燈亮度等級
這和例子比較簡單,業務邏輯層完全可以去除,直接從應用層調用功能模塊層,加快開發進度。

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

也就是下面的這兩個函數
void?MX_TIM1_Init(void);
void?HAL_TIM_MspPostInit(TIM_HandleTypeDef*?timHandle);/*?TIM1?init?function?*/
void?MX_TIM1_Init(void)
{
??/*?USER?CODE?BEGIN?TIM1_Init?0?*/
??/*?USER?CODE?END?TIM1_Init?0?*/
??TIM_ClockConfigTypeDef?sClockSourceConfig?=?{0};
??TIM_MasterConfigTypeDef?sMasterConfig?=?{0};
??TIM_OC_InitTypeDef?sConfigOC?=?{0};
??TIM_BreakDeadTimeConfigTypeDef?sBreakDeadTimeConfig?=?{0};
??/*?USER?CODE?BEGIN?TIM1_Init?1?*/
??/*?USER?CODE?END?TIM1_Init?1?*/
??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();
??}
??/*?USER?CODE?BEGIN?TIM1_Init?2?*/
??/*?USER?CODE?END?TIM1_Init?2?*/
??HAL_TIM_MspPostInit(&htim1);
}
void?HAL_TIM_MspPostInit(TIM_HandleTypeDef*?timHandle)
{
??GPIO_InitTypeDef?GPIO_InitStruct?=?{0};
??if(timHandle->Instance==TIM1)
??{
??/*?USER?CODE?BEGIN?TIM1_MspPostInit?0?*/
??/*?USER?CODE?END?TIM1_MspPostInit?0?*/
????__HAL_RCC_GPIOE_CLK_ENABLE();
????/**TIM1?GPIO?Configuration
????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);
??/*?USER?CODE?BEGIN?TIM1_MspPostInit?1?*/
??/*?USER?CODE?END?TIM1_MspPostInit?1?*/
??}
}對其進行封裝,就是我們想要的Led小燈的驅動了,到時候如果需要,改驅動直接改底層就行了。
void?Led_init()
{
????MX_TIM1_Init();
????HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);//啟動PWM
}根據上面的需求要求劃分為四個不同等級,同時也需要對LED驅動進行進一步封裝,以便滿足層與層之間不能跨級調用的原則(到這里是不是發現很麻煩!小項目就不要用啦!)
//ARR計數器設置值為0~10000
#define?LED_GRADE_0??0
#define?LED_GRADE_1??3000
#define?LED_GRADE_2??6000
#define?LED_GRADE_3??10000
//設置LED亮度功能
void?Led_Set_brightness(int?Grade)
{
????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功能
void?Led_Start()
{
????Led_init();
}這里僅僅以啟動層為例:
void?Start_app()
{
????Led_Start();
}?
到這里,一個簡單的例子也解釋完畢了,通過LED這個簡單的例子,已經大概了解到這個設計的復雜了,如果是大型項目,運用起來會很爽,小型的話完全沒必要這樣分層,太麻煩了,嚴重減慢開發效率,時間都用在思考如何進行分層才能符合框架分層的原則。
原文:http://t.csdn.cn/OWG8f
來源:混說Linux


碼上報名
2023第六屆無人駕駛及智能駕艙中國峰會,
5月11-12日,上海


碼上報名
AutoSec 7周年年會暨中國汽車網絡安全與數據安全合規峰會,5月11-12日,上海

