脉宽调制(PWM,Pulse Width Modulation)功能在嵌入式系统中非常常见,它是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。
Rockchip PWM 能够支持Linux下的标准PWM接口编程。
板上引出一路PWM用于自定义用途,其余还有用于屏幕背光的PWM,已被其它驱动独占,不能用作其它功能。
通过如下命令可以查看板上有哪些pwm设备
rk3588_u:/ # find /sys -name "*pwmchip*"
find: '/sys/kernel/debug/pinctrl': loop detected
/sys/class/pwm/pwmchip2
/sys/class/pwm/pwmchip0
/sys/class/pwm/pwmchip3
/sys/class/pwm/pwmchip1
/sys/devices/platform/fd8b0020.pwm/pwm/pwmchip2
/sys/devices/platform/fd8b0010.pwm/pwm/pwmchip1
/sys/devices/platform/febf0030.pwm/pwm/pwmchip3
/sys/devices/platform/pwm-gpio/pwm/pwmchip0
通过查询设备树可以得知 fd8b0010 fd8b0020 febf0030 分别为 pwm1 pwm2 pwm15 的寄存器首地址,因此 pwmchip3 为pwm15的节点。
下面通过简易的逻辑分析仪来抓取此路pwm的波形,接线如下
sysfs的节点默认需要root用户才能操作。如果要用其他用户,需要使用adb或者shell执行如下命令
su
# 将pwm设置为userspace使用
echo 0 > /sys/class/pwm/pwmchip3/export
# 给权限
chmod -R 777 /sys/class/pwm/pwmchip3
chmod 777 /sys/class/pwm/pwmchip3/pwm0/*
设置PWM 的周期,这里的单位ns
echo 10000 > /sys/class/pwm/pwmchip3/pwm0/period
设置占空比,如果是正常的输出极性,这个参数指定PWM 波一个周期内高电平持续时间,单位ns
echo 5000 > /sys/class/pwm/pwmchip3/pwm0/duty_cycle
polarity参数用于指定输出极性,即PWM 输出是否反相
echo normal > /sys/class/pwm/pwmchip3/pwm0/polarity
使能pwm通道输出
echo 1 > /sys/class/pwm/pwmchip3/pwm0/enable
执行结果如下,可以看到高低电平时长都为5us
JAVA接口代码如下,此处只需要使用简单的读写函数即可
public static void writeToFile(String fileName, String content) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
writer.write(content);
}
}
public static String readFileToString(String fileName) throws IOException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return new String(Files.readAllBytes(Paths.get(fileName)), StandardCharsets.UTF_8);
}
return null;
}
public static boolean isFileExists(String filePath) {
if (filePath == null || filePath.isEmpty()) {
return false;
}
File file = new File(filePath);
return file.exists();
}
在上一章节创建的app基础上,增加一个按钮和一个文本框,按下按钮则输出PWM,再次按下则停止PWM输出
private boolean isPWMEnable = false;
button6.setText("pwm enable");
button6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 设置要显示的文字
textDisplay.setText("start pwm test... \n");
if(!isFileExists("/sys/class/pwm/pwmchip3/pwm0/period")) {
textDisplay.append("pwm not export... \n");
} else {
if(!isPWMEnable) {
isPWMEnable = true;
button6.setText("pwm disable");
try {
writeToFile("/sys/class/pwm/pwmchip3/pwm0/period","20000");
writeToFile("/sys/class/pwm/pwmchip3/pwm0/duty_cycle","6000");
writeToFile("/sys/class/pwm/pwmchip3/pwm0/polarity","normal");
writeToFile("/sys/class/pwm/pwmchip3/pwm0/enable","1");
} catch (IOException e) {
throw new RuntimeException(e);
}
} else {
isPWMEnable = false;
button6.setText("pwm enable");
try {
writeToFile("/sys/class/pwm/pwmchip3/pwm0/enable","0");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
});
按下此按钮后,可以看到PWM波形,其中高电平时长6us,低电平时长14us