MTK平臺(tái)-如何輸出80KHZ頻率的PWM信號(hào)

綜述

傳音項(xiàng)目的需求,因?yàn)閟martpa在調(diào)試的時(shí)候,噪音很大,原因是i2s給的時(shí)鐘信號(hào)不穩(wěn)定,硬件工程師說(shuō)能不能嘗試用pwm信號(hào)當(dāng)做時(shí)鐘信號(hào),因此就學(xué)習(xí)了一下pwm的一些知識(shí),記錄下來(lái)。

[PWM]AP PWM 使用配置參數(shù)說(shuō)明

** AP端PWM使用配置參數(shù)說(shuō)明**

** 1. 概述**

(1)目前平臺(tái)AP端一般有7路PWM:PWM0/1/2/3/4/5/6。

        其中PWM1/2/3為pin腳,其余是復(fù)用其他GPIO口的某個(gè)mode。

(2)AP端PWM有5種工作模式:OLD MODE/FIFO MODE/MEMORY MODE/RANDOM MODE/SEQ MODE.

  • 只有PWM0/1/2/6可以設(shè)置為old mode,其余之外mode的設(shè)置沒(méi)有限制。
  • 實(shí)際中只有old mode 和FIFO mode最為常用。其中old mode可以在系統(tǒng)sleep時(shí)輸出PWM信號(hào)。

(3)軟件只需在應(yīng)用driver里面調(diào)用如下接口,正確配置參數(shù)即可得到相應(yīng)的PWM信號(hào):pwm_set_spec_config(struct pwm_spec_config *conf)

圖1

**2. old mode **

old mode PWM 本質(zhì)是設(shè)定波形頻率和占空比

(1)關(guān)鍵配置參數(shù)如下:

  • pwm_no:選擇需要使用的PWM NUMBER
  • mode:PWM工作模式,此處應(yīng)該設(shè)為PWM_MODE_OLD
  • clk_src:選擇時(shí)鐘源,PWM_CLK_OLD_MODE_BLOCK(52M)或者PWM_CLK_OLD_MODE_32K(32k)
  • clk_div:分頻系數(shù),CLK_DIV1, CLK_DIV2等
  • 結(jié)構(gòu)體
    struct _PWM_OLDMODE_REGS { U16 IDLE_VALUE; //idle狀態(tài)下的輸出電平
    U16 GUARD_VALUE; //guard duration的輸出電平
    U16 GDUARTION; //guard duration,即兩次完整波形間隔時(shí)間
    U16 WAVE_NUM; //輸出波形數(shù)目,為0則一直傳輸直到PWM_EN disabled
    U16 DATA_WIDTH; //波形周期寬度
    U16 THRESH; //高電平clk數(shù)目
    }PWM_MODE_OLD_REGS;

(2)old mode的輸出波形如下:

其中,

輸出頻率為:clk_src/clk_div/DATA_WIDTH
占空比為:THRESH/DATA_WIDTH

圖2

3. FIFO mode

FIFO mode下PWM波形是按照兩個(gè)32位DATA的數(shù)值輸出高低電平。

(1)關(guān)鍵參數(shù)

  • pwm_no:選擇需要使用的PWM number, 取值為0~6;
  • mode:PWM工作模式,選擇PWM_MODE_FIFO;
  • clk_src:PWM_CLK_NEW_MODE_BLOCK(即PWM_BLCK)或者PWM_CLK_NEW_MODE_BLOCK_DIV_BY_1625,需要注意的是PWM_BLCK和DDR頻率有關(guān),并非完全等于code中寫(xiě)的52M;
  • clk_div:分頻系數(shù)
  • 結(jié)構(gòu)體
    struct _PWM_MODE_FIFO_REGS {
    U32 IDLE_VALUE; //idle time輸出電平
    U32 GUARD_VALUE; //guard duration輸出電平
    U32 STOP_BITPOS_VALUE; //停止位,決定data中輸出的bit位數(shù),取值為0~63;
    U16 HDURATION; //高電平持續(xù)的base clk數(shù)目;
    U16 LDURATION; //低電平持續(xù)的base clk數(shù)目;
    U32 GDURATION; //兩個(gè)完整波形間隔時(shí)間;
    U32 SEND_DATA0; //32位DATA0數(shù)值;
    U32 SEND_DATA1; //32為DATA1數(shù)值;
    U32 WAVE_NUM; //輸出波形數(shù)目,若為0則持續(xù)輸出;
    }PWM_MODE_FIFO_REGS;

(2)輸出波形

FIFO MODE輸出波形如下:

注意HDURATION、LDURATION只對(duì)DATA數(shù)據(jù)生效,GDURATION采用base clk

圖3

若持續(xù)輸出,則頻率計(jì)算公式為:

freq = clk_src/clk_div/(DATA高電平數(shù)目*HDURATION + DATA低電平數(shù)目*LDURATION + GDURATION)

只有輸出波形為規(guī)則方波的時(shí)候才會(huì)有占空比:

duty = (DATA高電平數(shù)目*HDURATION)/(DATA高電平數(shù)目*HDURATION + DATA低電平數(shù)目*LDURATION + GDURATION), 其中,GUARD_VALUE為1

實(shí)踐

步驟一,配置dws文件

dws

這里使用GPIO10,設(shè)置默認(rèn)模式為PWM_C,這里的C代表2,
PWM_A 對(duì)應(yīng)的pwm_no=0
PWM_B 對(duì)應(yīng)的pwm_no=1
PWM_C 對(duì)應(yīng)的pwm_no=2
即:pwm_no:選擇需要使用的PWM number, 取值為0~6
步驟二,編寫(xiě)代碼
在你需要的地方加入以下設(shè)置,我這里加在lcm驅(qū)動(dòng)里
kernel-3.18/drivers/misc/mediatek/lcm/KR070IG1T_6953_CPT/KR070IG1T_6953_CPT.c

#include <mt-plat/mt_pwm.h>

int my_set_pwm(int pwm_num)
{
            
    struct pwm_spec_config pwm_setting;

    memset(&pwm_setting, 0, sizeof(struct pwm_spec_config));
    pwm_setting.pwm_no = pwm_num;
    pwm_setting.mode = PWM_MODE_OLD;
    printk("zcf my_set_pwm  pwm_no=%d\n",pwm_num);
    //LEDS_DEBUG("led_set_pwm: mode=%d,pwm_no=%d\n", led->nled_mode,
      //     pwm_num);
    /* We won't choose 32K to be the clock src of old mode 
      because of system performance. */
    /* The setting here will be clock src = 26MHz, 
        CLKSEL = 26M/1625 (i.e. 16K) */
    pwm_setting.clk_src = PWM_CLK_OLD_MODE_BLOCK; //pwm_setting.pmic_pad = 0;

    pwm_setting.PWM_MODE_OLD_REGS.THRESH = 66; 
    pwm_setting.clk_div = CLK_DIV1;//CLK_DIV1 = 1
    pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH = 133;

    pwm_setting.PWM_MODE_FIFO_REGS.IDLE_VALUE = 0;
    pwm_setting.PWM_MODE_FIFO_REGS.GUARD_VALUE = 0;
    pwm_setting.PWM_MODE_FIFO_REGS.GDURATION = 0;
    pwm_setting.PWM_MODE_FIFO_REGS.WAVE_NUM = 0;
    pwm_set_spec_config(&pwm_setting);

    return 0;
} 

注意
PWM_CLK_OLD_MODE_BLOCK=26KMHZ
輸出頻率為:clk_src/clk_div/DATA_WIDTH
26000/1/133=195MHZ
占空比為:THRESH/DATA_WIDTH
66/133=1/2

最后在probe函數(shù)中調(diào)用my_set_pwm(2)

static int lcm_probe(struct device *dev)
{
  //省略部分源碼
  my_set_pwm(2);//2對(duì)應(yīng)pwm_c
}

醬紫就可以輸出pwm信號(hào)了


pwm信號(hào)

荊軻刺秦王

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容