PWM使用参考
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¶
-
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
-
Cd 马达控制路径
Command:
cd /sys/devices/virtual/mstar/motor
-
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来解释
-
Hold 0
(驱动先把新的参数放在内存中) -> 打开hold 0 -> 一个period结束/保持最后波型 -> ( ISR ) 驱动从内存把参数回填 PWM/放开 hold 0 -> 产生新的波型
-
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
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)