【嵌入式開發問題彙總】程序篇

此文是我很久之前的一個計劃,目的是讓大家可以在別人的錯誤中有所收穫。

寫下我和實驗室小夥伴以及一些網友遇到的問題和分析。大家可以遇到問題也可以在博文下留言。當然,本人能力有限,錯漏之處請直接提出。希望這篇博文能爲所有喜歡嵌入式的朋友答疑解惑!

本文中,如沒有特殊說明,描述的都是STM32系列單片機相關問題。

相關博文:【嵌入式開發問題彙總】硬件篇 (持續更新中...)


目錄

問題1:定時器PWM——多個定時器的PWM頻率不一致

問題2:定時器PWM——高級定時器(TIM1/TIM8)不輸出PWM

問題3:定時器PWM——頻率和計算值不一致

問題4:定時器中斷——中斷無法產生

問題5:定時器中斷——中斷代碼執行異常/開啓中斷後主程序異常/程序死機

問題6:定時器中斷——中斷代碼執行一次之後失效

問題7:正交編碼器不工作/數據波動

問題8:代碼下載後不運行/重新上電後才執行

問題9:不想寫程序


 

 

問題1:定時器PWM——多個定時器的PWM頻率不一致

描述:同樣的定時器預分頻係數(PSC)和重裝載值(ARR)配置下的PWM頻率不一致(差了一倍)

分析:出現這種問題,一般是沒有意識到高級定時器與一般定時器的差別,高級定時器所使用的的時鐘和一般定時器不同。在STM32F10xx系列單片機中,TIM1、TIM8是高級定時器(小容量芯片沒有TIM8,比如STM32F103Cxxx)。在STM32F4xx系列單片機中,多了TIM9/TIM10/TIM11定時器(這些不是高級定時器但是也使用APB2時鐘)。定時器使用外設時鐘APB,但是高級定時器(以及F4xx系列中的TIM9/TIM10/TIM11通用定時器)使用APB2時鐘,其他的定時器使用APB1時鐘。一般來說,APB2時鐘頻率是APB1的兩倍。所以輸出PWM時,要根據定時器所使用的時鐘的頻率計算分頻數PSC與重裝載值ARR。

STM32F1xx中定時器所使用的的外設時鐘APB
STM32F4xx中定時器所使用的的外設時鐘APB

問題2:定時器PWM——高級定時器(TIM1/TIM8)不輸出PWM

描述:按照正常的PWM配置與GPIO配置後,TIM1/TIM8沒有輸出PWM波形。

分析:高級定時器之所以高級,他有互補輸出PWM的功能。這個功能有一個寄存器叫BDTR,高級定時器通過次寄存器完成互補PWM的死區控制。我們在使用普通的PWM輸出時,需要關閉死區控制,單打開PWM輸出的使能(BDTR寄存器的最高位)即可。所以需要在初始化完成之後加上以下代碼(以TIM1爲例):

寄存器版本:

TIM1->BDTR |= 0x8000;

庫函數版本:

TIM_CtrlPWMOutputs(TIM1, ENABLE);

問題3:定時器PWM——頻率和計算值不一致

描述:已知定時器所用的外設時鐘APB頻率並設置好PWM的預分頻PSC和重裝載值ARR之後,發現輸出的PWM頻率與計算所得不一致。

分析:新手長犯的錯誤,PWM頻率越高問題越多。這個就是寄存器的配置問題,我舉個例子大家就懂了:時鐘頻率72MHz,要到的1kHz的PWM,可以這樣設置(PSC=72-1;ARR=1000-1),給這倆寄存器的數值是計算值減一,這在手冊裏說的很清楚。定時器PWM的頻率計算公式爲:

f_{PWM}=\frac{f_{APB}}{\left ( PSC-1 \right )\left ( ARR-1 \right )}

問題4:定時器中斷——中斷無法產生

描述:配置好定時器中斷之後,發現程序運行時無法進入中斷

分析:只要定時器中斷初始化的配置正確,就能進入中斷。這裏列出幾個定時器中斷配置時容易忽略的問題:

(1)中斷使能未開啓,一般情況下,我們使用的中斷時間爲計數器溢出時間IT,檢查初始化中是否有以下代碼(庫函數):

TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE);//允許更新中斷

(2)中斷入口函數設置不正確,我曾經犯過這個問題,問題非常隱祕,害我一頓好找:

大小寫錯誤(“H”小寫了)
拼寫錯誤(少了"l")
正確的中斷入口函數

以上的錯誤其實會看彙編指令的話很容易發現問題,在觸發中斷時,代碼死在在彙編指令"B   ."上,B 是無條件跳轉指令,一個點“.”表示沒有找到跳轉的位置(正常情況下應該跳轉到正確的中斷入口地址).

問題5:定時器中斷——中斷代碼執行異常/開啓中斷後主程序異常/程序死機

描述:定時器中斷可以運行,但是一旦打開定時器中斷,會發現中斷代碼爲未執行完/主程序出現卡頓或異常/程序運行一段時間後死機。

分析:這種情況有幾個可能的原因

(1)在對單片機性能要求不嚴格的情況下,我也會偏好使用基於Systick時鐘的延時函數delay_ms()delay_us(),但往往就是這個函數引發了衆多BUG。爲什麼會這樣呢?主要是Systick時鐘只有一個,當然同時也只能執行一個延時函數(如果對其做了基於操作系統的調度等等不在討論範圍內)。如果主函數中和定時器中斷同時使用了基於Systick的延時函數,那麼第一個觸發的延時函數就會出現不可預料的錯誤,導致中斷代碼執行異常或主程序異常。最好的建議就是,不要在中斷程序中使用基於Systick時鐘的延時函數delay_ms()和delay_us(),中斷是無法預料的代碼段,在裏面放置延時函數就是爲自己埋雷,如果一定要在中斷中使用延時函數,建議使用_NOP空指令或計數器延時。

(2)出現了“套娃錯誤”:觸發中斷之後,中斷程序還沒有執行完,新的中斷又來了,如果發生在單箇中斷函數,只要將中斷函數設置成阻塞式即可(在中斷程序執行完成之後在開啓中斷)。如果發生在多箇中斷之間,則需要合理調度中斷,設置合理的中斷優先級。

問題6:定時器中斷——中斷代碼執行一次之後失效

描述:中斷執行了一次之後就不在被觸發,即使已經滿足觸發條件。

分析:就我目前的經歷看,只有一種可能,第一次退出中斷之後沒有清除中斷標誌位,所以再也進不去。這種情況在定時器,串口,SPI,DMA的配置中都會發生。大家寫BUG的時候一定小心。

比如這個是清除定時器7溢出中斷的標誌位的函數

問題7:正交編碼器不工作/數據波動

描述:使用正交編碼器時,編碼器不能正常工作,或者編碼器在單向旋轉時數據在一個固定數值波動

分析:首先要說的是,支持正交編碼模式的定時器要看好了,不是所有的定時器都可以用作正交編碼器計數的,在STM32F4xx中,只有TIM1、TIM2、TIM3、TIM4、TIM5、TIM8有正交編碼器計數功能,也就是那幾個具有硬件PWM功能的定時器,且一定要注意,編碼器的AB兩相,一定要接到定時器的第1,2通道,3,4通道不行哦!

如果是數據波動,先看數據趨勢是否正確,如果只是計數出現毛刺,可以增加濾波(庫函數中的初始化結構體):TIM_ICInitStructure.TIM_ICFilter = 5;

如果數據就是在幾個值波動,建議檢查編碼器的電源是否正常供電。有些編碼器的霍爾元件需要5-12V的電壓在能操作工作。

問題8:代碼下載後不運行/重新上電後才執行

描述:修改代碼之後下載,一定要手動復位或者重新上電之後纔會運行修改過後的代碼。

分析:調試器一般都有下載完之後自動復位的選擇,這裏以ST-Link調試器爲例:

點擊魔術棒
進入調試器的設置(這裏爲ST-link)
在Flash下載中勾選復位運行

問題9:不想寫程序

描述:不知道爲什麼就是不想寫程序

分析:建議來看看我的博文,點點贊,順便關注一下我。

 


如果以上的問題與解決方案對你有幫助,請爲我在右上角(PC端)/右下角(移動端App)點一下贊,本文持續更新中,可以收藏本文哦,謝謝!

如有問題,可以私信交流或直接在評論區留言!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章