日本a√视频在线,久久青青亚洲国产,亚洲一区欧美二区,免费g片在线观看网站

        <style id="k3y6c"><u id="k3y6c"></u></style>
        <s id="k3y6c"></s>
        <mark id="k3y6c"></mark>
          
          

          <mark id="k3y6c"></mark>

          "); //-->

          博客專欄

          EEPW首頁 > 博客 > 見鬼!PWM 沒有輸出和串口有啥關(guān)系?

          見鬼!PWM 沒有輸出和串口有啥關(guān)系?

          發(fā)布人:魚鷹談單片機(jī) 時間:2021-04-16 來源:工程師 發(fā)布文章

          魚鷹在做一個項目時,曾經(jīng)遇到一個問題,8 路 PWM 輸出,有一個高級定時器死活無法輸出PWM,另一個高級定時器卻可以順利輸出,初始化配置完全是一樣的。

          根據(jù)魚鷹的經(jīng)驗,定時器沒有輸出有幾個方面:

          1、如果通過中斷翻轉(zhuǎn)電平輸出PWM,那么需要檢查是否進(jìn)入中斷(檢查中斷控制器是否開啟中斷,外設(shè)相應(yīng)中斷是否開啟)。

          2、如果使用 PWM模式,一般問題出在 IO復(fù)用功能和重映射上。如果沒有使用 IO的復(fù)用功能,那么它是不可能被定時器外設(shè)所驅(qū)動的。而如果你的 IO不是該定時器默認(rèn)的輸出 IO,那么就需要進(jìn)行重映射。

          而STM32F1 和 STM32F4 的重映射機(jī)制是不一樣的。

          4.png

          可以看到 F4的重映射比較簡單,直接和 GPIO綁定,不需要另外開啟時鐘,并且我們可以從該函數(shù)的參數(shù)表中直接找到我們想要的對應(yīng) IO復(fù)用功能(上面的代碼代表 GPIOD_12的 TIM4 復(fù)用功能)。

          5.png

          但是 F1 分為部分映射,全映射,還可能有部分映射2……

          6.png

          沒有參考手冊,你根本不知道這些映射對應(yīng)的到底是哪個引腳。

          此時,我們打開相應(yīng)參考手冊,找到 GPIO那一章節(jié),AFIO 小節(jié),找到定時器部分,你可以看到所有定時器的IO映射關(guān)系。

          7.png

          從這張圖,我們可以得到以下幾點信息:

          1)如果不開啟重映射(沒有重映射),定時器2默認(rèn)輸出 IO為:PA0、PA1、PA2、PA3。
          2)部分重映射1 :PA15、PB3、PA2、PA3。
          3)部分重映射2:PA0、PA1、PB10、PB11。
          4)完全重映射:PA15、PB3、PB10、PB11。

          從中我們也可以看到另一個坑,那就是可能端口換了,而你相應(yīng)的時鐘并沒有打開,導(dǎo)致初始化配置失敗,最終導(dǎo)致無法輸出。而使用 PB3 時必須禁用部分 JTAG引腳才行。

          而在重映射上,魚鷹也確實踩了一個坑,到現(xiàn)在我也沒明白為什么。

          當(dāng)時在程序開始關(guān)閉了部分 JTAG引腳功能,然后再初始化定時器,并且開啟相應(yīng)重映射,最終還是沒有任何輸出,魚鷹甚至直接查看最終的 AFIO寄存器的值,但情況就是配置的值一樣,但還是無法輸出,所幸的是,當(dāng)我把復(fù)用功能在禁用部分 JTAG引腳后再開啟所有定時器的重映射功能,發(fā)現(xiàn)能用了……

          3、GPIO 的時鐘沒有打開,或者打開錯誤。

          RCC_APB1PeriphClockCmd(RCC_APB2Periph_GPIOA ENABLE);

          比如像這樣,用 APB1的函數(shù)打開 APB2外設(shè)的時鐘,當(dāng)然會出現(xiàn)問題,當(dāng)然這種坑還是蠻容易檢查出來的

          4、高級定時器的坑:

          要想高級定時器輸出脈沖,必須在初始化后增加一條語句:

          TIM_CtrlPWMOutputs(TIM8, ENABLE);

          沒有這個函數(shù),定時器是不可能輸出脈沖的。

          畢竟是高級定時器,很傲嬌,也很任性。

          而因為它特殊性,魚鷹也是在這里載了一個大跟頭,這也是魚鷹為什么要寫這篇筆記的原因了。

          定時器1 和定時器 8 同屬于高級定時器,但定時器 8 可以正常輸出,而定時器 1 卻沒法輸出,這是怎么回事?

          為了解決這個問題,魚鷹專門把定時器初始化部分封裝成了一個函數(shù),只留一個定時器作為參數(shù)部分:

          8.png

          但最終的結(jié)果還是沒法輸出,這不應(yīng)該的啊,都是一樣的函數(shù),一樣的配置,怎么一個成功,一個失敗。

          認(rèn)真檢查了初始化函數(shù)的每一條語句,參數(shù)并沒有任何問題。

          那到底是什么問題導(dǎo)致的?

          最終魚鷹只能上網(wǎng)查找相關(guān)問題了,有可能就有前輩踩過這種坑呢。

          經(jīng)過多方查找,魚鷹嘗試了各種辦法也沒有效果,最終死馬當(dāng)活馬醫(yī)的試了一個完全沒有道理的可能:把串口初始化函數(shù)屏蔽了。

          9.png

          試了之后,發(fā)現(xiàn)定時器真的有輸出了。

          那么這是怎么一回事?為什么串口還能干擾到定時器的輸出。

          這個時候就要說一說我們的棧了(關(guān)于棧,魚鷹寫過一篇筆記《今天,你的棧溢出了嗎?》)。

          很多關(guān)于棧的話題,基本都是棧溢出,但事實上,還有一個容易忽略的話題是,棧的值不確定。

          我們都知道,函數(shù)進(jìn)入時會進(jìn)行壓棧操作(用于保持寄存器的值),同時如果函數(shù)有局部變量,也可能會從棧中申請空間。

          10.png

          因為局部變量用完即毀,不會占用我們寶貴的 RAM資源,所以很多時候我們會選擇使用局部變量。

          而大部分網(wǎng)上參考例程在使用局部變量時并不規(guī)范,導(dǎo)致問題的發(fā)生。

          現(xiàn)在魚鷹解釋一下為什么串口函數(shù)會影響高級定時器的輸出,而其他普通定時器并沒有受影響。

          當(dāng)串口函數(shù)執(zhí)行時,使用的棧比較大,而在定時器函數(shù)執(zhí)行時,剛好使用了這部分已被修改的??臻g,并且使用時沒有初始化它,導(dǎo)致出現(xiàn)了問題。

          11.png

          那為什么屏蔽了串口就沒有問題呢?

          那是因為單片機(jī)開始運行時,__main 函數(shù)會將棧空間全部清零(在運行到main前完成該工作),如果不運行串口函數(shù),那么棧中的臟數(shù)據(jù)就不會很多,那么定時器函數(shù)的局部變量即使不初始化,也可認(rèn)為就是 0,而這正是定時器需要的默認(rèn)值。

          12.png

          那么為什么普通定時器不受影響呢?拿 TIM_TimeBaseInitTypeDef 結(jié)構(gòu)體來舉例。

          13.png

          基本定時器一般會初始化這幾個變量,但是你查看該結(jié)構(gòu)體的定義時你會發(fā)現(xiàn):

          14.png

          該結(jié)構(gòu)體還有一個變量是專為高級定時器準(zhǔn)備的,你并沒有對它進(jìn)行初始化,此時它可能是任何值,并會直接賦值給高級定時器的寄存器中。

          而關(guān)于輸出的結(jié)構(gòu)體 TIM_OCInitTypeDef 更是如此,很多變量在基本定時器中不會使用,卻會在高級定時器中影響它的輸出功能。

          所以為了解決這個問題,有兩個辦法:

          1、使用庫函數(shù)提前初始化局部變量:

          15.png

          這樣后續(xù)就不用關(guān)心不需要的變量了。

          2、直接在初始化時,將所有的結(jié)構(gòu)體成員變量都初始化一遍,確定沒有任何一個變量遺漏:

          16.png

          魚鷹推薦第二種辦法,這樣高級定時器和普通定時器的代碼可以統(tǒng)一,也能更直觀的看出函數(shù)提供的功能。

          當(dāng)然,兩種方法同時使用也是沒有任何問題的。

          以上就是魚鷹踩的坑,希望對各位道友有所幫助。咱們下期再見!

          *博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。

          接地電阻相關(guān)文章:接地電阻測試方法




          關(guān)鍵詞: PWM

          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉