OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8328|回复: 11

求救:IMX6ULL的PWM应用程序

[复制链接]

55

主题

159

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2016-7-16
在线时间
64 小时
发表于 2021-5-17 16:42:44 | 显示全部楼层 |阅读模式
10金钱
本帖最后由 清秋枫叶 于 2021-5-17 16:50 编辑

版主和各位大侠好:
     本人linux菜鸟,在根据教程学习IMX6ULL驱动编程,在学习到PWM编程时,发现教程只有驱动编程而没有对应的演示APP例程(别的例程都有驱动和对应的APP)。有没有对应的简易的APP例程?请提供,谢谢!


具体细节如下:IMX6U嵌入式linux驱动开发指南,第73章,Linux PWM驱动实验,在后面的驱动测试环节,使用的方法是:echo 50000 > /sys/class/pwm/pwmchip2/pwm0/period 设置频率,echo 10000 > /sys/class/pwm/pwmchip2/pwm0/duty_cycle设置占空比。那么,在应用程序里面,应该用什么函数呢?

最佳答案

查看完整内容[请看2#楼]

我也发现这个问题,我刚刚解决了。 正点原子和野火对于这个pwm,都没有说清楚。 韦东山老师没有pwm的讲解。 我结合他们三位老师的讲解,我摸索着解决了问题: 我这是实现了两路pwm的驱动和app测试 设备树: 驱动: APP:
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

9

主题

26

帖子

0

精华

初级会员

Rank: 2

积分
68
金钱
68
注册时间
2020-5-19
在线时间
14 小时
发表于 2021-5-17 16:42:45 | 显示全部楼层
我也发现这个问题,我刚刚解决了。
正点原子和野火对于这个pwm,都没有说清楚。
韦东山老师没有pwm的讲解。
我结合他们三位老师的讲解,我摸索着解决了问题:
我这是实现了两路pwm的驱动和app测试
设备树:

  1.         fs_pwm {
  2.                 compatible = "fsml,fs_pwm";
  3.                 pinctrl-names = "default";
  4.                 pinctrl-0 = <&pinctrl_fspwm>;
  5.                 pwm_power {
  6.                         pwm-names = "pwm_power";
  7.                         pwms =         <&pwm1 0 50000>;
  8.                 };
  9.                 pwm_motor {
  10.                         pwm-names = "pwm_motor";
  11.                         pwms =         <&pwm2 0 50000>;
  12.                 };

  13.         };


  14.         pinctrl_fspwm:fspwmgrp {
  15.                 fsl,pins = <
  16.                         MX6UL_PAD_LCD_DATA00__PWM1_OUT          0x1b0b0        /*/pwm1&motor pwm*/       
  17.                         MX6UL_PAD_LCD_DATA01__PWM2_OUT          0x1b0b0        /*/pwm1&motor pwm*/       
  18.                 >;
复制代码

驱动:
  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/platform_device.h>
  4. #include <linux/of_platform.h>
  5. #include <linux/err.h>
  6. #include <linux/pwm.h>
  7. #include <linux/slab.h>
  8. #include <linux/types.h>
  9. #include <linux/seq_file.h>
  10. #include <linux/stat.h>
  11. #include <linux/tty.h>
  12. #include <linux/kmod.h>
  13. #include <linux/gfp.h>

  14. struct pwm_device        *pwm_power_dev = NULL;  //定义pwm设备结构体
  15. struct pwm_device   *pwm_motor_dev = NULL;
  16. /*精简版 prob函数*/

  17. /* 1. 确定主设备号                                                                 */
  18. static int major = 0;
  19. static struct class *fspwm_class;
  20. //static struct gpio_desc *led_gpio;

  21. /* 3. 实现对应的open/read/write等函数,填入file_operations结构体                   */
  22. static ssize_t fspwm_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
  23. {
  24.         printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  25.         return 0;
  26. }

  27. /* write(fd, &val, 1); */
  28. static ssize_t fspwm_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
  29. {
  30.         int err;
  31.     int k_buf = 0;
  32.         short duty_ns,period;
  33.         //struct inode *inode = file_inode(file);
  34.         //int minor = iminor(inode);
  35.        
  36.         printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  37.         err = copy_from_user(&k_buf, (void*)buf, sizeof(int));

  38.     period = k_buf & 0xffff;
  39.     duty_ns = (k_buf >> 16) & 0xffff;

  40.         err = pwm_config(pwm_power_dev, duty_ns, period);
  41.         err = pwm_config(pwm_motor_dev, duty_ns, period);
  42.     printk("%s %d %d %d\r\n", __FUNCTION__, k_buf,  duty_ns, period);
  43.        
  44.         return 1;
  45. }

  46. static int fspwm_open (struct inode *node, struct file *file)
  47. {
  48.         //int minor = iminor(node);
  49.        
  50.         printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  51.        
  52.         return 0;
  53. }

  54. static int fspwm_close (struct inode *node, struct file *file)
  55. {
  56.         printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  57.         return 0;
  58. }

  59. /* 定义自己的file_operations结构体                                              */
  60. static struct file_operations fspwm_dev = {
  61.         .owner         = THIS_MODULE,
  62.         .open    = fspwm_open,
  63.         .read    = fspwm_read,
  64.         .write   = fspwm_write,
  65.         .release = fspwm_close,
  66. };




  67. static int pwm_power_probe_new(struct platform_device *pdev)
  68. {
  69.         int ret = 0;
  70.         struct device_node * child;
  71.         struct device_node * child2;
  72.         struct device *dev = &pdev->dev;
  73.         printk("match success \n");

  74.     //注册operations
  75.     major = register_chrdev(0, "fspwm", &fspwm_dev);

  76.         fspwm_class = class_create(THIS_MODULE, "fspwm_class");
  77.         if (IS_ERR(fspwm_class)) {
  78.                 printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  79.                 unregister_chrdev(major, "fspwm");
  80.                 return PTR_ERR(fspwm_class);
  81.         }

  82.     device_create(fspwm_class, NULL, MKDEV(major, 0), NULL, "fspwm_%s","motor");

  83.         child = of_get_next_child(dev->of_node, NULL);
  84.     printk(""%s"'s child: "%s"\n", dev->of_node->full_name, child->full_name);
  85.     printk("%s %s line %d\r\n"__FILE__, __FUNCTION__, __LINE__);
  86.     if(NULL == child)
  87.     {
  88.         printk("of_get_next_child error\r\n");
  89.     }
  90.         if (child)
  91.         {
  92.                 pwm_power_dev = devm_of_pwm_get(dev, child, NULL);
  93.                 if (IS_ERR(pwm_power_dev))
  94.                 {
  95.                         printk(KERN_ERR" pwm_power_dev,get pwm  error!!\n");
  96.                         return -1;
  97.                 }
  98.         
  99.         //pwm_motor_dev = devm_of_pwm_get(dev, chile, )
  100.         }
  101.         else
  102.         {
  103.                 printk(KERN_ERR" pwm_power_dev of_get_next_child  error!!\n");
  104.                 return -1;
  105.         }

  106.         child2 = of_get_next_child(dev->of_node, child);
  107.    
  108.     printk(""%s"'s child2: "%s"\n", dev->of_node->full_name, child2->full_name);
  109.     printk(""%s"'s child2: "%s"\n", dev->of_node->full_name, child2->full_name);
  110.     printk(""%s"'s child2: "%s"\n", dev->of_node->full_name, child2->full_name);
  111.     printk("%s %s line %d\r\n"__FILE__, __FUNCTION__, __LINE__);
  112.     if(NULL == child2)
  113.     {
  114.         printk("of_get_next_child2 error\r\n");
  115.     }
  116.         if (child2)
  117.         {
  118.         if (IS_ERR(child2))
  119.                 {
  120.                         printk(KERN_ERR" of_get_next_child,child2  error!!\n");
  121.                         return -1;
  122.                 }

  123.         printk(""%s"'s devm_of_pwm_get: "%s"\n", dev->of_node->full_name, child2->full_name);
  124.                 pwm_motor_dev = devm_of_pwm_get(dev, child2, NULL);
  125.         //pwm_motor_dev = devm_pwm_get(dev, child2->full_name);
  126.                 if (IS_ERR(pwm_motor_dev))
  127.                 {
  128.                         printk(KERN_ERR" pwm_power_dev,get pwm  error!!\n");
  129.                         return -1;
  130.                 }
  131.         }
  132.         else
  133.         {
  134.                 printk(KERN_ERR" pwm_power_dev of_get_next_child  error!!\n");
  135.                 return -1;
  136.         }

  137.     printk("set pwm_power...\r\n");

  138.         /*配置频率100KHz 占空比80%*/
  139.         ret = pwm_config(pwm_power_dev, 1000, 5000);
  140.     printk("ret:%d\r\n", ret);
  141.         /*反相 频率100KHz 占空比20%*/
  142.         ret = pwm_set_polarity(pwm_power_dev, PWM_POLARITY_INVERSED);
  143.     printk("ret:%d\r\n", ret);
  144.         ret = pwm_enable(pwm_power_dev);
  145.     printk("ret:%d\r\n", ret);

  146.     printk("set pwm_motor...\r\n");
  147.         /*配置频率100KHz 占空比80%*/
  148.         ret = pwm_config(pwm_motor_dev, 1000, 5000);
  149.     printk("ret:%d\r\n", ret);
  150.         /*反相 频率100KHz 占空比20%*/
  151.         ret = pwm_set_polarity(pwm_motor_dev, PWM_POLARITY_NORMAL);
  152.     printk("ret:%d\r\n", ret);
  153.         ret = pwm_enable(pwm_motor_dev);
  154.     printk("ret:%d\r\n", ret);

  155.         return ret;
  156. }

  157. static int pwm_power_remove(struct platform_device *pdev)
  158. {

  159.         device_destroy(fspwm_class, MKDEV(major, 0));
  160.         class_destroy(fspwm_class);
  161.         unregister_chrdev(major, "fspwm");
  162.     printk("%s %s line %d\r\n"__FILE__, __FUNCTION__, __LINE__);
  163.         return 0;
  164. }

  165. static const struct of_device_id of_pwm_leds_match[] = {
  166.         {.compatible = "fs_pwm"},
  167.         {},
  168. };

  169. static struct platform_driver led_pwm_driver = {
  170.         .probe                = pwm_power_probe_new,
  171.         .remove                = pwm_power_remove,
  172.         .driver                = {
  173.                 .name        = "fs_pwm",
  174.                 .of_match_table = of_pwm_leds_match,
  175.         },
  176. };

  177. /*
  178. *驱动初始化函数
  179. */
  180. static int __init pwm_driver_init(void)
  181. {
  182.     printk("%s %s line %d\r\n"__FILE__, __FUNCTION__, __LINE__);
  183.         return platform_driver_register(&led_pwm_driver);
  184. }

  185. /*
  186. *驱动注销函数
  187. */
  188. static void __exit pwm_driver_exit(void)
  189. {
  190.         printk(KERN_ERR "%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
  191.         /*注销平台设备*/
  192.         platform_driver_unregister(&led_pwm_driver);
  193. }

  194. module_init(pwm_driver_init);
  195. module_exit(pwm_driver_exit);

  196. MODULE_LICENSE("GPL");








复制代码


APP:
  1. #include "stdio.h"
  2. #include "unistd.h"
  3. #include "sys/types.h"
  4. #include "sys/stat.h"
  5. #include "fcntl.h"
  6. #include "stdlib.h"
  7. #include "string.h"
  8. //#include "linux/ioctl.h"
  9. #include "sys/ioctl.h"


  10. int main(int argc, char *argv[])
  11. {
  12.     int fd = 0;
  13.     int ret = 0;
  14.     int data = 0;
  15.     char *filename = NULL;
  16.     unsigned int value = 0;
  17.     unsigned short duty,period;
  18.     int cmd=0;

  19.     printf("\r\n\r\n\r\nargc num:%d\r\n",argc);

  20.     filename = argv[1];
  21.     duty = atoi(argv[2]);
  22.     period = atoi(argv[3]);
  23.     cmd = (duty << 16)+period;
  24.     fd = open(filename, O_RDWR);
  25.     if(0 > fd)
  26.     {
  27.         printf("can't open file %s\r\n", filename);
  28.         return -1;
  29.     }
  30.     printf("open fsio_dev ok cmd:%d\r\n",cmd);

  31.     write(fd, &cmd, sizeof(int));

  32.     close(fd);
  33.     printf("open fsio_dev ok cmd:%d,%d,%d\r\n",cmd,duty,period);
  34.     return ret;   
  35. }
复制代码
回复

使用道具 举报

55

主题

159

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2016-7-16
在线时间
64 小时
 楼主| 发表于 2021-5-17 16:50:13 | 显示全部楼层
具体细节如下:IMX6U嵌入式linux驱动开发指南,第73章,Linux PWM驱动实验,在后面的驱动测试环节,使用的方法是:echo 50000 > /sys/class/pwm/pwmchip2/pwm0/period 设置频率,echo 10000 > /sys/class/pwm/pwmchip2/pwm0/duty_cycle设置占空比。那么,在应用程序里面,应该用什么函数呢?
回复

使用道具 举报

7

主题

480

帖子

0

精华

高级会员

Rank: 4

积分
771
金钱
771
注册时间
2021-4-15
在线时间
304 小时
发表于 2021-5-17 17:19:03 | 显示全部楼层
帮顶  
回复

使用道具 举报

55

主题

159

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2016-7-16
在线时间
64 小时
 楼主| 发表于 2021-5-18 10:04:15 | 显示全部楼层
本帖最后由 清秋枫叶 于 2021-5-19 13:46 编辑

非常感谢2楼回复,我现在试一下。
回复

使用道具 举报

5

主题

120

帖子

0

精华

高级会员

Rank: 4

积分
813
金钱
813
注册时间
2021-2-26
在线时间
117 小时
发表于 2021-5-18 16:26:31 | 显示全部楼层
兄弟,你要知道pwm是什么,他是干什么用的。
你没接外围设备的话,简单一点,用万用表电压档测电压,不同的duty cycle会有不同的电压输出。
如果你有示波器的话,那就更直观了。
当然,你也是可以接上外围设备的,比如pwm控制的lcd背光
回复

使用道具 举报

70

主题

6698

帖子

0

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
12692
金钱
12692
注册时间
2012-11-26
在线时间
3711 小时
发表于 2021-5-18 16:32:13 | 显示全部楼层
它那个echo其实就是写数据   你正常打开 写  就好了
回复

使用道具 举报

55

主题

159

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2016-7-16
在线时间
64 小时
 楼主| 发表于 2021-5-19 10:48:26 | 显示全部楼层
实际上,无论是backlight的(pwm1)还是教程PWM3,教程都有驱动。我现在卡壳地方是,是如何知道PWM设备名称,并在应用程序里面调用。
看来我得再下功夫学习一下。
回复

使用道具 举报

55

主题

159

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2016-7-16
在线时间
64 小时
 楼主| 发表于 2021-5-19 13:43:13 | 显示全部楼层
本帖最后由 清秋枫叶 于 2021-5-19 13:45 编辑

非常感谢2楼回复,只是,我在测试的时候,输入:./pwmApp  /dev/pwm的时候,提示找不到这个文件(设备)
if(0 > fd)
    {
        printf("can't open file %s\r\n", filename);
        return -1;
    }

filename输入错误。  而且即使我运行  depmod  ;   modprobe  pwm.ko;  在/sys/dev/目录下也没有找到对应的设备。
请问,我的问题出在哪里?
回复

使用道具 举报

55

主题

159

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2016-7-16
在线时间
64 小时
 楼主| 发表于 2021-5-19 13:44:20 | 显示全部楼层
补充一下,我把驱动文件命名为pwm.c ,应用程序命名为pwmApp.c
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
21
金钱
21
注册时间
2019-8-7
在线时间
5 小时
发表于 2021-7-20 15:11:53 | 显示全部楼层
jckimi 发表于 2021-5-18 16:26
兄弟,你要知道pwm是什么,他是干什么用的。
你没接外围设备的话,简单一点,用万用表电压档测电压,不同 ...

你好,请问你有没有遇到
                if (IS_ERR(pwm_power_dev))
                {
                        printk(KERN_ERR" pwm_power_dev,get pwm power error!!\n");
                        return -1;
                }
这一步出现错误?我在 get pwm error中间加了一个power
回复

使用道具 举报

3

主题

39

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
482
金钱
482
注册时间
2021-1-16
在线时间
52 小时
发表于 2021-7-21 14:39:47 | 显示全部楼层
就是open,然后将export 的数据write进去;完了close
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 18:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表