Linux驱动编写之PWM驱动配置

简介

I.MX6ULL 有 8 路 PWM 输出,因此对应 8 个 PWM 控制器,所有在设备树下就有 8 个PWM 控制器节点。
![在这里插入图片描述](https://img-blog.csdnimg.cn/cd85ffb9e50d4cb897de9727135af435.png

而 GPIO1_IO08 就是 PWM1 的输出引脚,所以这里是基于IMX6ULL PWM1 的驱动。

设备树配置

pinctrl_pwm1: pwm1grp {
	fsl,pins = <
		MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0
	>;
};
&pwm1 {
	pinctrl-names = "default";
	pinctrl-0 = <&pinctrl_pwm1>;
	status = "okay";
};
根据以下文档写出backlight
	backlight {
		compatible = "pwm-backlight";
		pwms = <&pwm1 0 5000000>;
		brightness-levels = <0 4 8 16 32 64 128 255>;
		default-brightness-level = <7>;
		status = "okay";
	};

Linux内核绑定文档路径为Documentation/devicetree/bindings/video/backlight/pwm-backlight.txt查看该文档对pwm-backlight参数进行设置

Required properties:
compatible: “pwm-backlight”
pwms: OF device-tree PWM specification (see PWM binding[0])
brightness-levels: Array of distinct brightness levels. Typically these
are in the range from 0 to 255, but any range starting at 0 will do.
The actual brightness level (PWM duty cycle) will be interpolated
from these values. 0 means a 0% duty cycle (darkest/off), while the
last value in the array represents a 100% duty cycle (brightest).
default-brightness-level: the default brightness level (index into the
array defined by the “brightness-levels” property)
power-supply: regulator for supply voltage

以上是设备树的配置

驱动使能

NXP 官方的 Linux 内核已经默认使能了 PWM 驱动,所以不需要我们修改,
我们还是需要知道有没有使能。打开 Linux 内核配置界面,按照如下路径找到配置项:

-> Device Drivers
	-> Pulse-Width Modulation (PWM) Support
		-> <*> i.MX PWM support

在这里插入图片描述

通过PWM控制背光

在这里插入图片描述

补充其它IO口作为PWM的使用方法

以gpio_4为例

设备树配置

 pinctrl_pwm3: pwm3grp {
	 fsl,pins = <
	 	MX6UL_PAD_GPIO1_IO04__PWM3_OUT 0x110b0
	 >;
 };
 &pwm3 {
	 pinctrl-names = "default";
	 pinctrl-0 = <&pinctrl_pwm3>;
	 clocks = <&clks IMX6UL_CLK_PWM3>,
	 <&clks IMX6UL_CLK_PWM3>;
	 status = "okay";
 };

相关参数说明:
pinctrl-0 属性指定 PWM3 所使用的输出引脚对应的 pinctrl 节点
第 1个clock 设置 ipg 时钟 (注:IMX6UL_CLK_PWM3时钟和PWM序列一一对应,例:如果是PWM1则是IMX6UL_CLK_PWM1
第 2个clock设置 per 时钟(注:IMX6UL_CLK_PWM3时钟和PWM序列一一对应,例:如果是PWM1则是IMX6UL_CLK_PWM1
status 是否使能配置

使用方法

下面这8组pwmchip0-pwmchip6分别代表PWM1-PWM7
在这里插入图片描述
1、调出 pwmchip2 的 pwm0 子目录
首先需要调出 pwmchip2 下的 pwm0 目录,否则后续就没法操作了,输入如下命令:(以下都必须在设备树配置好的基础上操作)

echo 0 > /sys/class/pwm/pwmchip2/export

执行完成会在 pwmchip2 目录下生成一个名为“pwm0”的子目录,如下图所示:
在这里插入图片描述

2、使能 PWM3
输入如下命令使能 PWM3:

echo 1 > /sys/class/pwm/pwmchip2/pwm0/enable

3、设置 PWM3 的频率
注意,这里设置的是周期值,单位为 ns,比如 20KHz 频率的周期就是 50000ns,输入如下
命令:

echo 50000 > /sys/class/pwm/pwmchip2/pwm0/period

4、设置 PWM3 的占空比
这里不能直接设置占空比,而是设置的一个周期的 ON 时间,也就是高电平时间,比如 20KHz 频率下 20%占空比的 ON 时间就是 10000,输入如下命令:

echo 10000 > /sys/class/pwm/pwmchip2/pwm0/duty_cycle

Linux应用编程设置PWM参数

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <linux/ioctl.h>

#define dbmsg(fmt, args ...) printf("%s[%d]: "fmt"\n", __FUNCTION__, __LINE__,##args)

#define DUTY              "duty"
#define PERIOD            "1000000"
#define DUTYCYCLE         "500000"
#define LENGTH            100

int fd_period = 0,fd_duty = 0,fd_enable = 0,duty_m = 0;

int usage()
{
    printf("usage:\n");
    printf("./pwm-sysfs-test duty <0/1> : 0-->static; 1-->dynamic \n");   
    return 0;
}

int pwm_setup()
{
  int fd,ret;

  fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY);
  if(fd < 0)
  {
      dbmsg("open export error\n");
      return -1;
  }
  ret = write(fd, "0", strlen("0"));
  if(ret < 0)
  {
      dbmsg("creat pwm0 error\n");
      return -1;
  }else
  dbmsg("export pwm0 ok\n");

  fd_period = open("/sys/class/pwm/pwmchip0/pwm0/period", O_RDWR);
  fd_duty = open("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", O_RDWR);
  fd_enable = open("/sys/class/pwm/pwmchip0/pwm0/enable", O_RDWR);
  
  if((fd_period < 0)||(fd_duty < 0)||(fd_enable < 0))
  {
      dbmsg("open error\n");
      return -1;
  }

  ret = write(fd_period, PERIOD,strlen(PERIOD));
  if(ret < 0)
  {
      dbmsg("change period error\n");
      return -1;
  }else
    dbmsg("change period ok\n");

  ret = write(fd_duty, DUTYCYCLE, strlen(DUTYCYCLE));
  if(ret < 0)
  {
      dbmsg("change duty_cycle error\n");
      return -1;
  }else
    dbmsg("change duty_cycle ok\n");

  ret = write(fd_enable, "1", strlen("1"));
  if(ret < 0)
  {
      dbmsg("enable pwm0 error\n");
      return -1;
  }else
  dbmsg("enable pwm0 ok\n");

  duty_m = atoi(DUTYCYCLE)/2;
  printf("duty_m: %d \n",duty_m);

  return 0;
}

int main ( int argc, char *argv[] )
{
  int ret;
  int num;
  if(argc < 2)
  {
    usage();
    return -1;
  }

  if(strncmp(argv[1],DUTY, sizeof(DUTY)) == 0)
  {
    dbmsg("%s", DUTY);
    if(argc != 3)
    {
      usage();
      return -1;
    }
    pwm_setup();
  }

  return 0;
}
  • 3
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路过的小熊~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值