查看: 783|回复: 0

pcDuino Linux驱动开发五 -- 最简单的PWM驱动

[复制链接]
  • TA的每日心情
    奋斗
    2022-9-16 05:52
  • 签到天数: 1368 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2014-11-30 23:14:22 | 显示全部楼层 |阅读模式
    分享到:
    其实比较来说,PWM比中断还要简单,只不过一般刚接触的板子首先实现的都是基本的IO,所以把PWM安排在了中断之后。为了不使帖子看起来内容太少,这个程序将两路PWM 放在了一起,不过也是多了几个寄存器的设置而已。
    另外要吐槽一下A10,PWM少就不说什么了,居然计数寄存器只有8位。是的,只有8位,最大到255而已,这个也太弱了吧

    还有预分频,也只有这么几个

    看到0101...0111那几个了吗?经过尝试后,发现其实是起作用的,是/720、/840、/960,后面的1101...1111是84K、96K、108K,权当一点补偿吧。
    下面上程序,跟GPIO的一样,还是精简得不能再精简了。接线方式没来得及拍照,后面补上。

    • #include <linux/init.h>
    • #include <linux/module.h>
    • #include <linux/fs.h>
    • #include <linux/cdev.h>
    • #include <linux/device.h>
    • #include <linux/wait.h>
    • #include <linux/delay.h>
    • #include <asm/io.h>
    • #include <asm/uaccess.h>
    • #include "../A10.h"
    • /**********************************************************************/
    •      #define PWM_CH0            2
    •      volatile static unsigned long* REG_PB_CFG0;
    •      volatile static unsigned long* REG_PI_CFG0;
    •      volatile static unsigned long* REG_PWM_CTRL_REG;
    •      volatile static unsigned long* REG_PWM_CH0_PERIOD;
    •      volatile static unsigned long* REG_PWM_CH1_PERIOD;

    •      static int Inited = 0;
    • static int PWM_open(struct inode* n, struct file* f)
    • {
    •      int Result = 0;
    •      Inited++;
    •      if (Inited > 1)
    •      {
    •             return 0;
    •      }
    •      REG_PB_CFG0 = (volatile unsigned long*) ioremap(PB_CFG0, 4);
    •      REG_PI_CFG0 = (volatile unsigned long*) ioremap(PI_CFG0, 4);
    •      REG_PWM_CTRL_REG = (volatile unsigned long*) ioremap(PWM_CTRL_REG, 4);
    •      REG_PWM_CH0_PERIOD= (volatile unsigned long*) ioremap(PWM_CH0_PERIOD, 4);
    •      REG_PWM_CH1_PERIOD= (volatile unsigned long*) ioremap(PWM_CH1_PERIOD, 4);


    •      *REG_PB_CFG0 &= ~(0x7 << 8) ;
    •      *REG_PB_CFG0 |= (0x2 << 8) ; //PWM0

    •      *REG_PI_CFG0 &= ~(0x7 << 12) ;
    •      *REG_PI_CFG0 |= (0x2 << 12) ; //PWM1
    •      *REG_PWM_CH0_PERIOD = (249 << 16) + 5;
    •      *REG_PWM_CTRL_REG |= (0xF << 0);
    •      *REG_PWM_CTRL_REG |= (0x0 << 8) + (0x0 << 7) + (0x1 << 6) + (0x0 << 5);
    •      *REG_PWM_CTRL_REG |= (0x1 << 4);

    •      *REG_PWM_CH1_PERIOD = (249 << 16) + 5;
    •      *REG_PWM_CTRL_REG |= (0x8 << 15);
    •      *REG_PWM_CTRL_REG |= (0x0 << 23) + (0x0 << 22) + (0x1 << 21) + (0x1 << 20);
    •      *REG_PWM_CTRL_REG |= (0x1 << 19);
    •      printk("Open Finished!\n");
    •      return Result;
    • }
    • static ssize_t PWM_write(struct file* f, const char __user* buf, size_t len, loff_t* l)
    • {
    •      //printk("Write Finished!\n");
    •      return 0;
    • }
    • static ssize_t PWM_read(struct file* f, char __user* buf, size_t len, loff_t* l)
    • {
    •      //printk("Read Finished!\n");
    •      return 0;
    • }
    • static int PWM_close(struct inode* n, struct file* f)
    • {
    •      Inited--;
    •      if (Inited > 0)
    •      {
    •             return 0;
    •      }
    •      *REG_PWM_CTRL_REG = 0;
    •      *REG_PWM_CH0_PERIOD = 0;
    •      *REG_PWM_CH1_PERIOD = 0;

    •      iounmap(REG_PB_CFG0);
    •      iounmap(REG_PI_CFG0);
    •      iounmap(REG_PWM_CTRL_REG);
    •      iounmap(REG_PWM_CH0_PERIOD);
    •      iounmap(REG_PWM_CH1_PERIOD);
    •      printk("Close Finished!\n");
    •      return 0;
    • }
    • /**********************************************************************/
    •      #define DEV_NAME     &quotWM"
    •      #define DEV_COUNT     1
    •      static struct class* pClass;
    •      int major;

    •      static struct file_operations fops =
    •      {
    •             .owner = THIS_MODULE,
    •             .open = PWM_open,
    •             .write = PWM_write,
    •             .read = PWM_read,
    •             .release = PWM_close,
    •      };
    • static int __init PWM_init(void)
    • {
    •      major = register_chrdev(0, DEV_NAME, &fops);
    •      pClass = class_create(THIS_MODULE, DEV_NAME);
    •      if (pClass == NULL)
    •      {
    •             unregister_chrdev(major, DEV_NAME);
    •             return -1;
    •      }
    •      device_create(pClass, NULL, MKDEV(major, 0), NULL, DEV_NAME);

    •      PWM_open(NULL, NULL);
    •      //printk("Init Finished!\n");
    •      return 0;
    • }
    • static void __exit PWM_exit(void)
    • {
    •      PWM_close(NULL, NULL);

    •      unregister_chrdev(major, DEV_NAME);
    •      if (pClass)
    •      {
    •             device_destroy(pClass, MKDEV(major, 0));
    •             class_destroy(pClass);
    •      }
    •      //printk("Exit Finished!\n");
    • }
    • MODULE_LICENSE("GPL");
    • MODULE_AUTHOR("LiuYang");
    • module_init(PWM_init);
    • module_exit(PWM_exit);
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-12-19 01:07 , Processed in 0.123974 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.