![]() |
發布時間: 2019-6-6 11:48
正文摘要:- 前言 - 時至今日,依舊看到很多小伙伴們放著單片機里的定時器不用,動輒delay1s(); delay500ms();雖然簡單粗暴,但是其實是很不妥當的。還有很多需要按鍵的程序,動不動就“while(k1==0);”的等按鍵松開,這樣 ... |
如果有需要,我可以把相關的主程序和架構打包上傳……不過說實話這些代碼隨便敲敲就有了,需要鍛煉的是一種“精準控制”軟件的邏輯的思維。 跑快了的東西我們把它放慢些,跑慢了的東西給它放快些。 對于一個系統來說,“平衡”是很重要的事情。 最后再說一句,while(1)大循環里面不要放“delay();”或者“while(按鍵被按下);”了…… ![]() |
很抱歉的告訴大家,之前的想法還是太樂觀,現在每天忙成狗,完全不確定啥時候能抽時間寫完,7月15日要是沒有更新的話還請大家諒解。![]() ![]() ![]() 不過我是不會就這么停筆的,只是不知道啥時候有時間寫而已。作為打工仔,真的身不由己。 為了不辜負大家的期待,下次更新時我會把文檔做成pdf,附帶源碼,流程圖,表格一并上傳。 ![]() ![]() ![]() 其實還有很多可以寫的地方,但是現在這篇帖子就寫這3點——時基,模塊化,狀態機——已經夠大家消化一陣子了。而且,如果帖子的篇幅太長了,其實不利于閱讀的。 以后如果還有別的分享,我會另開帖子的,多蹭點管理員的黑幣,哈哈。 ![]() ![]() ![]() |
ccdmcu 發表于 2019-8-2 16:22 我不是給了個keyPress()程序么,你再好好看看。 簡單來說,有鍵按下時,時間就會++; 無鍵按下時,時間就會清零。 但在清零之前會先檢查,時間是否大于0,時間值大于0(或者消抖值)說明曾經有鍵按下過,并且剛剛松開。這時候處理“這次按鍵”不就好了。 |
樓主這文章比那些所謂的教科書好多了,那些教科書按鍵消抖動不動就是delay(20ms),真是誤人子弟,真正出來做到大型項目才知道 DELAY是多么不實際。希望樓主繼續更新,最好轉成PDF,多點例程,尤其是一些按鍵的,短按,長按,雙擊組合鍵例程。現在絕大部份寫按鍵程序都喜歡delay消抖,while松手檢測。郭天詳的書也是這么教的,一點不實用 |
laishu12345 發表于 2019-8-9 17:08 確實不會“小于”0,但“等于”0是有可能的喔,所以這樣寫是沒問題的。 至于為什么我寫了“<=",而不是”==“呢? 理由是 —— 容錯機制: 萬一手殘了,在定義key_press_time的時候忘記加了unsigned,我們的按鍵程序照樣可以正常工作(只是計數最大值只有原來的一半了) |
本帖最后由 Similarv 于 2019-8-15 10:40 編輯 IdeaMing 發表于 2019-8-14 10:27 這個好說,把基礎時基變成10ms(或者20ms),也就是定時器中斷10ms(或者20ms)產生一次。 然后就是……
|
IdeaMing 發表于 2019-8-16 16:25 我剛剛特意去查了一下,這玩意僅僅是個溫度傳感器,而且還特么是數字的,讀一次溫度居然至少要5Ms?!(還不確定是否會更久) 這樣,如果你有示波器的話,請你做這么一個實驗,把單片機某個端口設為輸出,這個端口平時是低電平,然后用18b20讀取溫度之前拉高它,讀取結束的時候又拉低它,然后用示波器好好的看看這個端口被拉高的時間,你就知道它每次采溫需要多長時間了。再結合其他子程序的工作時長,設計你的時基。 其實,這種數字型溫度傳感器在我們實際做項目的人的眼里,只有華而不實四個字可以評價。如果我們的項目里需要測溫,我們一般會采用內部自帶adc模塊的單片機,測溫只要一個熱敏電阻就可以搞定。整個測溫的時間只需大約10us。不但更便宜,精度更好,效率還是你那個測溫模塊的500倍!具體方案這里就不贅述了。 |
本帖最后由 Similarv 于 2020-1-13 18:07 編輯 13303022280 發表于 2020-1-7 14:29 你的做法當然也沒有問題,不過我是這么做的: 按鍵就只是做按鍵檢測,并且設置相應的“按鍵已觸發”標志(bit變量);至于按鍵的功能則是在別處比如狀態機中去執行。 例子:當按鍵按下之后開/關燈 key.c 文件: bit key_flag_light; //當按鍵觸發時為1,否則為0, 此變量是給狀態機使用的 static bit key_press_light; //當按鍵按下時為1,未按下為0,此變量僅在key.c內使用。 函數1-keyScan() -- 功能:檢測按鍵是否按下,若按鍵按下則將key_press_light置一,否則清零。 函數2-keyDeal() -- 功能:使用某靜態變量統計key_press_light的時間;當key_press_light從1變為0的時候,檢查靜態變量的值是否大于消抖值,若大于消抖時間則將key_flag_light設置為1; state.c文件 函數1-StateMachine() -- 功能:當key_flag_light==1時,取反led_flag_out的值,隨后將key_flag_light設置為0. led.c文件 bit led_flag_out; //當該值==1,開燈;當該值==0;關燈 函數1-ledOutput() -- 功能:根據led_flag_out的取值開燈或者關燈 main.c文件 在10ms或者20ms的時基中依次調用 keyScan(); keyDeal(); StateMachine(); 在100ms的時基中調用 ledOutput(); /******/ 稍微修改一下,剛剛沒有認真審題,你需要做長按的判定,我這個架構是基于短按的。 修改的地方位于keyDeal()部分, 短按 —— 是等待按鍵松開時裁決靜態變量的計時值。 長按 —— 則是直接在靜態變量等于‘長按時間點’的時刻將key_flag_light置一即可。key_flag_light==1的時候,狀態機自然會處理長按事件,此后keyDeal()里的靜態變量會在按鍵繼續按著的時候繼續加,但其值已經‘大于’‘長按時間點’了,所以key_flag_light不會被重復置一,當按鍵釋放之后,此靜態變量清零,一切重新開始。 |
hubj627 發表于 2020-1-13 09:20 進階教程尚待壇友們自己修行,鄙人不才,只能帶路到這了 ![]() |
好文章,不知樓主能否弄成pdf格式上傳呢,想保存起來!!! |
不錯學習了 |
good!! |
絕世好貼! |
很好 |
感謝分享 |
這是教的程序整體架構,對于裸機(沒有操作系統)開發是堪稱經典的教程。 |
學會了,謝謝樓主 |
我是白菜,這個思路一下子就打開了我的思維,大多教程都是老的那一套,感謝大神的分享!! |
秒啊,好文![]() |
必須收藏了好吧![]() |
真不錯,有耳目一新的感覺。![]() |
幾年前的貼子怎么沒有留意到呢,點了好幾年的燈,看來有望進階八級點燈大師啦![]() |
學到很多,單片機的學習最終還是必須回歸到給客戶服務 |
長文看不完,收藏吧 |
denggong 發表于 2025-3-9 08:28 中斷講究快進快出,除非不得已不得在中斷里做太多工作 |
我直接在中斷里調用顯示程序,雖然占用點時間,但保證每次中斷能刷新顯示,不用每次刷新顯存后調用顯示程序。 |
受益匪淺 |
謝謝分享,學習一下 |
還以為是新帖,仔細一看原來是2019年的帖子,但是直到現在還有回復,內容真的干貨。 感謝大神的無私分享。 |
把定時器封裝成DELAY()MS,這樣用也方便, |
很好,能看到這樣的帖子很好 |
太棒了我正愁不知道該怎么辦 |
感謝大佬!!值得學習!! |
14頁都看了一遍,深深認識到:感謝【51黑電子論壇】及其創辦者和維護人員!!!有了這個平臺和這些人,才有我們學習的機會,非常感謝! |
Similarv 發表于 2019-8-19 01:00 我自已做的開發板就用了個溫感芯片,還自以為很高級,慚愧啊,熱敏電阻,受教受教! ![]() |
首先,感謝樓主的分享!其次,本人愚鈍,看時還未茅塞頓開,但有豁然開朗的感覺,需要慢慢消化吸收。 最后,再次致謝樓主的無私分享! |
干貨![]() |
不錯,很有用。 |
看了樓主的教程,學到了知識 |
越學越感覺深奧 |
很好,記錄一下,學習 |
不錯的文章。點贊,學習了![]() |
新手進階必讀 |
經典,不知道樓主如今何處開新貼了~~ |
謝謝分享,多發一些類似文章。 |
大佬原來是這么厲害的嗎,學到了繼續努力 |
大佬 求更新 |
絕世好帖! |
多年前的老帖了啊 |