Linux系统PWM应用编程

news2024/9/22 23:22:08

目录

  • 应用层如何操控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,如下所示:

echo 0 > /sys/class/pwm/pwmchip0/export #导出PWM1
echo 0 > /sys/class/pwm/pwmchip1/export #导出PWM2
echo 0 > /sys/class/pwm/pwmchip2/export #导出PWM3
echo 0 > /sys/class/pwm/pwmchip3/export #导出PWM4
echo 0 > /sys/class/pwm/pwmchip4/export #导出PWM5
echo 0 > /sys/class/pwm/pwmchip5/export #导出PWM6

导出成功后会在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。

#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)
{
    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);
}

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 腾出来给我们测试使用,直接操作呢?
首先我们需要重启开发板,进入到u-boot 命令行模式下,如下:
在这里插入图片描述
我们要做什么呢?其实就是去修改内核设备树文件,将LCD 和backlight 设备的status 属性修改为“disabled”,禁用这两个设备;怎么修改呢?u-boot 中提供了查看、修改设备树的命令,u-boot 启动时,会将内核设备树(dtb)拷贝到内存中,当拷贝到内存中之后呢,我们就可以去查看或修改设备树了,这里笔者直接把需要执行的命令贴出来,如下所示:
SD/eMMC 启动方式:

setenv disable_lcd 'fdt addr ${fdt_addr}; fdt set /backlight status disable; fdt set /soc/aips-bus@02100000/lcdif@021c8000 status disable'
下一条命令
setenv mmcboot 'echo Booting from mmc ...; run mmcargs; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then run disable_lcd; bootz ${loadaddr} - ${fdt_addr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;'

NAND 启动方式:

setenv disable_lcd 'fdt addr ${fdt_addr}; fdt set /backlight status disable; fdt set /soc/aips-bus@02100000/lcdif@021c8000 status disable'
下一条命令
setenv bootcmd 'nand read ${loadaddr} 0x620000 0x800000;nand read ${fdt_addr} ${fdt_offset} 0x20000; run disable_lcd; bootz ${loadaddr} - ${fdt_addr}'

拷贝时注意格式的问题,分为SD/eMMC 启动方式和NAND 启动方式;笔者测试用的开发板是eMMC方式启动的,在u-boot 命令行模式下执行如下命令:
在这里插入图片描述
执行完两条命令后,接着执行boot 命令启动开发板:

boot

在这里插入图片描述
Tips:这种修改方式只对本次启动生效,因为我们修改的是内存中的那份设备树文件,下一次重启开发板时将又恢复到未修改前的状态,请悉知!
系统启动之后,PWM1 就已经腾出来给我们测试使用了,此时LCD 被禁用了!
执行上小节编译得到的可执行文件:
在这里插入图片描述
本实验测试的是PWM1,开发板出厂系统已经将PWM1 输出绑定到了GPIO1_IO08 引脚(也就是LCD
背光引脚),该引脚已经通过开发板上的扩展口引出,如下所示:
在这里插入图片描述
Mini 开发板可以通过背面丝印标注的名称或原理图进行确认。
接下来使用示波器来检测GPIO1_IO08 引脚输出的PWM 波形,如下所示:
在这里插入图片描述
此时GPIO1_IO08 引脚输出了PWM 波形,其周期为500us(也就是500000ns),对应的频率为2KHz,占空比为50%,与我们配置的情况是一样的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/392721.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java多态性

用一句话概括就是&#xff1a;事物在运行过程中存在不同的状态。 多态的存在有三个前提: 1.要有继承关系 2.子类要重写父类的方法 3.父类引用指向子类对 但是其中又有很多细节需要注意。首先我们定义两个类&#xff0c;一个父类Animal&#xff0c;一个子类Cat。 父类Animal cl…

Hive学习——企业级调优

目录 一、计算资源调优 (一)Yarn资源配置——集群 1.Yarn配置说明 (1)yarn.nodemanager.resource.memory-mb (2)yarn.nodemanager.resource.cpu-vcores (3)yarn.scheduler.maximum-allocation-mb (4)yarn.scheduler.minimum-allocation-mb (二)MapReduce资源配置 二、…

裁员降本,扭转颓势!通用汽车吹响智能电动「中国集结号」

2023年&#xff0c;将是合资品牌能否搭上中国智能电动市场红利的关键一年。 全新一代VCS智能座舱&#xff08;高通8155&#xff0c;30英寸6K曲面OLED显示屏&#xff0c;12.6英寸WHUD以及5G版本的别克eConnect车联系统&#xff09;、全新一代Super Cruise超级辅助驾驶系统&#…

7.SpringSecurity中的权限管理

SpringSecurity中的权限管理 SpringSecurity是一个权限管理框架&#xff0c;核心是认证和授权&#xff0c;前面已经系统的给大家介绍过了认证的实现和源码分析&#xff0c;本文重点来介绍下权限管理这块的原理。 一、权限管理的实现 服务端的各种资源要被SpringSecurity的权限…

ccc-pytorch-卷积神经网络介绍(5)

文章目录一、卷积二、池化三、Batch Norm四、经典卷积网络简单介绍一、卷积 卷积连续函数形式&#xff1a; F(x)∫f(t)g(x−t)dtF(x)\int f(t)g(x-t)dtF(x)∫f(t)g(x−t)dt 物理意义是一个函数在另一个函数上的加权叠加。在2D卷积中指卷积核在数据矩阵中分割出的矩阵和卷积核相…

PMP和软考高项集成,更应该考哪个呢?

要看你自己的偏向&#xff0c;要说考的话&#xff0c;我是觉得都值得考的&#xff0c;一个证一份技术嘛。 我给你稍微介绍一下&#xff0c;PMP都是美国PMI发起的考试&#xff0c;软考高项是国内的考试。PMP是项目管理证书&#xff0c;学习的内容是项目管理&#xff0c;包含大约…

研报精选230306

目录 【行业230306东亚前海证券】食品饮料行业2023年年度投资策略&#xff1a;复苏在途&#xff0c;蓄势待发【行业230306国金证券】基础化工行业研究&#xff1a;MDI价格上行&#xff0c;新一轮国企改革在即【行业230306中银证券】华为汽车产业链深度报告&#xff1a;三种合作…

k8s控制器

目录 一、控制器简介 二、控制器类型 1、RC和RS 2、Deployment 3、DaemonSet 4、Job 5、CronJob 6、StateFulSet 7、HPA 一、控制器简介 在kubernetes中&#xff0c;按照Pod的创建方式可以将其分为两类&#xff1a; 自主式:kubernetes直接创建出来的Pod&#xff0c;…

【Alamofire】【Swift】属性包装器注解@propertyWrapper

Alamofire 中的源码例子 import Foundationprivate protocol Lock {func lock()func unlock() }extension Lock {/// Executes a closure returning a value while acquiring the lock.////// - Parameter closure: The closure to run.////// - Returns: The value…

9.SpringSecurity核心过滤器-SecurityContextPersistenceFilter

SpringSecurity核心过滤器-SecurityContextPersistenceFilter 一、SpringSecurity中的核心组件 在SpringSecurity中的jar分为4个&#xff0c;作用分别为 jar作用spring-security-coreSpringSecurity的核心jar包&#xff0c;认证和授权的核心代码都在这里面spring-security-co…

Promise入门

Promise入门 Promise的基本概念 男女相爱了&#xff0c;女方向男方许下一个承诺怀孕new Promise&#xff0c;这是会产生两种结果怀上(resolve)和没怀上(reject)&#xff0c;resolve对应then&#xff0c;reject对应catch&#xff0c;无论是否怀上都会执行finally。 <script&…

【论文速递】CASE 2022 - EventGraph: 将事件抽取当作语义图解析任务

【论文速递】CASE 2022 - EventGraph: 将事件抽取当作语义图解析任务 【论文原文】&#xff1a;https://aclanthology.org/2022.case-1.2.pdf 【作者信息】&#xff1a;Huiling You, David Samuel, Samia Touileb, and Lilja vrelid 论文&#xff1a;https://aclanthology.o…

sql server 对比两个查询性能 ,理解Elapsed Time、CPU Time、Wait Time

分析 SET STATISTICS TIME ONyour sqlSET STATISTICS TIME OFF由上图分析: cpu time 是查询执行时占用的 cpu 时间。如果了解系统的多任务机制&#xff0c;就会知道系统会将整个 cpu 时间分为一个一个时间片&#xff0c;平均分配给运行的线程——一个线程在 cpu 上运行一段时间…

《PyTorch深度学习实践9》——卷积神经网络-高级篇(Advanced-Convolution Neural Network)

一、1∗11*11∗1卷积 由下面两张图&#xff0c;可以看出1∗11*11∗1卷积可以显著降低计算量。 通常1∗11*11∗1卷积还有以下功能&#xff1a; 一是用于信息聚合&#xff0c;同时增加非线性&#xff0c;1∗11*11∗1卷积可以看作是对所有通道的信息进行线性加权&…

Air101|Air103|Air105|Air780E|ESP32C3|ESP32S3|Air32F103开发板:概述及PinOut

1、合宙Air101&#xff08;芯片及开发板&#xff09; 合宙Air101是一款QFN32 封装&#xff0c;4mm x 4mm 大小的mcu。通用串口波特率&#xff0c;设置波特率为921600。 ​ 管脚映射表 GPIO编号 命名 默认功能及扩展功能 0 PA0 BOOT 1 PA1 I2C_SCL/ADC0 4 PA4 I2C_S…

前端必备技术之——AJAX

简介 AJAX 全称为 Asynchronous JavaScript And XML&#xff0c;就是异步的 JS 和 XML(现在已经基本被json取代)。通过 AJAX 可以在浏览器中向服务器发送异步请求&#xff0c;最大的优势&#xff1a;无刷新获取数据。AJAX 不是新的编程语言&#xff0c;而是一种将现有的标准组…

揭秘关键一环!数据安全服务大盘点

数据安全服务&#xff0c;数据安全体系建设的关键一环。通过数据安全服务解决数据安全建设难题&#xff0c;得到越来越多的重视。不久前&#xff0c;《工业和信息化部等十六部门关于促进数据安全产业发展的指导意见》发布&#xff0c;明确“壮大数据安全服务”&#xff0c;推进…

VScode 插件【配置】

写这篇博客的原因&#xff1a; vscode 很久以前的插件&#xff0c;忘记是干什么的了记录 vscode 好用的插件 插件介绍&#xff08;正文开始&#xff09; Auto Rename tag 开始/关闭标签内容 同步 Chinese (Simplified) VScode 中文化 CSS Peek 通过 html 代码查找到引用的样式…

Linux - 磁盘I/O性能评估

文章目录概述RAID文件系统与裸设备的对比磁盘I/O性能评判标准常用命令“sar –d”命令组合“iostat –d”命令组合“iostat –x”单独统计某个磁盘的I/O“vmstat –d”命令组合小结概述 RAID 可以根据应用的不同&#xff0c;选择不同的RAID方式 如果一个应用经常有大量的读操…

Flink(Java版)学习

一、Flink流处理简介 1.Flink 是什么 2.为什么要用 Flink 3.流处理的发展和演变 4.Flink 的主要特点 5.Flink vs Spark Streaming 二、快速上手 1.搭建maven工程 2.批处理WordCount 3.流处理WordCount 三、Flink部署 1.Standalone 模式 2.Yarn 模式 3.Kubernetes 部署 四、F…