close

今天分享的文章,主要給那些沒有軟件設計思想、初級的MCU軟件工程師看的。

隨着目前MCU的各方面性能顯著提升,一些以MCU為控制中心的嵌入式系統也是越來越複雜,毫無軟件設計理念的代碼,真的是拖累單片機,所以對每個MCU軟件工程師在軟件設計等方面的要求也將越來越高。

本文利用一個實際發生的例子,對入行的初級軟件工程師提一些軟件設計上的建議,並分享了一些經常走的彎路,希望可以幫到大家。

這篇文章我沒有談編程的規範性的東西,如果你想讓自己的程序文件代碼更加直觀、看起來美觀、可讀性強,推薦學習一下全面的編程規範,比如網絡上廣為流傳的,華為「C語言編程規範」。本文主要想說一說,當我們的單片機遇到多個模塊的數據需要處理,類似於「多任務」時應該怎麼去思考和處理?

背景是這樣的:9月份開始安排一個工程師開始做電動汽車交流充電樁,機械設計部分由公司機械結構部門負責。充電樁的電子部分總體上分為X個部分(用到的資源):電阻觸摸屏(RS232),M1卡讀寫(RS232),電能計量表(RS485),語音提示(SPI),電力開關(繼電器IO),通訊接口(RS485、CAN)。

工程師做的過程非常勤奮,期間也是困難重重,改了很多個版本,很多的bug,總算第二年6月把充電樁立起來了。

當然,此過程我並沒有過多的干涉,系統也沒有經過非常嚴格的測試,結果發現讀卡的時候不能處理觸摸屏,播放語音的時候不能處理讀卡,語音播放不能打斷或者跳躍,反正就是所有事件必須一個一個按部就班的來,一旦操作錯誤,就需要多次執行、等待,甚至重新來過。

一個工作3年多的工程師怎麼會把產品做成這樣呢?思來想去不應該呀,是不是程序哪裡出了問題 ? 解決問題的最好辦法就是評審代碼,來review代碼瞧瞧。

不看不知道,一看嚇一跳!整個的程序是沒有邏輯的,一條線就往下寫,這不正是當年在學校剛做第一個項目的代碼嗎?

//主循環while(1){//上電進入主程序或觸發觸摸屏Function1();//播放提示語音Delay();//等待播放完畢//讀取M1卡信息Function2();Delay();//等待讀卡數據返回//播放提示語音Function3();Delay();//等待播放完畢//M1卡數據交互,判定下一步操作及提示Function4();Delay();//等待數據處理完畢…………}

從代碼上可以看出這個工程師基本上對於自己設計的產品沒有任何軟件上的設計可言,也很少去吸收一些優秀的代碼和思想,對自己開發的程序在產品上的具體表現也不敏感,更被說對RTOS的學習和理解了。

他犯了幾個在程序開發過程中比較忌諱的錯誤:

1、delay(死等)這類函數應該只在實驗室驗證某個功能過程中用到,或許是在一些初始化時序使用到,而不會用來控制整個的程序運行架構,在實際的產品開發時無論是主循環while中,還是其調用的函數中,亦或是中斷服務程序中幾乎是不可能看到的。

2、產品設計的各個相對比較獨立的子模塊之間的邏輯關係太強,例如:必須等待播音完畢才能讀卡進入下一步操作等。

我們講,產品設計中只有各個事件處理模塊間的邏輯關係弱化,才能更加靈活的進行處理。例如:兩個事件A和B,如果程序開發時將A做成B事件的必要條件,B事件的觸發就必須等待A事件的發生。反之如果A事件作為B事件處理的一個特殊情況,也就是說我不執行A也有可能執行B,那麼程序開發起來就變得靈活很多。

3、沒有考慮到單片機本身是一個單核單任務的架構,每一個事件都會獨占CPU內核,當多個任務模塊同時存在時我們應該對各個事件進行區分,我們應當分情況、分事件實時性要求等區分對待。  

那麼,針對這樣的問題或者是遇到類似的項目,我們應該如何處理呢? 

下面提出我的建議和想法,首先他這裡是裸機開發,所以就不談RTOS方面的設計建議了,僅僅只是針對前後台架構。

1、將硬件系統區分為獨立單元單獨做成底層驅動函數和應用函數,並且函數正常應該有參數和返回值,其中返回值是必要的。如何衡量這類函數呢?這類函數可移植性強,只要一個.h文件和一個或多個.c文件就可以隨意放到任何工程中,一句話吧,模塊化!例如:語音播放、M1讀卡、485處理等。

2、將1中的所有函數進行時間評估,評估點有兩個:一是函數的執行時間t;二是函數的周期性發生的時間T,一個最基本的條件是t < T,理想情況應該是t << T。

3、建立一個集中邏輯處理函數,也就是核心任務調度處理函數,在這個函數中對1中的各個函數進行調度。這個函數發揮的作用相當於嵌入式系統中的系統調度。

這種調度是整個硬件邏輯中所有事件處理的調度,它的目的是完成一個處理過程,但是絕不依賴於任意事件的必要處理過程。這樣就將問題2中提到的事件間的邏輯關係弱化了,處理起來變得十分靈活,使得各個關係不在相互必要。

4、為了保證前面內容的正常實施還需要針對各類事件的周期,建立一個必要的時間管理函數,時間函數的基礎一般情況下由一個內部定時器的中斷來完成,中斷的周期一般我們考慮5-10ms。按照實際需求,將N個定時器中斷定義為一個事件處理的周期TT,這個周期應該保證處理完最惡劣情況可能發生的所有t,且保證TT < T。

5、這其中也有例外,一些實時性要求高的事件應當用中斷完成。其中,中斷處理函數的處理事件應儘量短,時間要求參見2。我覺得,不管你所做的項目有沒有用到RTOS,平時都需要玩玩RTOS,對該觀點的理解會有幫助。

作者:handong

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 鑽石舞台 的頭像
    鑽石舞台

    鑽石舞台

    鑽石舞台 發表在 痞客邦 留言(0) 人氣()