User Tools

Site Tools


Action disabled: source
prog:mcp560x:20250226-001:index

RT1064學習筆記-FlexPWM輸出 (2025-02-26)

Local Backup

FlexPWM簡介

  • FlexPWM 全名為:Enhanced Flex Pulse Width Modulator,也稱為eFlexPWM,即增強型靈活的脈寬調變器。 RT1064 內部有4 個這種脈寬調變器(FlexPWM)模組,每個脈寬調變器模組有4 個子模組,每個子模組可用於控制單一半橋功率計,且提供故障保護通道。
  • 脈寬調製器(FlexPWM)模組可以組成多種開關組合方式,可產生高度複雜的波形,它可以用於控制各種類型的電機,也是各種開關電源(SMPS)拓撲模型的理想控制器。

主要特點

  • 16位元解析度的中心,邊緣對齊,和非對稱的pwm
  • 每個脈寬調變器(FlexPWM)有4 個子模組;
  • 分數PWM時鐘產生提高解析度的PWM週期和占空比
  • 當精細邊緣位置不可用時,抖動來模擬增強的分辨率
  • 可以作為互補對或獨立通道的PWM輸出
  • 能夠接受有符號的數字PWM產生
  • 每個PWM輸出的兩邊都有獨立的控制
  • 支援同步到外部硬體或其他PWM
  • 雙緩衝PWM暫存器
    • 積分重新加載率從1到16
    • 半循環重載能力
  • 透過hard,每個PWM週期可以產生多個輸出觸發事件
  • 支援雙開關PWM輸出
  • 故障輸入可以分配到控制多個PWM輸出
  • 用於故障輸入的可編程濾波器
  • 獨立可程式PWM輸出極性
  • 獨立的頂部和底部空時插入
  • 每個互補對可以用自己的PWM頻率和死區時間值工作
  • 每個PWM輸出的獨立軟體控制
  • 所有輸出都可以透過程式設計FORCE_OUT事件來同時改變
  • PWM_X引腳可以從每個子模組任意輸出第三個PWM訊號
  • 不用於PWM產生的通道可以用於緩衝輸出比較功能
  • 不用於PWM產生的通道可以用於輸入擷取功能
  • 增強的雙邊緣捕捉功能
  • 為每個互補PWM訊號對提供電源的選項如下:
    • 橫樑模組輸出
    • 外部ADC輸入,考慮ADC高低限位暫存器中設定的值

模組框圖解讀

  • 由圖可知,FlexPWM 的每個子模組由1 個預分頻器、1 個16 位元計數器和6 個16 位元比較器等部分組成,主要有3 個輸出訊號:PWM_X、PWM_A 和PWM_B,其中PWM_A 和PWM_B可以用來輸出PWM/AWM_A 和PWM_B,其中PWM_A 和PWM_B可以用來輸出PWM/PWM_A 和PWM_X 做一個輔助輸出,PWM_PWM_PWM_PWM_ 做一個輔助輸出,而PWM_X 是一個輔助輸出,輸出PWM 波形。
  • 圖中①處,是故障訊號輸入,來自模組匯流排,由XBAR1 的輸出通道來控制,若要正常輸出PWM,必須設定適當的故障狀態,或是禁止故障偵測功能,否則將無法正常輸出PWM!

FlexPWM 子模組的輸出邏輯

  • 圖中PWM23 和PWM45 分別由VAL2/VAL3 和VAL4/VAL5 控制佔空比,來自經過死區處理後的訊號,本程式沒用到死區控制,所以在這裡對死區不做介紹。由圖可知,PWM23和PWM45的輸出處理路徑是一樣的,只是控制訊號不同而已,我們以PWM23 為例,介紹其具體的輸出過程:
    • 1, 用來選擇輸出到下一級的是PWM23 還是PWMAFS[0]的值,由Disable PWM_A 訊號控制。
      當該訊號為0 的時候,PWM23 輸出到下一層,否則PWMAFS[0]的值輸出到下一層。
      很明顯,要正常輸出PWM,必須Disable PWM_A 訊號必須為0。 PWMAFS[0]來自SMx_OCTRL(x=0~3)暫存器。
    • 2, 用於設定是否屏蔽PWM 輸出,
      當MASKA=0 時,可以正常輸出;
      當MASKA=1 時,屏蔽PWM 輸出。
      MASKA 來自PWMx_MASK(x=0~3)暫存器。
    • 3, 用於設定輸出有效訊號極性。
      當POLA=0 時,輸出訊號不反相;
      當POLA=1 時,輸出訊號反相;
      POLA 來自SMx_OCTRL(x=0~3)暫存器。
    • 4, 用於控制PWM 最終是否輸出到PWM_A,由PWM_A_EN、PWMAFS[1]和Disable PWM_A 三個訊號共同控制。
      PWM_A_EN 由PWMx_OUTEN(x=0 ~ 3)暫存器設置,PWMAFS[1]來自SMx_OCTRL(x=0 ~ 3)暫存器。
    • 5, Disable PWM_A 來自故障保護單元,它由FAULT0~3 和Wait Mode、Debug Mode 和Stop Mode 等訊號控制。我們待會重點介紹。
      因此可知,PWM_A 要像正常輸出來自PWM23 的PWM 訊號,就必須設定好對應的控制位元/訊號:Disable PWM_A 必須為0,MASKA 必須為1,PWM_A_EN 必須為1。對於PWM_B的輸出,同樣也要設定類似的位元/訊號。

PWMA 故障訊號控制邏輯

  • 由圖可知Disable PWM_A 主要來自兩個方向:
    • 1,故障輸出(FAULT0~3);
    • 2,MCU 工作模式(Wait/Debug/Stop)。
  • 正常工作時,我們只需要考慮故障輸出,因此我們將重點放在下圖中標註的①~⑥。
    • 1, 二或閘,只要故障輸出或MCU 工作模式輸出有效,則Disable PWM_A 有效(=1)。
    • 2, 四或閘,來自四個故障訊號:FAULT0~FAULT3,只要任一個故障訊號有效(=1),則輸出有效。
    • 3, 故障0(FAULT0)屏蔽位(DISA0),用於設定是否屏蔽來自故障0(FAULT0)的訊號,如果我們不想讓故障0 控制我們的PWM 輸出,則可以設定該位元為0。 DISA0 來自SMx_DISMAP0(x=0 ~ 3),同樣的DISA1 ~ DISA3 也是由此暫存器控制,分別控制FAULT1~FAULT3 的屏蔽。注意:這些位元預設都是1 的!
    • 4, 故障輸入0 到Disable PWM_A 輸出組合路徑屏蔽位,當NOCOMB0 為0 時,FAULT0 有兩條路徑可以輸出到Disable PMW_A:1,通過NOCOMB0 與閘;2,經由FILT 濾波器;當NOCOMB0 為1 時,則只能經由FLIT 路徑輸出到Disable PWM_Aisable。 NOCOMB0 來自PWMx_FCTRL20(x=0 ~ 3)暫存器。同樣的,NOCOMB1~3 也是來自此暫存器。
    • 5, 故障訊號0(FAULT0),來自XBAR1 的輸出。這些故障訊號可以透過XBAR1 映射到相關外部IO 口,從而實現故障檢測。具體的映射關係,詳見《RT1050 參考手冊》第246 頁,Table 3-6。

FlexPWM 子模組的時鐘部分

  • 1, 時脈來源選擇器,由CLK_SEL[1:0]位元設置,我們一般選擇IPBus 時脈作為時脈來源,IPBus 時脈來自IPG_CLK_ROOT(150Mhz)。 CLK_SEL[1:0]來自SMx_CTRL2(x=0~3)暫存器。
  • 2, 時鐘預分頻器,這是8 位元預分頻器,但只能設定固定的幾個分頻值,不能隨意設定!其分頻值可以是:1/2/4/8/16/32/64/128 等7 個值,透過PSRC[2:0]設定。 PSRC[2:0]來自SMx_CTRL(x=0~3)暫存器。
  • 3, 時脈啟用開關,由RUN 位元控制,如果RUN 位元為1,則可以正常輸出時脈;如果RUN 位元為0,則禁止輸出時脈;RUN 位元來自PWMx_MCTRL(x=0~3)暫存器。

FlexPWM 子模組產生PWM 的具體流程

  • FlexPWM 子模組的計數器(CNT),只能工作在向上計數模式(圖中類似三角波的波形)
  • 上圖是FlexPWM 子模組產生中央對齊PWM 的時序圖,因為計數方向是不可改變的,只能修改圖中的③~⑨來實現中央對齊PWM 的輸出。事實上中央對齊、邊緣對齊和非對稱PWM 的輸出,都是透過修改這幾個暫存器來實現的。
  • 注意:FlexPWM 是支援有符號操作的,如果INIT 的值剛好和VAL1 的值相反(值相同,符號相反),則表示是有符號模式,否則表示是無符號模式。
    • 1, PWM_A 波形,其波形是以VAL0 的值中心對稱的。 PWM_A 波形由VAL2 控制上升沿,由VAL3 控制下降沿,只要VAL0-VAL2=VAL3-VAL0,則是中心對稱模式。
    • 2, PWM_B 波形,其波形也是以VAL0 的值中心對稱的。 PWM_B 波形由VAL4 控制上升沿,由VAL5 控制下降沿,只要VAL0-VAL4=VAL5-VAL0,則是中心對稱模式。
    • 3, INIT 暫存器,用於設定CNT 的初始值。
      這是一個有符號16 位元暫存器,它可以設定成負數或正數,圖17.1.5 種設定的INIT 值為0XFF00,即-256,是負數。
      此暫存器用於在每個PWM 週期的啟動時初始化CNT 值(也就是CNT 達到VAL1 溢位後,都會將INIT 的值重新賦值到CNT)。
      此暫存器和VAL1 共同決定是否工作在有符號模式,只要這兩個暫存器的值不剛好相反,則是工作在無符號模式.
      一般建議用無符號模式。
    • 4, VAL0 暫存器,用於設定CNT 的中間值。這是一個有符號16 位元暫存器,該暫存器的值介於INIT 和VAL1 之間,一般等於(VAL1-INIT)/2。
    • 5, VAL1 暫存器,用於設定CNT 計數器的最大值。這是一個有符號16 位元暫存器,該暫存器和INIT 暫存器共同決定是否工作在有符號模式。
    • 6, VAL2 暫存器,用於控制PWM_A 的上升沿。這是一個有符號16 位元暫存器,透過它可以決定PWM_A 波形高電平的起始時間。
    • 7, VAL3 暫存器,用於控制PWM_A 的下降沿。這是一個有符號16 位元暫存器,透過它可以決定PWM_A 波形高電平的結束時間。
      INIT、VAL1、VAL2 和VAL3 共同決定了PWM_A 的波形。
    • 8, VAL4 暫存器,用於控制PWM_B 的上升沿。這是一個有符號16 位元暫存器,透過它可以決定PWM_B 波形高電平的起始時間。
    • 9, VAL5 暫存器,用於控制PWM_B 的下降沿。這是一個有符號16 位元暫存器,透過它可以決定PWM_B 波形高電平的結束時間。
      INIT、VAL1、VAL4 和VAL5 共同決定了PWM_B 的波形。
  • 注意:INIT、VAL0 ~ VAL5 等七個暫存器都是有緩衝的,我們寫入這些暫存器的值不會立即生效,必須設定PWMx_MCTRL(x=0 ~ 3)暫存器的LDOK 位,然後在下一個PWM 週期開始的時候,會將寫入這些暫存器的值載入到緩衝暫存器,然後設定的值才會生效。
  • 圖17.1.5 中是中央對齊模式的設置,如果我們調整INIT 和VAL0~VAL5 的值,則可以實現許多不同模式的PMW 波形輸出。
  • 詳見RT1064RM的54.4.1 P3118

寄存器簡介

初始化暫存器(SM0INIT - SM3INIT) Initial Count Register 在這裡插入圖片描述 此暫存器用於設定計數器(CNT)的起始計數值,支援有符號操作,該暫存器和VAL1 暫存器共同決定了子模組的計數範圍。 如果INIT 和VAL1 暫存器的值相反,則表示有符號操作模式;否則表示無符號操作模式。

數值0 暫存器(SM0VAL0 - SM3VAL0) Value Register 0 在這裡插入圖片描述 此暫存器用於設定計數器(CNT)的中間值,支援有符號操作(由INIT 和VAL1 決定),該暫存器的值介於INIT 和VAL1 之間,一般等於(VAL1-INIT)/2。

數值1 暫存器(SM0VAL1 - SM3VAL1) Value Register 1 在這裡插入圖片描述 圖中英文翻譯: 寫入這個緩衝的讀寫暫存器的16位元有符號值定義了子模組計數器的模計數值(最大計數)。 當達到這個計數值時,計數器會用INIT暫存器的內容重新載入自己,並在重置PWM_X時發出本地同步訊號。 這個暫存器不是位元組可存取的。 NOTE:VAL1暫存器被緩衝。 直到MCTRL[LDOK]被設置,下一個PWM負載週期開始或CTRL[LDMOD]被設置,寫入的值才會生效。 當MCTRL[LDOK]被設定時,不能寫入VAL1。 讀取VAL1是在緩衝區中讀取值。 這並不一定是PWM發生器目前使用的值。 NOTE:當使用FRACVAL1時,對於無符號的應用程序,將VAL1的最大值限制為0xFFFE,對於有符號的應用程序,將VAL1的最大值限制為0x7FFE,以避免由於累積由FRACVAL1定義的小數週期而導致計數器翻轉。 NOTE: 如果VAL1暫存器定義了計時器週期(本地同步被選為計數器初始化訊號),那麼在PWMX輸出上就不能實現100%的佔空比。 當計數達到VAL1後,PWMX輸出在每個週期中至少有一個計數是低的。 當主同步訊號(僅由子模組0的Local Sync產生)用於控制定時器週期時,VAL1暫存器可以自由用於其他功能,如PWM產生,而不受佔空比限制。

此暫存器用於設定計數器(CNT)的最大值,FlexPWM 子模組的計數器(CNT)計數範圍為:INIT≤CNT≤VAL1。另外,此暫存器和INIT 暫存器一起決定了是否使用有符號操作,如果VAL1和INIT 暫存器的值相反,則表示有符號操作模式;否則表示無符號操作模式。 另外,VAL1 暫存器還具有小數(分數)位元功能,透過SMx_FRACVAL1(x=0 ~ 3)設置,不過我們一般不用這個分數功能,所以不需要設定FRACVAL1 暫存器。同樣的,對於VAL2 ~ VAL5也都是有對應的FRACVAL2~FRACVAL5。

數值2 暫存器(SM0VAL2 - SM3VAL2) Value Register 2 在這裡插入圖片描述此暫存器用於設定PWM_A(PWM23)波形上升沿,決定了PWM_A 高電平的起始位置。

數值3 暫存器(SM0VAL3 - SM3VAL3) Value Register 3 在這裡插入圖片描述 這個暫存器用來設定PWM_A(PWM23)波形下降沿,決定了PWM_A 高電平的結束位置。 透過VAL3和VAL2 這兩個暫存器,我們就可以決定PWM_A 的高電平脈寬和位置, 透過INIT 和VAL1,我們就可以決定PWM_A 的週期。 因此,透過INIT、VAL1、VAL2 和VAL3 就可以確定PWM_A 的整個波形。 類似的,透過INIT、VAL1、VAL4 和VAL5 就可以確定PWM_B 的整個波形, 這裡就不再單獨介紹VAL4 和VAL5 這兩個暫存器了。

故障保護禁止暫存器(SM0DISMAP0 - SM3DISMAP0) Fault Disable Mapping Register 0 在這裡插入圖片描述 此暫存器用於設定哪些PWM 接腳禁止故障保護功能,透過設定此暫存器,可以屏蔽PWM 輸出時的故障保護。 DIS0A[3:0]用於屏蔽PWM_A 的故障輸入3 ~ 0(FAULT3 ~ FAULT0),每個位元控制1個故障通道,且一一對應。同樣的DIS0B[3:0]和DIS0X[3:0]分別控制PWM_B 和PWM_X 的故障輸入3 ~ 0。

注意:故障保護功能,預設是全開的(SMx_DISMAP0 預設值全1),因此我們要想正常輸出PWM,則需要屏蔽相關故障,或透過XBAR 設定故障輸入為非有效。

控制暫存器(SM0CTRL - SM3CTRL)

在這裡插入圖片描述 Control Register LDFQ[15:12]位元:用於控制暫存器載入頻率(即把寫入VAL0~VAL5 等暫存器快取的值載入到暫存器裡面,生效),載入頻率以HALF 位元和FULL 位元為基礎。例如設定:LDFQ[3:0]=0100,HALF=0, FULL=1,則表示每5個PWM計數週期載入一次。 我們一般設定LDFQ[3:0]=0000 ,HALF=0,FULL=1,表示每個PWM 計數週期載入一次。

HALF 位元:用於啟用半週期加載,當啟用該位元時,只要CNT 和VAL0 值相等,則表示一個加載週期(每個PWM 週期只可能出現一次,所以他們是相等的),至於到底要多少個加載週期才真正加載一次,則需要看LDFQ[3:0]的設定。

FULL 位:用於啟用全週期加載,當啟用該位元時,只要CNT 和VAL1 值相等,則表示一個加載週期(每個PWM 週期也​​只能出現一次),至於到底要多少個加載週期才真正加載一次,則需要看LDFQ[3:0]的設定。

想要把暫存器緩衝裡面的值載入到暫存器,有兩個方法: 1, 設定HALF 位元或FULL 位元為1,或都設為1。 2, 設定LDMOD 位元為1。 不過這兩個方法都有一個大前提,就是設定:SMx_MCTRL(x=0~3)暫存器的LDOK 位元為1,只有LDOK 為1 時,這兩個方法才有效。

COMPMODE 位元:用於設定CNT 和VALn(n=0~5)的比較模式。位元為0 時,表示相等時視為符合;該位元為1 時,表示大於等於時,視為符合;我們一般設定該位元為0。

PRSC[2:0]位元:用於設定PWM 輸入頻率的預分頻係數。範圍:0~7,表示2^PRSC[2:0]分頻。

LDMOD 位元:用於設定暫存器載入模式。當LDMOD=0 時,表示由HALF、FULL 和FREQ[3:0]共同決定載入時機。當LDMOD=1 時,表示只要SMx_MCTRL(x=0~3)暫存器的LDOK 位元為1,就立即進行載入操作。我們預設LDMOD 設為0,使用載入時機可控的方式。

控制暫存器2 (SM0CTRL2 - SM3CTRL2) Control 2 Register 在這裡插入圖片描述 DBGEN 位元:用於設定是否啟用調試模式下PWM 繼續運作。一般設定為1,使能調試模式運作。

INDEP 位元:用於設定PWM_A 和PWM_B 工作在獨立模式,還是在互補輸出模式。本章我們設定為1,PWM_A 和PWM_B 工作在獨立模式。

CLK_SEL[1:0]位,用於設定FlexPWM 子模組的時脈來源。 00,選擇IPG_CLK_ROOT 作為時脈來源; 01,選擇EXT_CLK 作為時脈來源; 10,選擇子模組0 輸出的AUX_CLK 作為時脈來源; 11,保留; 我們一般設定為00,也就是選擇IPG_CLK_ROOT 作為時脈來源,可以得到150MHz 的時脈來源。

輸出使能暫存器(OUTEN) 輸出使能暫存器

在這裡插入圖片描述 此暫存器用於控制PWMx(x=0~3,下同)各個子模組PWM_A、PWM_B 和PWM_X 的輸出啟用。 其中:PWMA_EN[3:0]:用於控制PWMx 的子模組3 0(SM3 SM0)的PWM_A 的輸出。 類似的,PWMB_EN[3:0]和PWMX_EN[3:0]分別用來控制子模組3~0 的PWM_B 和PWM_X 輸出。

主控制暫存器(MCTRL) 主控制暫存器

在這裡插入圖片描述 RUN[3:0]位,用於設定是否啟用子模組3 ~ 0(SM3 ~ SM0)的時鐘。要想子模組能正常運作,必須先設定該子模組對應的RUN 位元為1。例如我們要讓能PWM2 的子模組3,則必須設定PWM2_MCTRL 暫存器的bit10 為1。

LDOK[3:0]位,用於啟用子模組3 ~ 0(SM3 ~ SM0)的暫存器載入。這些暫存器包括INIT、 VAL0~VAL5 等,我們要想寫入這些暫存器的值生效,就必須設定對應的LDOK 位元為1,然後在下一個載入週期進行載入(相關介紹見前面介紹)。例如我們要讓能PWM2 的子模組3 的暫存器加載,則必須設定PWM2_ LDOK 暫存器的bit3 為1。

FSL函式庫函數詳解及FlexPWM配置流程 FlexPWM 相關的函式庫函數在fsl_pwm.c 和fsl_pwm.h 這兩個檔案中。

1.設定GPIO復用功能 將GPIO3_IO03 的複用功能設定為PWM2 的PWM_B 通道,方法如下:

IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_03_FLEXPWM2_PWMB03,0); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_03_FLEXPWM2_PWMB03,0x10B0); 1 2 2.使能FlexPWM時鐘 使用函數CLOCK_EnableClock 啟用FlexPWM2 時鐘,使用方法如下:

CLOCK_EnableClock(kCLOCK_Pwm2) 1 此函數會被FlexPWM2 定時器初始化函數PWM_Init 調用,所以不需要我們顯示的調用。

3.初始化FlexPWM FlexPWM2 的初始化透過函數PWM_Init 來完成,此函數原型如下:

status_t PWM_Init(PWM_Type *base, pwm_submodule_t subModule, const pwm_config_t *config) 1 第一個參數PWM_Type *base:指定初始化哪一個PWM, 可選參數PWM1,PWM2,PWM3,PWM4,在MIMXRT1064.h中34634行 第二個參數pwm_submodule_t subModule:此參數指定要初始化的是哪個pwm子模組 Submodule=子模組

/*! @brief List of PWM submodules */ typedef enum _pwm_submodule {

  kPWM_Module_0 = 0U, /*!< Submodule 0 */
  kPWM_Module_1,      /*!< Submodule 1 */
  kPWM_Module_2,      /*!< Submodule 2 */
  kPWM_Module_3       /*!< Submodule 3 */

} pwm_submodule_t; 1 2 3 4 5 6 7 8 第三個參數const pwm_config_t *config:此參數是指向結構體pwm_config_t 的指針,此結構體定義如下:

typedef struct _pwm_config {

  bool enableDebugMode;                    /*!< true: PWM continues to run in debug mode;debug 模式下 PWM 是否运行
                                                false: PWM is paused in debug mode wait 模式下 PWM 是否运行*/
  bool enableWait;                         /*!< true: PWM continues to run in WAIT mode;falut 滤波器计数值
                                                false: PWM is paused in WAIT mode falut 滤波器周期*/
  pwm_init_source_t initializationControl; /*!< Option to initialize the counter */
  pwm_clock_source_t clockSource;          /*!< Clock source for the counter PWM 时钟源*/
  pwm_clock_prescale_t prescale;           /*!< Pre-scaler to divide down the clock PWM 分频值*/
  pwm_chnl_pair_operation_t pairOperation; /*!< Channel pair in indepedent or complementary mode设置一对 PWM 是独立运行还是互补运行 */
  pwm_register_reload_t reloadLogic;       /*!< PWM Reload logic setup PWM 加载模式,全周期还是半周期*/
  pwm_reload_source_select_t reloadSelect; /*!< Reload source select */
  pwm_load_frequency_t reloadFrequency;    /*!< Specifies when to reload, used when user's choice
                                                is not immediate reload */
  pwm_force_output_trigger_t forceTrigger; /*!< Specify which signal will trigger a FORCE_OUT */

} pwm_config_t;

1 2 3 4 5 6 7 8 9 10 11 12 十三 14 15 16 FlexPWM 的設定參數還是不少的,而且大部分都是枚舉類型的,我們這裡就看一下重要的配置選項,其他的配置選項根據實際使用情況自行查閱相關文件。 首先來看clockSource 這個成員變量,這是個pwm_clock_source_t 類型的,此類型定義如下:

/*! @brief PWM clock source selection.*/ typedef enum _pwm_clock_source {

  kPWM_BusClock = 0U,  /*!< The IPBus clock is used as the clock IPBus 作为 PWM 时钟源 */
  kPWM_ExternalClock,  /*!< EXT_CLK is used as the clock 外部 CLK 作为 PWM 时钟源*/
  kPWM_Submodule0Clock /*!< Clock of the submodule 0 (AUX_CLK) is used as the source clock 子模块 0 作为 PWM 时钟源*/

} pwm_clock_source_t; 1 2 3 4 5 6 7 成員變數prescale 用來設定分頻,變數類型為pwm_clock_prescale_t,此類型定義如下:

/*! @brief PWM prescaler factor selection for clock source*/ typedef enum _pwm_clock_prescale {

  kPWM_Prescale_Divide_1 = 0U, /*!< PWM clock frequency = fclk/1 */
  kPWM_Prescale_Divide_2,      /*!< PWM clock frequency = fclk/2 */
  kPWM_Prescale_Divide_4,      /*!< PWM clock frequency = fclk/4 */
  kPWM_Prescale_Divide_8,      /*!< PWM clock frequency = fclk/8 */
  kPWM_Prescale_Divide_16,     /*!< PWM clock frequency = fclk/16 */
  kPWM_Prescale_Divide_32,     /*!< PWM clock frequency = fclk/32 */
  kPWM_Prescale_Divide_64,     /*!< PWM clock frequency = fclk/64 */
  kPWM_Prescale_Divide_128     /*!< PWM clock frequency = fclk/128 */

} pwm_clock_prescale_t; 1 2 3 4 5 6 7 8 9 10 11 12 成員變數reloadLogic 設定載入模式,類型為pwm_register_reload_t,此類型定義如下:

/*! @brief Options available on how to load the buffered-registers with new values */ typedef enum _pwm_register_reload {

  kPWM_ReloadImmediate = 0U,     /*!< Buffered-registers get loaded with new values as soon as LDOK bit is set */
  kPWM_ReloadPwmHalfCycle,       /*!< Registers loaded on a PWM half cycle */
  kPWM_ReloadPwmFullCycle,       /*!< Registers loaded on a PWM full cycle */
  kPWM_ReloadPwmHalfAndFullCycle /*!< Registers loaded on a PWM half & full cycle */

} pwm_register_reload_t; 1 2 3 4 5 6 7 8 成員變數pairOperation用來設定同一個PWM子模組的兩個通道是互補輸出還是獨立輸出

/*! @brief Options available for the PWM A & B pair operation */ typedef enum _pwm_chnl_pair_operation {

  kPWM_Independent = 0U,  /*!< PWM A & PWM B operate as 2 independent channels */
  kPWM_ComplementaryPwmA, /*!< PWM A & PWM B are complementary channels, PWM A generates the signal */
  kPWM_ComplementaryPwmB  /*!< PWM A & PWM B are complementary channels, PWM B generates the signal */

} pwm_chnl_pair_operation_t; 1 2 3 4 5 6 7 函數PWM_GetDefaultConfig用於配置結構體為預設參數,預設參數設定如下:

/*! * brief Fill in the PWM config struct with the default settings * * The default values are: * code * config→enableDebugMode = false; * config→enableWait = false; * config→reloadSelect = kPWM_LocalReload; * config→clockSource = kPWM_BusClock; * config→prescale = kPWM_Prescale_Divide_1; * config→initializationControl = kPWM_Initialize_LocalSync; * config→forceTrigger = kPWM_Force_Local; * config→reloadFrequency = kPWM_LoadEveryOportunity; * config→reloadLogic = kPWM_ReloadImmediate; * config→pairOperation = kPWM_Independent; * endcode * param config Pointer to user's PWM config structure. */ void PWM_GetDefaultConfig(pwm_config_t *config) {

  assert(config);
  /* Initializes the configure structure to zero. */
  (void)memset(config, 0, sizeof(*config));
  /* PWM is paused in debug mode */
  config->enableDebugMode = false;
  /* PWM is paused in wait mode */
  config->enableWait = false;
  /* PWM module uses the local reload signal to reload registers */
  config->reloadSelect = kPWM_LocalReload;
  /* Use the IP Bus clock as source clock for the PWM submodule */
  config->clockSource = kPWM_BusClock;
  /* Clock source prescale is set to divide by 1*/
  config->prescale = kPWM_Prescale_Divide_1;
  /* Local sync causes initialization */
  config->initializationControl = kPWM_Initialize_LocalSync;
  /* The local force signal, CTRL2[FORCE], from the submodule is used to force updates */
  config->forceTrigger = kPWM_Force_Local;
  /* PWM reload frequency, reload opportunity is PWM half cycle or full cycle.
   * This field is not used in Immediate reload mode
   */
  config->reloadFrequency = kPWM_LoadEveryOportunity;
  /* Buffered-registers get loaded with new values as soon as LDOK bit is set */
  config->reloadLogic = kPWM_ReloadImmediate;
  /* PWM A & PWM B operate as 2 independent channels */
  config->pairOperation = kPWM_Independent;

}

1 2 3 4 5 6 7 8 9 10 11 12 十三 14 15 16 17 18 19 20 21 22 23 24 二十五 二十六 二十七 二十八 二十九 三十 31 三十二 33 三十四 三十五 三十六 三十七 三十八 三十九 40 41 四十二 43 四十四 四十五 四十六 四十七 四十八 設定PWM2的子模組3可以用以下程式碼

pwm_config_t pwm2sm3_config; PWM2 模块 3 配置结构体 初始化 PWM2 模块 3 的通道 B PWM_GetDefaultConfig(&pwm2sm3_config); 先初始化为默认配置 pwm2sm3_config.clockSource=kPWM_BusClock; 时钟源为 IP BUS=150MHz pwm2sm3_config.prescale= kPWM_Prescale_Divide_128; 设置 128 分频 pwm2sm3_config.reloadLogic=kPWM_ReloadPwmFullCycle; 全周期更新 pwm2sm3_config.pairOperation=kPWM_Independent; PMWA PWMB 独立模式 PWM_Init(PWM2,kPWM_Module_3,&pwm2sm3_config); 初始化 PWM2 模块 3 1 2 3 4 5 6 7 8 4.關閉FlexPWM的故障偵測功能 透過設定SM3_DISMAP0 暫存器為0,我們可以屏蔽子模組3 的故障偵測功能,從而可以正常輸出PWM。否則必須設定XBAR 才可以正常輸出PWM,程式碼如下:

屏蔽故障检测功能 PWM2→SM[3].DISMAP[0]=0; 1 2 5.配置PWM2的PWM通道 上面我們都是配置的PWM2,具體到某個通道的時候還是需要配置的,此函數原型如下: status_t PWM_SetupPwm(PWM_Type *base, pwm_submodule_t subModule, const pwm_signal_param_t *chnlParams, uint8_t numOfChnls, pwm_mode_t mode, uint32_t pwmFreq_Hz, uint32_t srcClock_Hz) 1 2 3 4 5 6 7 第1個參數PWM_Type *base:指定初始化哪一個PWM 第2個參數pwm_submodule_t subModule:此參數指定要初始化的是哪個pwm子模組 第3個參數const pwm_signal_param_t *chnlParams:此參數為pwm_signal_param_t 類型的成員變量,用來設定通道配置參數。 此參數為一個數組,因為PWM 有兩個通道,每個通道都需要一個配置參數。結構體pwm_signal_param_t 定義如下: /*! @brief Structure for the user to define the PWM signal characteristics */ typedef struct _pwm_signal_param { pwm_channels_t pwmChannel; /*!< PWM channel being configured; PWM A or PWM B PWM 通道:PWM A 或 PWM B*/ uint32_t dutyCyclePercent; /*!< PWM pulse width, value should be between 0 to 100 0=inactive signal(0% duty cycle)… PWM 占空比百分比,0~100 表示 0%~ 100% 100=always active signal (100% duty cycle)*/ pwm_level_select_t level; /*!< PWM output active level select PWM 输出有效电平*/ uint16_t deadtimeValue; /*!< 死区值The deadtime value; only used if channel pair is operating in complementary mode */ } pwm_signal_param_t; 1 2 3 4 5 6 7 8 9 10 第4個參數uint8_t numOfChnls:要設定的通道數,一個子模組有2 個通道:PWMA 和PWMB,因此此參數最大為2,此參數也就是chnlParams 這個陣列的大小。 第5個參數pwm_mode_t mode:PWM 對齊工作模式,可選模式如下: /*! @brief PWM operation mode */ typedef enum _pwm_mode { kPWM_SignedCenterAligned = 0U, /*!< Signed center-aligned 有符号的中央对齐模式*/ kPWM_CenterAligned, /*!< Unsigned cente-aligned 无符号的中央对齐模式*/ kPWM_SignedEdgeAligned, /*!< Signed edge-aligned 有符号边沿对齐*/ kPWM_EdgeAligned /*!< Unsigned edge-aligned 无符号边沿对齐*/ } pwm_mode_t; 1 2 3 4 5 6 7 8 第6個參數uint32_t pwmFreq_Hz:設定PWM 的頻率,單位為HZ。 第7個參數uint32_t srcClock_Hz:設定PWM 時脈來源頻率,單位為HZ,我們前面設定PWM2 的時脈來源為IPBus時鐘,也就是150MHz,所以此參數要設定為150000000,我們也可以直接使用函數CLOCK_GetFreq 來取得IPGBus 時鐘,程式碼如下: CLOCK_GetFreq(kCLOCK_IpgClk); 1 範例 如果我們要設定PWMB 頻道頻率為10KHz,佔空比為50%,那麼就可以使用以下設定程式碼: u32 sourceclock; 设置 PWM2_PWMB 通道 sourceclock=CLOCK_GetFreq(kCLOCK_IpgClk); PWMB pwm_ignal.pwmChannel=kPWM_PwmB; PWM 通道 B pwm_ignal.level=kPWM_HighTrue; 高电平有效 pwm_ignal.dutyCyclePercent=50; 50%占空比 设置 PWM2,中央对齐模式 PWM_SetupPwm(PWM2, PWM2 kPWM_Module_3, PWM2 的子模块 3 &pwm_ignal, PWM 通道配置参数结构体 1, 配置一个 PWM 通道 kPWM_CenterAligned, 无符号中央对齐模式 10000, PWM 频率为 10KHz sourceclock); PWM 时钟源为 150MHz

PWM_SetPwmLdok(PWM2,kPWM_Control_Module_3,true); 设置 PWM 的 load ok 位 1 2 3 4 5 6 7 8 9 10 11 12 十三 14 15 16 17 6.開啟PWM2 設定好PWM2 以及對應的頻道以後就可以開啟PWM2 了,PWM2 開啟函數為PWM_StartTimer,此函數原型如下: PWM_StartTimer(PWM_Type *base, uint8_t subModulesToStart) 1 第1個參數PWM_Type *base:指定初始化哪一個PWM 第2個參數uint8_t subModulesToStart:指定開啟PWM 哪一個子模組,選用配置參數如下: /*! @brief Options for submodule master control operation */ typedef enum _pwm_module_control { kPWM_Control_Module_0 = (1U « 0), /*!< Control submodule 0's start/stop,buffer reload operation */ kPWM_Control_Module_1 = (1U « 1), /*!< Control submodule 1's start/stop,buffer reload operation */ kPWM_Control_Module_2 = (1U « 2), /*!< Control submodule 2's start/stop,buffer reload operation */ kPWM_Control_Module_3 = (1U « 3) /*!< Control submodule 3's start/stop,buffer reload operation */ } pwm_module_control_t; 1 2 3 4 5 6 7 8 範例 開啟PWM2的子模組3的程式碼如下: PWM_StartTimer(PWM2,kPWM_Control_Module_3); 开启 PWM 1 7.設定佔空比 如果我們想要控制PWM的輸出佔空比,我們可以使用PWM_UpdatePwmDutycycle,此函數的原型如下:

/*! * brief Updates the PWM signal's dutycycle. * * The function updates the PWM dutycyle to the new value that is passed in. * If the dead time insertion logic is enabled then the pulse period is reduced by the * dead time period specified by the user. * * param base PWM peripheral base address * param subModule PWM submodule to configure * param pwmSignal Signal (PWM A or PWM B) to update * param currPwmMode The current PWM mode set during PWM setup * param dutyCyclePercent New PWM pulse width, value should be between 0 to 100 * 0=inactive signal(0% duty cycle)… * 100=active signal (100% duty cycle) */ void PWM_UpdatePwmDutycycle(PWM_Type *base,

                          pwm_submodule_t subModule,
                          pwm_channels_t pwmSignal,
                          pwm_mode_t currPwmMode,
                          uint32_t dutyCyclePercent)

1 2 3 4 5 6 7 8 9 10 11 12 十三 14 15 16 17 18 19 20 第1個參數PWM_Type *base:指定初始化哪一個PWM 第2個參數pwm_submodule_t subModule:此參數指定要初始化的是哪個pwm子模組 第3個參數pwm_channels_t pwmSignal:指定要設定哪個通道,可選參數如下

/*! @brief List of PWM channels in each module */ typedef enum _pwm_channels {

  kPWM_PwmB = 0U,
  kPWM_PwmA,
  kPWM_PwmX

} pwm_channels_t; 1 2 3 4 5 6 7 第4個參數pwm_mode_t currPwmMode:目前PWM 對齊模式,有/無符號中央/邊緣對齊模式。可選參數如下:

/*! @brief PWM operation mode */ typedef enum _pwm_mode {

  kPWM_SignedCenterAligned = 0U, /*!< Signed center-aligned */
  kPWM_CenterAligned,            /*!< Unsigned cente-aligned */
  kPWM_SignedEdgeAligned,        /*!< Signed edge-aligned */
  kPWM_EdgeAligned               /*!< Unsigned edge-aligned */

} pwm_mode_t; 1 2 3 4 5 6 7 8 第5個參數uint32_t dutyCyclePercent:佔空比,百分比模式。 0~100 表示佔空比0%~100%。

範例 #include “flexpwm.h”

/ * @description: 初始化PWM2_SM3 * @param {uint16_t} psc 预分频系数 0-7 代表1-128 * @param {uint32_t} fre PWM频率 单位hz * @param {uint8_t} duty 占空比 单位% * @return {*} * @author: ShiShengjie */ void PWM2_SM3_PWMAB_Init(uint16_t psc,uint32_t fre,uint8_t duty) { uint32_t sourceclock; pwm_config_t PWM2SM3_config; pwm_clock_prescale_t pwm_prescale=(pwm_clock_prescale_t)psc; pwm_signal_param_t pwm_signal; 配置IO口 IOMUXC_SetPinMux(IOMUXC_GPIO_B1_02_FLEXPWM2_PWMA03,0); IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_02_FLEXPWM2_PWMA03,0x10B0); IOMUXC_SetPinMux(IOMUXC_GPIO_B1_03_FLEXPWM2_PWMB03,0); IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_03_FLEXPWM2_PWMB03,0x10B0); PWM_GetDefaultConfig(&PWM2SM3_config); PWM2SM3_config.clockSource=kPWM_BusClock;时钟源为IPBUS PWM2SM3_config.prescale=pwm_prescale;分频为输入参数psc PWM2SM3_config.reloadLogic=kPWM_ReloadPwmFullCycle;全周期更新 PWM2SM3_config.pairOperation=kPWM_Independent;PWMA PWMB独立模式 PWM_Init(PWM2, kPWM_Module_2, &PWM2SM3_config); 屏蔽故障检测功能 PWM2→SM[3].DISMAP[0]=0; 设置PWMB通道 sourceclock = CLOCK_GetFreq(kCLOCK_IpgClk); PWMB pwm_signal.pwmChannel=kPWM_PwmB;PWM通道B pwm_signal.dutyCyclePercent=duty;占空比,输入参数duty pwm_signal.level=kPWM_HighTrue;高电平有效 设置PWM2,中央对齐模式 哪个PWM,子模块,通道参数,通道数,对齐模式,频率input,时钟频率 PWM_SetupPwm(PWM2, kPWM_Module_3, &pwm_signal, 1, kPWM_CenterAligned, fre, sourceclock); PWM_SetPwmLdok(PWM2,kPWM_Control_Module_3,true);设置PWM的load ok位 PWM_StartTimer(PWM2, kPWM_Module_3);开启定时器 } /** * @description: 更新指定通道的占空比 * @param {uint8_t} duty 占空比 * @return {*} * @author: ShiShengjie */ void PWM2_SM3_DutySet(uint8_t duty) { 更新占空比 PWM_UpdatePwmDutycycle(PWM2, kPWM_Module_3, kPWM_PwmB, kPWM_CenterAligned, duty); 设置PWM的load ok位 PWM_SetPwmLdok(PWM2,kPWM_Control_Module_3,true); } * 本文參考正點原子RT1052開髮指南修改編輯。 ====== ====== Back ====== ====== <html> <!– PDF for A4-Portrait: PDF for A4-Landscape: PDF for iPad Note: search?q=work-note%3A2024-08%3A12&amp;btnI=lucky Youtube: search?q=large%3AXXXXX&amp;btnI=lucky Code Highlight: <sxh php; first-line: 70; highlight: [89,92]; title: New title attribute in action> –> </html>

prog/mcp560x/20250226-001/index.txt · Last modified: 2025/02/26 17:59 (external edit)