這篇文章分享怎么寫出穩定的單片機代碼。
我對優秀代碼的理解,大體分為兩個部分:高效和穩定。 兩者都能做到很好的,如果靠自己摸索,沒有刻意去練習,可能需要花10年,甚至更久。
對于單片機產品來說,高效可能不是剛需。
高效寫法和低效寫法,在很多功能上看不出區別,代碼執行效率快個納秒、微秒、甚至是毫秒的時間差,對功能本身并無影響。
所以在高效和穩定之間,我建議先提升怎么把程序寫穩定,再進一步優化程序效率。
如果當下覺得自己寫的代碼比較爛,也沒關系,先多寫,再多學習高手寫的代碼,你就能看出其中的精華。
經驗不足的時候,哪怕別人直接給你答案,你也不知道他為什么要這樣做。
我很多代碼思維和技巧,都是學習同事的代碼,我看到他們的代碼時,和無際項目特訓營老鐵看我們代碼的感覺是一樣的,先是一臉懵逼,有些工作后,接觸項目多了,才領悟其中的精髓。
剛開始我也不能理解他們的代碼,感覺寫的很復雜,搞不懂明明可以寫的很簡單,為什么要繞一個彎。
不過我把他們的代碼保存起來了。
后面跳槽又做了幾年,有次,領導安排了一個復雜點的新項目,需要自己獨立從頭到尾去做。
很多功能沒做過,不知道怎么下手,摸著石頭過河,用最笨的辦法,先把功能實現。
后面把代碼組織在一起的時候,又發現整個邏輯異常混亂和沖突。
舉個簡單的例子,一個LED燈指示設備聯網狀態,未接連上時,每200ms閃一次,連接上wifi時,每400ms閃一次,連接上路由器時,每600ms閃一次,連接上服務器時,常亮。
固定的閃爍效果,簡單,但要考慮到通用性和擴展性,就難很多了。
為什么我要專門給點燈,寫一個程序架構?
是因為LED需求太多了,LED大多數產品都有,而且每個產品LED數量,需要的閃爍效果都不同,每次重復去寫,費時費力。
所以我把LED閃爍,設計成獨立的功能模塊,并考慮到了擴展性和移植性。
需要修改LED數量,直接修改枚舉量就好了,需要增加LED閃爍效果,直接添加一個波形數組就好了,后續算法會根據數組的值,自動輸出相應的波形。
架構定好,下次類似產品功能的需求,我改一下,只需要幾分鐘。
所以,程序寫的咋樣,不是看代碼寫得多漂亮,或者用了什么高級語法,而是看是否精準解決需求。
除此以外,所有花里胡哨的技巧,都是脫褲子放屁。
代碼穩定性,主要體現在一些復雜的項目上,一些簡單的項目,沒多少功能,硬調也能調出來。
所以,我覺得,想把代碼寫穩定,最主要的就是程序架構的設計。
如果架構設計不好,會導致代碼難以維護、容易出錯、功能擴展困難、穩定性差、調試困難、硬件兼容性差等問題。
好的程序架構,我覺得核心是要把控兩點:
一、程序"地基"也就是整個項目,所有功能的"管理者"。比如RTOS,就是充當這樣的角色。
很多復雜的單片機項目,都會上RTOS,就是保證地基是穩定,降低對工程師的技能要求。
寫一個系統,和移植一個系統用,完全不是一個難度級別。
不過,我還是比較喜歡用"裸機"寫程序,然后采用自己設計的輕量任務調度系統。
這是一個簡單的輪詢式任務調度系統,通過一個定時器中斷來觸發任務調度。相對RTOS來說,有以下優勢:
①簡單,資源占用少不需要復雜的任務管理數據結構和調度算法,因此占用的內存和CPU資源較少,特別適合資源受限的單片機,之前這個架構多次用于51單片機的項目。
②能完全掌控代碼都是自己寫的,相對移植RTOS來說,更能掌控,減少由于對系統不熟,給產品埋雷的風險。任務也是按順序執行的,沒有復雜的任務切換,調試時更容易跟蹤和分析問題。 ③任務分離通過任務創建函數OS_CreatTask,將不同的功能分配給不同的任務。這種分離確保了每個任務只關注一件事情,提高了代碼的可讀性和可維護性。
④靈活性創建任務時,可以為每個任務分配不同執行頻率,從而調整任務執行順序,可以很靈活地控制任務執行,也非常適合周期性的任務。
⑤減少CPU占用,響應更快雖然在這個架構中沒有明確的任務優先級,但可以通過調整任務的執行頻率或順序,來間接實現優先級控制。
傳統while(1)死循環的用法,CPU一直在忙碌地執行某個代碼塊,而輪詢式架構可以讓CPU在沒有任務執行時,處于空閑狀態,一旦任務準備好執行,它可以立即開始運行,減少響應時間。 不過有一點,需要人為控制每個任務的代碼效率,盡量不要有延時高的代碼。 ⑤擴展性強雖然架構簡單,但通過增加任務和調整調度邏輯,系統仍然可以擴展以支持更多的功能,比如增加現場切換功能和任務優先級管理,即是最精簡的RTOS系統。 這種輪詢式任務調度系統,雖然不支持真正的并發執行,但以更簡單,高效的方式來管理多個任務,對于大多數的單片機項目來說,其實也夠了。至少我還沒碰到過,非要上RTOS才能完成的產品。
這個架構也有配套的開源視頻,是我2018年錄著玩的,不過代碼已申請版權,非學員不能直接用于自己項目,可以學習這種編程思維,要的找我安排。
二、功能模塊化如果是項目功能比較多,一定要采用模塊化的方式,以便于后期的代碼維護和移植。 拿我們無際特訓營項目6的代碼舉例,創建了3個任務,分別管理硬件層、中間層、應用層的功能。
1.硬件層主要是單片機外設,以及一些外圍芯片的驅動程序,比如定時器、LED、語音輸出、按鍵、串口、ADC、EEPROM。
然后不同的硬件驅動程序也是相互獨立的。
2.中間層主要是一些協議的解析,比如mqtt、lora、4G等,還有就是一些硬件層的應用程序,比如屏顯示圖案,電池電量檢測邏輯,外電檢測邏輯等。
不同的功能程序也是相互獨立的。
3.應用層就是具體的產品邏輯功能實現代碼,比如菜單系統,防盜報警模式邏輯等等。
我們在做功能的時候,也要有架構的思維,需要考慮到后續功能的擴展和移植。
比如我們做菜單的時候,會考慮到后期如果項目需要增加或刪減界面,怎么設計比較方便靈活。
我們目前的做法是通過結構體數組來管理每個界面,然后通過雙向鏈表讓各界面建立聯系。
類似的還有很多,比如說LED,按鍵這種,基本也是每個產品的剛需。
三、怎么去鍛煉架構思維和能力?一般的工程師,會在工作了3,4年左右,才能意識到程序架構的必要性,也取決于你什么時候能有機會獨立完成復雜的項目,這個時候你會發現,原來的知識體系不夠用。
心態上不用太著急和焦慮,按照正確的方向努力,很快就能具備架構設計能力。
一般流程是這樣的。1.先實現功能先不要考慮架構,先把功能實現出來,再從功能里面找規律。
比如一個按鍵檢測代碼,和10個按鍵,其實也就是加個for循環,代碼就能復用。
比如LED燈的特效,其本質就是輸出的高低電平波形持續的時間不一樣,我們是否能用一個數組來存儲波形數據,通過定時器配合小算法來輸出波形呢? 這些代碼,都是要一步步迭代的,可能修改10次,就比較完美了,不要要求一寫就接近完美,容易自閉。 還有就是多接觸優秀的工程師和項目,沒條件的可以看看STM32固件庫代碼,看看藍牙協議棧,看看RTOS,這些都是開源的產品級代碼。
-
單片機
+關注
關注
6043文章
44621瀏覽量
638614 -
代碼
+關注
關注
30文章
4828瀏覽量
69058
原文標題:如何編寫穩定的單片機代碼?
文章出處:【微信號:nanshuqg,微信公眾號:無際單片機編程】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
怎么提升單片機代碼執行效率
單片機Debug工具性能對比 單片機調試常用命令
單片機Debug與仿真區別
讓單片機代碼性能起飛的七大技巧
![讓<b class='flag-5'>單片機</b><b class='flag-5'>代碼</b>性能起飛的七大技巧](https://file1.elecfans.com/web1/M00/F5/38/wKgaoWc4AgyAZv_zAAAM5p8QlOI357.png)
評論