PWM使用参考

Version 1.0


1. 概述

本文描述通过提供的硬件PWM如何产生特定的波型。


1.1. Default PWM Pad

PWM 00 -> PAD_PM_GPIO0
PWM 01 -> PAD_PM_GPIO1
PWM 02 -> PAD_PM_GPIO2
PWM 03 -> PAD_PM_GPIO3
PWM 04 -> PAD_TTL13
PWM 05 -> PAD_TTL14
PWM 06 -> PAD_SPI0_DO
PWM 07 -> PAD_FUART_RX
PWM 08 -> PAD_GPIO8
PWM 09 -> PAD_GPIO9
PWM 10 -> PAD_GPIO10

PWM与GPIO对应关系:(从hw/HW Doc/SSR920 HW Checklist.xlsx tmux获取)

以PWM0举例:

PWM0总共有六个mode分别从不同的六个pad出,其中mode1从PAD_PM_GPIO0出。

当获取完PWM的对应关系之后:

需要修改两个文件:

比如:mercury6.dtsi

910:mercury6-ssc017-s01a-padmux.dtsi,920:mercury6-ssc016a-s01a-demo-padmux.dtsi,具体以参与编译的dts为准。


2. LINUX PWM控制

2.1. Console下控制PWM

  1. Motor hierarchy

    Group 0
        PWM 0
        PWM 1
        PWM 2
        PWM 3
    Group 1
        PWM 4
        PWM 5
        PWM 6
        PWM 7
    Group 2
        PWM 8
        PWM 9
        PWM 10
    
  2. Cd 马达控制路径

    Command:

    cd /sys/devices/virtual/mstar/motor
    
  3. Set mode/fonteriod(frequency) / Begin/End / round number/enable/hold/stop

    • mode

      Command:

      echo PWM_ID enable > group_mode
      

      举例:

      echo 0 1 > group_mode # 设定PWM0为马达模式 
      ex : echo 0 0 > group_mode # 取消PWM0为马达模式
      
    • period

      Command:

      echo PWM_ID period > group_period
      

      在驱动程序实现中,xxxx 表示输出频率。

      举例:

      echo 0 2000 > group_period # PWM0 will generate 2KHz waveform
      
    • begin

      Command:

      echo PWM_ID begin > group_begin
      

      举例:

      echo 0 10 > group_begin # PWM0 将从周期的 10% 开始生成duty_cycle
      
    • end

      Command:

      echo PWM_ID end > group_end
      

      举例:

      echo 0 25 > group_end # PWM0 将在周期的 75% 时生成duty_cycle
      
    • round

      Command:

      echo GROUP_ID round > group_round
      

      举例:

      echo 0 10000 > group_round # Group 0 将产生 10000 个周期的波形
      
    • enable

      Command:

      echo GROUP_ID enable > group_enable
      

      举例:

      echo 0 1 > group_enable # Group 0 开始生成波形
      echo 0 0 > group_enable # Group 0 停止生成波形
      
    • hold

      Command:

      echo GROUP_ID > group_hold
      

      举例:

      echo 0 > group_hold # Group 0 保持最后一个完整的波形
      
    • stop

      Command:

      echo GROUP_ID > group_stop
      

      举例:

      echo 0 > group_stop # Group 0 立即停止生成波形
      
    • duty_qe0

      Command:

      echo QE0_EN > group_duty_qe0
      

      举例:

       echo 0 > group_duty_qe0 # QE0 enable/disable
      
    • hold_mode1

      Command:

      echo MODE1_EN > group_hold_mode1
      

      举例:

      echo 1 > group_hold_mode1 # Mode1 enable
      Mode 0 (keep pwm state)
      

在拉hold期间更改设定,且pwm值保持原始Mode 1 (pull low)

在拉hold期间更改设定,但pwm值数完最后一个period后会拉low, Hold 0 会有interrupt, 这个interrupt是下了hold 0之后, 这个period结束, HW会发interrupt, 然后driver在ISR里头填新的参数, 取消hold 0, 然后PWM就会产生新的参数的波型了

以下红色代表是AP(用户) 的操作;蓝色代表是Driver的操作;绿色代表是HW 的行为。

填参数->enable之后, 以下分成hold 0/1来解释

  1. Hold 0

    (驱动先把新的参数放在内存中) -> 打开hold 0 -> 一个period结束/保持最后波型 -> ( ISR ) 驱动从内存把参数回填 PWM/放开 hold 0 -> 产生新的波型

  2. Hold 1

    打开Hold 1-> 一个period结束/波形拉低 -> (AP确定period结束) 下新的参数->放开Hold 1-> 产生新的波形

2.2. Kernel driver控制PWM

#include <linux/fontwm.h>

#static struct pwm_device *mstar_pwm;
  • struct pwm_device *pwm_request(int pwm_id, const char *label)

    • (此api用于获取对应id的pwm设备)
  • int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)

    • (通过此api对获取到的pwm设备设置周期与占空比)
  • int pwm_enable(struct pwm_device *pwm, int duty_ns, int period_ns)

    • (通过此api enable获取得到的pwm设备)

使用实例:

  • enable PWM0(PAD_PWM0)
    static struct pwm_device *mstar_pwm;
    
    mstar_pwm = pwm_request(0, "MSTAR LCD");
    
    if (IS_ERR(mstar_pwm)) {
    
        printk("Start Unable to request PWM for LCD power!\n");
    
        return PTR_ERR(mstar_pwm);
    
    }
    
    pwm_config(mstar_pwm, 500000, 1000000);//duty=50%, hz=1000
    
    pwm_enable(mstar_pwm);
    

公式如下:

set 1000Hz duty 50% pwm waveform

period\_value = 1000000000 / 1000 = 1000000 ns
duty_value = period_value \times 50\% = 500000 ns

3. UBOOT标准 PWM控制接口

3.1. PWM API

#include <pwm.h>
  • int pwm_init(id, div, invert)

    • sets up the clock speed and whether or not it is inverted
  • int pwm_config(id, duty, period_ns)

    • sets up the duty and period
  • int pwm_enable(int pwm_id)

    - enables the PWM driver

  • int pwm_disable(int pwm_id)

    - disables the PWM driver

参数说明:

  • Id: 0:PWM0, 1:PWM1……7:PWM7

  • DIV: 设置范围0~65535

  • Invert: 设置范围0或1

  • Duty: 设置范围0~100

  • Period: 设置范围 2~262143 (Hz)

3.2. PWM设置参考