本章我们将学习如何对开发板上的 PWM 设备进行应用编程。
本章将会讨论如下主题内容。
⚫ 应用层 PWM 编程介绍;
⚫ PWM 测试。
应用层如何操控 PWM
与 LED 设备一样,PWM 同样也是通过 sysfs 方式进行操控,进入到/sys/class/pwm 目录下,如下所示:
这里列举出了 8 个以 pwmchipX(X 表示数字 0~7)命名的文件夹,这八个文件夹其实就对应了 I.MX6U的 8 个 PWM 控制器,I.MX6U 总共有 8 个 PWM 控制器,大家可以通过查询 I.MX6U 参考手册得知。
我们随便以其中一个为例,进入到 pwmchip0 目录下:
在这个目录下我们重点关注的是 export、npwm 以及 unexport 这三个属性文件,下面一一进行介绍:
⚫ npwm:这是一个只读属性,读取该文件可以得知该 PWM 控制器下共有几路 PWM 输出,如下所示:
I.MX6U 每个 PWM 控制器只有 1 路 PWM 输出,所以总共有 8 路 PWM,分别对应 I.MX6U 的PWM1~PWM8 这 8 路输出(pwmchip0 对应 PWM1,pwmchip1 对应 PWM2,以此类推,开发板出厂系统中,PWM1 已经被用作 LCD 背光控制了,应用层不能直接对它进行控制了;而其它 PWM 均不能使用,原因在于 I/O 资源不够,为了满足板子上其它外设对 I/O 引脚的需求,取舍情况下只能如此!)。
⚫ export:与 GPIO 控制一样,在使用 PWM 之前,也需要将其导出,通过 export 属性进行导出,以下所示:
echo 0 > export
0 表示一个编号,注意,每个 PWM 控制器(pwmchipX)下,使用 export 属性文件导出 PWM 时,编号都是从 0 开始;因为 I.MX6U 每个控制器都只有一路 PWM,所以都只能使用编号 0,如下所示:
导出成功后会在 pwmchipX(X 表示数字 0~7)目录下生成一个名为 pwm0 的目录,如图 24.1.4 所示,稍后介绍。
⚫ unexport:将导出的 PWM 删除。当使用完 PWM 之后,我们需要将导出的 PWM 删除,譬如:
echo 0 > unexport
写入到 unexport 文件中的编号与写入到 export 文件中的编号是相对应的;需要注意的是,export 文件和 unexport 文件都是只写的、没有读权限。
如何控制 PWM
通过 export 导出之后,便会生成 pwm0 这个目录,我们进入到该目录下看看:
该目录下也有一些属性文件,我们重点关注 duty_cycle、enable、period 以及 polarity 这四个属性文件,接下来一一进行介绍。
⚫ enable:可读可写,写入"0"表示禁止 PWM;写入"1"表示使能 PWM。读取该文件获取 PWM 当前是禁止还是使能状态。
echo 0 > enable #禁止 PWM 输出 echo 1 > enable #使能 PWM 输出
通常配置好 PWM 之后,再使能 PWM。
⚫ polarity:用于设置极性,可读可写,可写入的值如下:
"normal":普通; "inversed":反转;echo normal > polarity #默认极性 echo inversed > polarity #极性反转
很多 SoC 的 PWM 外设其硬件上并不支持极性配置,所以对应的驱动程序中并未实现这个接口,应用层自然也就无法通过 polarity 属性文件对 PWM 极性进行配置,ALPHA/Mini I.MX6U 开发板出厂系统便是如此!
⚫ period:用于配置 PWM 周期,可读可写;写入一个字符串数字值,以 ns(纳秒)为单位,譬如配置 PWM 周期为 10us(微秒):
echo 10000 > period #PWM 周期设置为 10us(10 * 1000ns)
⚫ duty_cycle:用于配置 PWM 的占空比,可读可写;写入一个字符串数字值,同样也是以 ns 为单位,譬如:
echo 5000 > duty_cycle #PWM 占空比设置为 5us
更多待补充。
编写应用程序
通过上面的介绍,我们已经知道在应用层如何去使用 PWM 外设了,本小节我们来编写一个简单的测试代码,来控制开发板上的 PWM 外设,示例代码如下所示:
本例程源码对应的路径为:开发板光盘->11、Linux C 应用编程例程源码->24_pwm->pwm.c。
main()函数中,首先对传参进行校验,执行该应用程序的时候需要用户传入 3 个参数,分别是编号(0、1、2、3 等,分别表示 I.MX6U 的 PWM1、PWM2、PWM3…)、周期(以 ns 为单位)、PWM 占空比(以ns 为单位)。譬如:
./testApp 0 500000 250000
接下来需要导出 pwm,首先使用 access()函数判断 pwm0 目录是否存在,如果存在表示 pwm 已经导出,如果不存在,则表示未导出,那么就需要通过 export 文件将其导出。
导出成功之后,接着配置 PWM 周期、占空比,最后使能 PWM。
编译示例代码:
在开发板上测试
将上小节编译得到的可执行文件拷贝到开发板 Linux 系统/home/root 目录下,如下所示:
前面提到了,开发板出厂系统没法使用 PWM,如果大家想要测试 PWM,可以对出厂系统的内核源码进行配置、需修改设备树,禁用 LCD 和 backlight 背光设备(status 属性设置为 disabled 即可),修改完之后重新编译设备树,用编译得到的设备树镜像文件(dtb 文件)替换掉开发板启动文件中的 dtb 文件。也可以参考《I.MX6U 嵌入式 Linux 驱动开发指南》第七十三章内容,自行配置 PWM。
这里笔者告诉大家一个简单地方法,不用重新编译设备树文件,直接把禁用 LCD 和 backlight 背光设备,将 PWM1 腾出来给我们测试使用,直接操作呢?
具体参考正点原子相关内容,此处不赘述。
执行上小节编译得到的可执行文件:
本实验测试的是 PWM1,开发板出厂系统已经将 PWM1 输出绑定到了 GPIO1_IO08 引脚(也就是 LCD背光引脚),该引脚已经通过开发板上的扩展口引出,如下所示:
Mini 开发板可以通过背面丝印标注的名称或原理图进行确认。
接下来使用示波器来检测 GPIO1_IO08 引脚输出的 PWM 波形,如下所示:
此时 GPIO1_IO08 引脚输出了 PWM 波形,其周期为 500us(也就是 500000ns),对应的频率为 2KHz,占空比为 50%,与我们配置的情况是一样的。
本章内容到此结束!