日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > > 嵌入式大雜燴
[導(dǎo)讀]前篇 《由static來談?wù)勀K封裝》 基本實現(xiàn)了對外隱藏屬性,隱藏局部模塊函數(shù),開放接口的功能。對于這個話題還有些點沒有深入探討:為什么要這樣做?以及這樣做的好處是什么?

前篇 《由static來談?wù)勀K封裝》 基本實現(xiàn)了對外隱藏屬性,隱藏局部模塊函數(shù),開放接口的功能。對于這個話題還有些點沒有深入探討:為什么要這樣做?以及這樣做的好處?;蛟S很多剛剛開始用C或者其他面向?qū)ο缶幊陶Z言(比如C++)的小伙伴們,常常在一個項目里為了圖省事,整了很多全局對象、全局變量滿天飛,這樣做其實是有很多弊端,本文來聊聊這個話題。


先談?wù)勅肿兞康奶攸c

全局變量(Global Variables):在計算機編程語言中,所謂全局變量是指具有全局作用域的變量,這意味著它在整個程序中是可見的,因此是可訪問的。所謂可訪問,是指全局可讀、全局可寫。在編譯語言中,全局變量通常是靜態(tài)變量,其范圍(生命周期)是程序的整個運行時。當(dāng)然解釋性語言除外,解釋性語言包括命令行解釋器(比如python, Java script,shell等)中,全局變量通常在聲明時由解釋器動態(tài)分配,這是由于解釋性語言是讀取>解釋>執(zhí)行模式,不像編譯性語言,運行前可預(yù)知變量屬性,解釋性語言讀取解釋前無從獲取變量屬性。

在C/C++編程語言中,全局變量的這種全局可見性特點,濫用全局變量會讓代碼表現(xiàn)當(dāng)相當(dāng)邪惡!如果使用全局變量,就意味著下面這些場景的存在:

  • 實際代碼可能有很多地方在讀、在寫全局變量
  • 全局變量在多線程或多任務(wù)間共享
  • 全局變量在常規(guī)代碼和中斷服務(wù)程序間共享

為啥說全局變量很邪惡?

單片機裸機編程

或許你會說,我就這樣用?咋了?軟件也跑的很好???來看看這個場景:

一個超字寬的變量(比如16位單片機,字寬即為16位),正被一個常規(guī)代碼在寫變量數(shù)據(jù)域時且還沒寫完,啪嘰,來了個中斷!中斷一來,CPU趕緊把手里的活兒停下來,奔過去處理中斷了,不巧在中斷函數(shù)里,該變量因業(yè)務(wù)需求有需要寫這個變量有經(jīng)驗的不這么寫,僅為了方便說明:

舉個栗子,還是以之前文章的傳感器為例,實際應(yīng)用中傳感器可能是下面這樣的數(shù)據(jù)結(jié)構(gòu)來描述:

#ifndef?_SENSOR_H_
#define?_SENSOR_H_
typedef?struct?_t_sensor{
???/*?測量值與測量范圍及單位有關(guān)?*/
???float?value;
???
???/*?測量范圍,根據(jù)采樣值映射??*/
???float?upper_range;
???float?lower_range;
???/*?溫度單位?*/
???
unsiged char unit;
}T_SENSOR;

/*假定是一個溫度測量產(chǎn)品*/
extern?T_SENSOR?temperature;

#endif?_SENSOR_H_


假定這個傳感器數(shù)據(jù)結(jié)構(gòu)有這樣一些被訪問的可能:

  1. 上位機會改寫測量數(shù)據(jù)的范圍及單位,串口通信中斷服務(wù)程序直接寫這個全局變量中的上下限數(shù)據(jù)域
  2. LCD操作界面可改寫溫度上下限范圍。
  3. 測量更新模塊根據(jù)當(dāng)前范圍及單位配置,將傳感器采集到的數(shù)據(jù)映射為測量值。

這些需求用例,用圖描述一下:


比如用戶操作HMI界面正改寫溫度范圍,而此時遠(yuǎn)程上位機也正改寫溫度范圍,按上面這個做法,可能出現(xiàn)哪些邪惡的后果呢?

  1. 通過LCD界面寫入上限為300.5(假定原下限為0),此時遠(yuǎn)程串口報文收到,程序直接在中斷服務(wù)程序?qū)⒎秶薷臑椋?100,200.5),此時中斷返回,用戶可能接著修改下限為-200,則最終設(shè)備內(nèi)的溫度范圍可能既不是(-100,200.5)也不是(-200,300.5),而可能是(-200,200.5)。這是一個易理解的數(shù)據(jù)混亂的場景。
  2. 現(xiàn)實中如果使用的單片機是8位/16位單片機,一條指令無法完成操作一個32位立即數(shù),有可能才完成一個浮點數(shù)中某幾個字節(jié),此時就被中斷打斷寫入200,然后中斷返回后繼續(xù)寫入剩下字節(jié),數(shù)據(jù)可能會變得非常詭異!利用http://www.speedfly.cn/tools/hexconvert/ 在線工具轉(zhuǎn)換浮點數(shù)到16進(jìn)制:
0x43964000?/*?浮點數(shù)300.5的16進(jìn)制*/
0x43488000?/*?浮點數(shù)200.5的16進(jìn)制*/


假定中斷進(jìn)入時,HMI界面程序?qū)懭肓?x4396前兩個字節(jié),中斷返回時,上限改寫為200.5(0x43488000),此時繼續(xù)執(zhí)行后面兩個字節(jié)寫入,則上限變成為(0x43484000),來看看這個數(shù)是多大?變成了200.25,這是不是很邪惡?


或許有的朋友會說,可以在LCD寫范圍時關(guān)中斷嘛。誠然,可以這么做:

void?hmi_operate()
{
????/*關(guān)中斷*/
????_disable_interrupt();
????/*改寫溫度范圍*/
????....
????/*開中斷*/
????_enable_interrupt();
}


但是如果這個全局變量有很多地方在改寫,為了數(shù)據(jù)安全,勢必就到處開/關(guān)中斷,這樣做的壞處:

  • 經(jīng)常開關(guān)中斷,勢必影響中斷響應(yīng),會有概率丟失異步中斷處理(比如串口按字節(jié)接收中斷,可能就會漏收字節(jié)),程序不健壯,工作不穩(wěn)定。
  • 到處訪問改寫,不易調(diào)試,群魔亂舞,代碼也不易維護(hù)。想加點東西,改點東西可能隨處都是坑,一不小心就掉坑里去了!
  • 初學(xué)者甚至不會用struct將相關(guān)的數(shù)據(jù)包在一起,其結(jié)果是代碼里到處都是基本類型的全局變量。一些簡單的業(yè)務(wù)邏輯實現(xiàn)變成一個復(fù)雜的代碼,數(shù)據(jù)信息流向一團(tuán)亂麻。

裸機程序策略

對于上面這樣一個應(yīng)用場景,怎么解決這種混亂的現(xiàn)象呢。這里分享一下我的思路,這里將主要的串口以及測量模塊的設(shè)計思路用UML圖描述一下大體思路:


如此一來,外部就看不到全局變量了,只需要調(diào)用對應(yīng)的set/get方法即可實現(xiàn)讀寫訪問,由于是裸機前后臺程序,數(shù)據(jù)流向就變的非常清晰了。main函數(shù)的主循環(huán)大致就可能是這樣:

void?main(void)
{
???/*模塊初始化*/
???init_uart();
???init_temperature();
???....
???
???while(1)
???{
???????interprete_uart();
???????/*可能是周期性調(diào)用*/
???????if(timer_100ms)
???????{
??????????timer_100ms?=?0;
??????????update_temperature();
???????}????????
?????????
???????....
???}???
}


那么uart協(xié)議解析要怎么做呢?

void?interprete_uart(void)
{
????if(rx_msg.flag)
????{
????????rx_msg.flag?=?false;
????????/*報文完整性檢查*/
????????...
????????????
????????/*設(shè)置溫度配置*/
????????set_upper_range(xxx);
????????set_lower_range(xxx);
????????set_unit(xxx);
????}
????
????if(tx_msg.flag)
????{
????????tx_msg.flag?=?false;
????????start_send();
????}
}

static?start_send(T_UART_MSG?*pMsg)
{
????/*負(fù)責(zé)底層操作,啟動中斷傳輸*/
}

/*提供應(yīng)答數(shù)據(jù)接口*/
void?reply_temperature_setting(T_SENSOR?sensor)
{
????/*解析傳入?yún)?shù)并封裝應(yīng)答報文*/
}


如此一來,數(shù)據(jù)流向?qū)⒆兊煤芮逦?,串口接收到?shù)據(jù)更新范圍配置時,也無需開關(guān)中斷了,從應(yīng)用角度幾乎見不到全局變量。當(dāng)然這樣做的代價就是會增加一些棧開銷。但是這種代價還是值得的。

對于測量模塊的set函數(shù)思路稍做說明:

int?set_upper_range(float?range)
{
????T_SENSOR?temp?=?temperature;
????temp.upper_range?=?range;
????/*實現(xiàn)范圍合理性檢查*/
????if(check_range(temp))
????{
????????/*兩個結(jié)構(gòu)體變量可以直接賦值*/
????????temperature?=?temp;
????????return?0;
????}
????else
????{
???????return?-1;
????}
}

int?set_unit(E_UNIT?unit)
{
????if(unit>E_UNIT_F)
????????return?-1;
????adjust_range(&temperature,unit);
????temperature.unit?=?unit;????
}


上述代碼旨在分享個人的一些思路,其中或有不夠嚴(yán)謹(jǐn)?shù)牡胤?,但通過這樣的設(shè)計思路,應(yīng)能大幅度遠(yuǎn)離滿天飛的全局變量。

多任務(wù)/多線程環(huán)境

上面描述其實本質(zhì)上描述了裸機程序里,普通模式運行程序與中斷服務(wù)程序?qū)τ谂R界資源的競爭。事實上現(xiàn)在不管是單片機,還是處理器,大多都是基于一個操作系統(tǒng)進(jìn)行應(yīng)用開發(fā)。甚至還可能是多核芯片,這里就存在并發(fā)競爭訪問資源的問題。

臨界資源:各任務(wù)/線程采取互斥的方式,實現(xiàn)共享的資源稱作臨界資源。屬于臨界資源的硬件串口打印、顯示等,軟件有消息緩沖隊列、變量、數(shù)組、緩沖區(qū)等。多任務(wù)/線程間應(yīng)采取互斥方式,從而實現(xiàn)對這種資源的共享。

多任務(wù)/多線程情況下在寫模塊時,只需要封裝進(jìn)保護(hù)機制即可。常見的保護(hù)機制有關(guān)中斷、信號量、互斥鎖等。在Linux內(nèi)核中為應(yīng)對多核并發(fā)訪問還有自旋鎖機制。由于篇幅所限,本文就不做展開了,先挖個坑,以后有機會再分享吧。

總結(jié)一下

在前文介紹static文章的基礎(chǔ)上,相對更深入的介紹了為何需要隱藏屬性以及開放接口的做法。以及如何遠(yuǎn)離邪惡的全局變量漫天飛舞的不良設(shè)計風(fēng)格。

辛苦原創(chuàng)總結(jié),如果覺得有價值也請幫忙點贊/在看/轉(zhuǎn)發(fā)支持,不勝感激!

END

往期精彩推薦,點擊即可閱讀




猜你喜歡

干貨 | 嵌入式必備技能之Git的使用

CPU中的程序是怎么運行起來的

嵌入式系統(tǒng)軟件架構(gòu)設(shè)計

Linux下應(yīng)用開發(fā)基礎(chǔ)

【Linux筆記】Pinctrl子系統(tǒng)與GPIO子系統(tǒng)


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當(dāng)下,工業(yè)電機作為核心動力設(shè)備,其驅(qū)動電源的性能直接關(guān)系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護(hù)是驅(qū)動電源設(shè)計中至關(guān)重要的兩個環(huán)節(jié),集成化方案的設(shè)計成為提升電機驅(qū)動性能的關(guān)鍵。

關(guān)鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設(shè)備的使用壽命。然而,在實際應(yīng)用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護(hù)成本,還影響了用戶體驗。要解決這一問題,需從設(shè)計、生...

關(guān)鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關(guān)鍵字: LED 設(shè)計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術(shù)之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關(guān)鍵元件,其性能直接影響到電動汽車的動力性能和...

關(guān)鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設(shè)中,街道及停車場照明作為基礎(chǔ)設(shè)施的重要組成部分,其質(zhì)量和效率直接關(guān)系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進(jìn)步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關(guān)鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設(shè)計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關(guān)鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術(shù)日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設(shè)備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關(guān)鍵字: LED照明技術(shù) 電磁干擾 驅(qū)動電源

開關(guān)電源具有效率高的特性,而且開關(guān)電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關(guān)鍵字: LED 驅(qū)動電源 開關(guān)電源

LED驅(qū)動電源是把電源供應(yīng)轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關(guān)鍵字: LED 隧道燈 驅(qū)動電源
關(guān)閉