MTK平台-如何输出80KHZ频率的PWM信号

综述

传音项目的需求,因为smartpa在调试的时候,噪音很大,原因是i2s给的时钟信号不稳定,硬件工程师说能不能尝试用pwm信号当做时钟信号,因此就学习了一下pwm的一些知识,记录下来。

[PWM]AP PWM 使用配置参数说明

** AP端PWM使用配置参数说明**

** 1. 概述**

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

        其中PWM1/2/3为pin脚,其余是复用其他GPIO口的某个mode。

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

  • 只有PWM0/1/2/6可以设置为old mode,其余之外mode的设置没有限制。
  • 实际中只有old mode 和FIFO mode最为常用。其中old mode可以在系统sleep时输出PWM信号。

(3)软件只需在应用driver里面调用如下接口,正确配置参数即可得到相应的PWM信号:pwm_set_spec_config(struct pwm_spec_config *conf)

MTK平台-如何输出80KHZ频率的PWM信号_第1张图片
图1

**2. old mode **

old mode PWM 本质是设定波形频率和占空比

(1)关键配置参数如下:

  • pwm_no:选择需要使用的PWM NUMBER
  • mode:PWM工作模式,此处应该设为PWM_MODE_OLD
  • clk_src:选择时钟源,PWM_CLK_OLD_MODE_BLOCK(52M)或者PWM_CLK_OLD_MODE_32K(32k)
  • clk_div:分频系数,CLK_DIV1, CLK_DIV2等
  • 结构体
    struct _PWM_OLDMODE_REGS { U16 IDLE_VALUE; //idle状态下的输出电平
    U16 GUARD_VALUE; //guard duration的输出电平
    U16 GDUARTION; //guard duration,即两次完整波形间隔时间
    U16 WAVE_NUM; //输出波形数目,为0则一直传输直到PWM_EN disabled
    U16 DATA_WIDTH; //波形周期宽度
    U16 THRESH; //高电平clk数目
    }PWM_MODE_OLD_REGS;

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

其中,

输出频率为:clk_src/clk_div/DATA_WIDTH
占空比为:THRESH/DATA_WIDTH

MTK平台-如何输出80KHZ频率的PWM信号_第2张图片
图2

3. FIFO mode

FIFO mode下PWM波形是按照两个32位DATA的数值输出高低电平。

(1)关键参数

  • 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频率有关,并非完全等于code中写的52M;
  • clk_div:分频系数
  • 结构体
    struct _PWM_MODE_FIFO_REGS {
    U32 IDLE_VALUE; //idle time输出电平
    U32 GUARD_VALUE; //guard duration输出电平
    U32 STOP_BITPOS_VALUE; //停止位,决定data中输出的bit位数,取值为0~63;
    U16 HDURATION; //高电平持续的base clk数目;
    U16 LDURATION; //低电平持续的base clk数目;
    U32 GDURATION; //两个完整波形间隔时间;
    U32 SEND_DATA0; //32位DATA0数值;
    U32 SEND_DATA1; //32为DATA1数值;
    U32 WAVE_NUM; //输出波形数目,若为0则持续输出;
    }PWM_MODE_FIFO_REGS;

(2)输出波形

FIFO MODE输出波形如下:

注意HDURATION、LDURATION只对DATA数据生效,GDURATION采用base clk

MTK平台-如何输出80KHZ频率的PWM信号_第3张图片
图3

若持续输出,则频率计算公式为:

freq = clk_src/clk_div/(DATA高电平数目*HDURATION + DATA低电平数目*LDURATION + GDURATION)

只有输出波形为规则方波的时候才会有占空比:

duty = (DATA高电平数目*HDURATION)/(DATA高电平数目*HDURATION + DATA低电平数目*LDURATION + GDURATION), 其中,GUARD_VALUE为1

实践

步骤一,配置dws文件

MTK平台-如何输出80KHZ频率的PWM信号_第4张图片
dws

这里使用GPIO10,设置默认模式为PWM_C,这里的C代表2,
PWM_A 对应的pwm_no=0
PWM_B 对应的pwm_no=1
PWM_C 对应的pwm_no=2
即:pwm_no:选择需要使用的PWM number, 取值为0~6
步骤二,编写代码
在你需要的地方加入以下设置,我这里加在lcm驱动里
kernel-3.18/drivers/misc/mediatek/lcm/KR070IG1T_6953_CPT/KR070IG1T_6953_CPT.c

#include 

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函数中调用my_set_pwm(2)

static int lcm_probe(struct device *dev)
{
  //省略部分源码
  my_set_pwm(2);//2对应pwm_c
}

酱紫就可以输出pwm信号了


pwm信号

荆轲刺秦王

你可能感兴趣的:(MTK平台-如何输出80KHZ频率的PWM信号)