0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux应用开发【第十一章】PWM编程应用开发

weidongshan 来源:weidongshan 作者:weidongshan 2021-12-10 19:25 次阅读

文章目录

11 PWM编程应用开发

11.1 PWM概述

11.1.1 PWM的参数说明

11.2 用户层查看PWM

11.3 PWM的SYSFS使用

11.4 PWM应用编程

11.4.1 修改设备树

11.4.2 修改配置文件

11.4.3 添加驱动

11.4.4 运行测试

11 PWM编程应用开发

11.1 PWM概述

​ PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对interwetten与威廉的赔率体系 信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%。是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的威廉希尔官方网站 。

poYBAGGzOTeAMvdqAAAzet9xcHI318.png

​ PWM信号把模拟信号转化为数字电路所需要的编码,现在基本是采用数字电路,因此在很多场合都采用PWM信号,我们经常见到的就是交流调光电路,也可以说是无级调速,高电平占多一点,也就是占空比大一点亮度就亮一点,占空比小一点亮度就没有那么亮,前提是PWM的频率要大于我们人眼识别频率,要不然会出现闪烁现象。除了在调光电路应用,还有在直流斩波电路、蜂鸣器驱动、电机驱动、逆变电路、加湿机雾化量等都会有应用。

pYYBAGGzOT6ADz5WAAAajfUkDIQ538.png

11.1.1 PWM的参数说明

https://www.kernel.org/doc/Documentation/pwm.txt
period
PWM信号的总周期(读/写)。
值以纳秒为单位,是活动和非活动的总和
PWM的时间。

duty_cycle(占空比)
PWM信号的有效时间(读/写)。
值以纳秒为单位,且必须小于周期。
在NORMAL模式下,表示一个周期内高电平持续的时间
在INVERTED模式下,表示一个周期中低电平持续的时间

polarity
改变PWM信号的极性(读/写)。
写入此属性仅在PWM芯片支持更改时才有效
极性。只有PWM不能改变极性
启用。值是字符串“normal”或“inversed”。

enable
启用/禁用PWM信号(读/写)。

0 - 禁用

1 - 启用

11.2 用户层查看PWM

​ 如果在内核配置中启用了CONFIG_SYSFS,则会提供一个简单的sysfs接口来使用用户空间的PWM。它在/ sys / class / pwm /中公开。每个被探测的PWM控制器/芯片将被输出为pwmchipN,其中N是PWM芯片的基础。你在目录里面会发现:

 1 echo 0 > /sys/class/pwm/pwmchip0/export /*设置PWM4输出,调出pwm0目录下设备节点,用于以下配置 */
 2 echo 1000000 >/sys/class/pwm/pwmchip0/pwm0/period /*设置PWM4一个周期的持续时间,单位为ns,即1K Hz */
 3 echo 500000 >/sys/class/pwm/pwmchip0/pwm0/duty_cycle /*设置一个周期中的”ON”时间,单位为ns,即占空比=duty_cycle/period=50% */
 4 echo 1 >/sys/class/pwm/pwmchip0/pwm0/enable /*设置PWM4使能 */

11.3 PWM的SYSFS使用

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#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 errorn");
      return -1;
  }
  ret = write(fd, "0", strlen("0"));
  if(ret < 0)
  {
      dbmsg("creat pwm0 errorn");
      return -1;
  }else
  dbmsg("export pwm0 okn");

  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 errorn");
      return -1;
  }

  ret = write(fd_period, PERIOD,strlen(PERIOD));
  if(ret < 0)
  {
      dbmsg("change period errorn");
      return -1;
  }else
    dbmsg("change period okn");

  ret = write(fd_duty, DUTYCYCLE, strlen(DUTYCYCLE));
  if(ret < 0)
  {
      dbmsg("change duty_cycle errorn");
      return -1;
  }else
    dbmsg("change duty_cycle okn");

  ret = write(fd_enable, "1", strlen("1"));
  if(ret < 0)
  {
      dbmsg("enable pwm0 errorn");
      return -1;
  }else
  dbmsg("enable pwm0 okn");

  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;
}

11.4 PWM应用编程

The main useful user API are the following:
devm_pwm_get() or pwm_get() / pwm_put(): this API is used to look up, request, then free a PWM device.
pwm_init_state(),pwm_get_state(), pwm_apply_state(): this API is used to initialize, retrieve and apply the current PWM device state.
pwm_config(): this API updates the PWM device configuration (period and duty cycle).

11.4.1 修改设备树

beeper {
compatible = "pwm-beeper";
pwms = <&pwm 0 1000000 0>;
pinctrl-names = "default";
pinctrl-0 = <&pwm0_pin>;
};

11.4.2 修改配置文件

Activate PWM framework in the kernel configuration through the Linux menuconfig tool, Menuconfig or how to configure kernel (CONFIG_PWM=y):
Device Drivers  --->
   [*] Pulse-Width Modulation (PWM) Support  --->

11.4.3 添加驱动

#include 
#include 
#include 
#include 
#include 
#include 

//#include 

#define PWM_ON  0x100001
#define PWM_OFF 0x100002

struct pwm_device *pwm_dev_2;
struct pwm_device *pwm_dev_3;

static long pwm_ioctl(struct file *file,
                        unsigned int cmd,
                        unsigned long arg)
{
    int ret;
    switch(cmd) {
        case PWM_ON:
                ret = pwm_config(pwm_dev_2,200000,500000);
                if(ret < 0){
                    printk("pwm_dev_2 ioctl fail");
                    return 0;
                }
                ret = pwm_config(pwm_dev_3,300000,500000);
                if(ret < 0){
                    printk("pwm_dev_3 ioctl fail");
                }
                pwm_enable(pwm_dev_2);
                pwm_enable(pwm_dev_3);
            break;
        case PWM_OFF:
                ret = pwm_config(pwm_dev_2,0,500000);
                if(ret < 0){
                    printk("pwm_dev_2 ioctl fail");
                    return 0;
                }
                ret = pwm_config(pwm_dev_3,0,500000);
                if(ret < 0){
                    printk("pwm_dev_3 ioctl fail");
                }
                pwm_disable(pwm_dev_2);
                pwm_disable(pwm_dev_3);
            break;
    }
    return 0;
}

//定义初始化硬件操作方法
static struct file_operations pwm_fops = {
    .owner = THIS_MODULE,
    .unlocked_ioctl = pwm_ioctl
};

//定义初始化混杂设备对象
static struct miscdevice pwm_misc = {
    .minor = MISC_DYNAMIC_MINOR, //动态分配次设备号
    .name = "mypwm",             //dev/mypwm
    .fops = &pwm_fops 
};

static int pwm_init(void)
{
    int ret;
    printk("regisger pwm_misc devicen");
    //1.申请pwm资源,设置输出为0
    pwm_dev_2 = pwm_request(1,"pwm_2");
    if(pwm_dev_2 == NULL){
        printk("pwm_dev_2 register failn");
    }
    pwm_dev_3 = pwm_request(2,"pwm_3");
    if(pwm_dev_3 == NULL){
        printk("pwn_dev_3 register failn");
    }

    ret = pwm_config(pwm_dev_2,0,500000);
    if(ret < 0){
        printk("pwm_config_2 init failn");
        return 0;
    }
    ret = pwm_config(pwm_dev_3,0,500000);
    if(ret < 0){
        printk("pwm_config_3 init failn");
        return 0;
    }

    ret = pwm_enable(pwm_dev_2);
    if(ret == 0){
        printk("pwm_enable_dev_2 init successn");
    }
    if(ret < 0 ){
        printk("pwm_enable_dev_2 init failn");
        return 0;
    }
    ret = pwm_enable(pwm_dev_3);
    if(ret == 0){
        printk("pwm_enable_dev_3 init successn");
    }
    if(ret < 0 ){
        printk("pwm_enable_dev_3 init failn");
        return 0;
    }
    //2.注册混杂设备
    misc_register(&pwm_misc);
    return 0;
}

static void pwm_exit(void)
{
    printk("unregister pwm_misc devicen");
    //1.卸载混杂设备
    misc_deregister(&pwm_misc);
    //2.释放pwm资源
    pwm_config(pwm_dev_2,0,500000);
    pwm_disable(pwm_dev_2);
    pwm_free(pwm_dev_2);
    
    pwm_config(pwm_dev_3,0,500000);
    pwm_disable(pwm_dev_3);
    pwm_free(pwm_dev_3);
}
module_init(pwm_init);
module_exit(pwm_exit);
MODULE_LICENSE("GPL");

11.4.4 运行测试

#include  
#include  
#include  
#include  
 
#define PWM_ON  0x100001 
#define PWM_OFF 0x100002 
 
int main(void) 
{
    int fd; 
    int a; 
 
    fd = open("/dev/mypwm", O_RDWR); 
    if (fd < 0) 
        return -1; 
 
    while(1) { 
            ioctl(fd, PWM_ON); 
    } 
    close(fd); 
    return 0; 
}

审核编辑 黄昊宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • PWM
    PWM
    +关注

    关注

    114

    文章

    5186

    浏览量

    213895
  • Linux
    +关注

    关注

    87

    文章

    11303

    浏览量

    209439
收藏 人收藏

    评论

    相关推荐

    明德扬视频分享点拨FPGA课程--第十一章  Signaltapll的使用技巧

    第十一章Signaltapll的使用技巧1. signaltapll使用http://yunpan.cn/cjZTiDA9pY56x访问密码 c359
    发表于 11-11 09:03

    至芯科技之altera 系列FPGA教程 第十一篇 添加激励

    至芯科技之altera 系列FPGA教程 第十一篇 添加激励
    发表于 08-11 03:29

    视频详解:上海尤老师verilog入门到实战第十一

    上海尤老师verilog入门到实战第十一课——手把手讲解异步FIFO内部原理2; 百度云网盘链接后缀:/s/1o8tV3PC, 加群讨论252520964,307510678
    发表于 10-06 15:23

    第十一期 存储与读取文件

    第十一期实现写入文件与文件的读取操作
    发表于 09-16 12:23

    「正点原子Linux连载」第十一章模仿STM32驱动开发格式实验

    ,获取更多资料:正点原子第十一章模仿STM32驱动开发格式实验 在上一章使用C语言编写LED灯驱动的时候,每个寄存器的地址我们都需要写宏定义,使用起来非常的不方便。我们在学习STM32的时候,可以
    发表于 12-20 15:03

    蓝桥杯第十一届省赛单片机组

    蓝桥杯第十一届省赛单片机组,翻了下以前做过的一些项目和比赛,发现了之前准备比赛的一些注意事项和心得,分享给大家希望大家能够避免错误拿高分。 适当的延时很重要,可以解决一些不正常现象ds1302读取
    发表于 07-14 06:57

    迅为iMX6ULL开发板使用手册资料下载

    实验第四章 C语言实现LED例程第五章 移植官方SDK第六章 创建裸机工程第七章 蜂鸣器例程第八章 按键例程第九章 主频和时钟配置例程第十章 GPIO中断例程第十一章 EPIT定时器例程第十二章 定时器
    发表于 12-02 14:13

    【倾心力作!】i.MX8MM嵌入式linux开发指南+全覆盖开发资料

    搭建第四部分 开发板固件编译第八章 Android编译环境搭建第九章 Android固件编译第十Linux固件编译第十一章IMX8MM软件资源介绍第五部分
    发表于 02-11 10:27

    更新 | 持续开源 迅为RK3568驱动指南第十一篇-pinctrl子系统

    《iTOP-RK3568开发板驱动开发指南》更新,本次更新内容对应的是驱动(第十一期_pinctrl子系统-全新升级)视频,后续资料会不断更新,不断完善,帮助用户快速入门,大大提升研发速度。 文档
    发表于 10-18 11:12

    三相电路原理(第十一章)

    三相电路原理(第十一章)  11-1 三相电路 11-2 线电压(电流)与相电压(电流)的关系 11-3 对称三相电路的计算 11-4 不对称三相电路的概念&nb
    发表于 05-23 11:44 53次下载

    模拟电路网络课件 第十一节:小信号模型分析法

    模拟电路网络课件 第十一节:小信号模型分析法 3.4 小信号模型分析法
    发表于 09-17 09:53 8594次阅读
    模拟电路网络课件 <b class='flag-5'>第十一</b>节:小信号模型分析法

    第十一届高交会电子展今日开锣

    第十一届高交会电子展今日开锣 2009年11月16日9:46:07第十一届高交会电子展(ELEXCON 2009)将于11月16日~21日在深圳会展中心2号馆隆重举
    发表于 11-16 09:46 779次阅读

    第十一届蓝桥杯嵌入式设计与开发 (省赛)

    第十一届蓝桥杯嵌入式设计与开发 (省赛)分析此次赛题围绕两个方向,结构如下:代码:1.主函数模块main.c#include #include
    发表于 11-03 15:36 21次下载
    <b class='flag-5'>第十一</b>届蓝桥杯嵌入式设计与<b class='flag-5'>开发</b> (省赛)

    第十一届蓝桥杯单片机模拟题--智能门锁

    第十一届蓝桥杯单片机模拟题--智能门锁
    发表于 11-30 10:21 17次下载
    <b class='flag-5'>第十一</b>届蓝桥杯单片机模拟题--智能门锁

    【正点原子FPGA连载】第十一章触摸按键控制LED灯实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    :http://www.openedv.com/thread-300792-1-1.html3)对正点原子FPGA感兴趣的同学可以加群讨论:9942440164)关注正点原子公众号,获取最新资料更新第十一章触摸按键控制LED灯实验随着电子威廉希尔官方网站 的不断发展,按键的应用场景越来越广泛。触摸按键在稳定性、使用寿命、
    发表于 12-31 19:21 9次下载
    【正点原子FPGA连载】<b class='flag-5'>第十一章</b>触摸按键控制LED灯实验 -摘自【正点原子】新起点之FPGA<b class='flag-5'>开发</b>指南_V2.1