一、PWM操作介绍
PWM,脉宽调制技术的编程方法和LED类设备一样可以通过sysfs虚拟文件系统控制。进入到目录/sys/class/pwm目录下:
其中每个pwmchipx对应于一个pwm控制器,进入pwmchip0文件:
npwm: 这是一个只读属性,读取该文件可以得知该 PWM 控制器下共有几路 PWM 输出,如下所
示:
可以看出I.MX6ULL每个PWM控制器对应的只有一路输出。export: 与 GPIO 控制一样,在使用 PWM 之前,也需要将其导出,通过 export 属性进行导出。unexport: 将导出的 PWM 删除。当使用完 PWM 之后,我们需要将导出的 PWM 删除。
enable: 可读可写,写入"0"表示禁止 PWM;写入"1"表示使能 PWM。读取该文件获取 PWM 当前是禁止还是使能状态。
polarity: 用于设置极性,可读可写,可写入的值如:"normal":普通;"inversed":反转;period: 用于配置 PWM 周期, 可读可写;写入一个字符串数字值,以 ns(纳秒)为单位
duty_cycle: 用于配置 PWM 的占空比, 可读可写;写入一个字符串数字值, 同样也是以 ns 为单位。
二、编写应用操作
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
static char pwm_path[100];
static int pwm_config(const char *attr, const char *val) //配置PWM
{
char file_path[100];
int len;
int fd;
sprintf(file_path, "%s/%s", pwm_path, attr);
if (0 > (fd = open(file_path, O_WRONLY))) {
perror("open error");
return fd;
}
len = strlen(val);
if (len != write(fd, val, len)) {
perror("write error");
close(fd);
return -1;
}
close(fd); //关闭文件
return 0;
}
int main(int argc, char *argv[])
{
/* 校验传参 */
if (4 != argc) {
fprintf(stderr, "usage: %s <id> <period> <duty>\n",
argv[0]);
exit(-1);
}
/* 打印配置信息 */
printf("PWM config: id<%s>, period<%s>, duty<%s>\n",
argv[1], argv[2],
argv[3]);
/* 导出 pwm */
sprintf(pwm_path, "/sys/class/pwm/pwmchip%s/pwm0", argv[1]);
if (access(pwm_path, F_OK)) {//如果 pwm0 目录不存在, 则导出
char temp[100];
int fd;
sprintf(temp, "/sys/class/pwm/pwmchip%s/export", argv[1]);
if (0 > (fd = open(temp, O_WRONLY))) {
perror("open error");
exit(-1);
}
if (1 != write(fd, "0", 1)) {//导出 pwm
perror("write error");
close(fd);
exit(-1);
}
close(fd); //关闭文件
}
/* 配置 PWM 周期 */
if (pwm_config("period", argv[2]))
exit(-1);
/* 配置占空比 */
if (pwm_config("duty_cycle", argv[3]))
exit(-1);
/* 使能 pwm */
pwm_config("enable", "1");
/* 退出程序 */
exit(0);
}