新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 外設一個一個學_PWM

        外設一個一個學_PWM

        作者: 時間:2016-11-10 來源:網絡 收藏
        PWM脈沖寬度調制(PWM)!
        一般用途:電機、機器人。系統時鐘(當然一般是RTC)、蜂鳴器、手機屏幕明暗調節:
        1、書寫流程。
        根據芯片手冊、
        關于使用PWM驅動蜂鳴器的步驟。
        ①:設置PWM的模式為PWMTOUT1 GPDCON 0XE0300080
        在4~7位 寫入 0x2
        ②:PWM_ON PWM_OFF /*作為控制命令參數*/
        ③:設置預分頻函數:SET_PRE SET_CNT TCNTM=2TCMPB 占空比
        ④:關于寄存器的修改
        TCFG0 0XEA000000
        TCFG1 4~7
        TCON 0XEA000008
        8~11 0x2 0010
        0x9 1001
        驅動如下:

        #ifndef __S5PC100_LED_HHHH
        #define __S5PC100_LED_HHHH

        //need arg = 0/1/2/3
        #define PWM_ON _IO(K, 0)
        #define PWM_OFF _IO(K, 1)
        #define SET_PRE _IO(K, 2)
        #define SET_CNT _IO(K, 3)

        #endif

        本文引用地址:http://www.104case.com/article/201611/317488.htm

        #include
        #include
        #include
        #include
        #include

        #include
        #include

        #include "s5pc100_pwm.h"

        MODULE_LICENSE("GPL");

        #define S5PC100_GPDCON 0xE0300080
        #define S5PC100_TIMER_BASE 0xEA000000

        #define S5PC100_TCFG0 0x00
        #define S5PC100_TCFG1 0x04
        #define S5PC100_TCON 0x08
        #define S5PC100_TCNTB1 0x18
        #define S5PC100_TCMPB1 0x1C

        static int pwm_major = 250;
        static int pwm_minor = 0;
        static int number_of_device = 1;

        struct s5pc100_pwm
        {
        struct cdev cdev;
        unsigned int *gpdcon;
        void __iomem *timer_base;
        };

        struct s5pc100_pwm *pwm;

        static int s5pc100_pwm_open(struct inode *inode, struct file *file)
        {
        writel((readl(pwm->gpdcon) & ~(0xf << 4)) | (0x2 << 4), pwm->gpdcon);
        writel(readl(pwm->timer_base + S5PC100_TCFG0) | 0xff, pwm->timer_base + S5PC100_TCFG0);
        writel((readl(pwm->timer_base + S5PC100_TCFG1) & ~(0xf << 4)) | (0x2 << 4), pwm->timer_base + S5PC100_TCFG1);
        writel(0x200, pwm->timer_base + S5PC100_TCNTB1);
        writel(0x100, pwm->timer_base + S5PC100_TCMPB1);
        writel((readl(pwm->timer_base + S5PC100_TCON) & ~(0xf << 8)) | (0x2 << 8), pwm->timer_base + S5PC100_TCON);
        //writel((readl(pwm->timer_base + S5PC100_TCON) & ~(0xf << 8)) | (0x9 << 8), pwm->timer_base + S5PC100_TCON);

        return 0;
        }

        static int s5pc100_pwm_release(struct inode *inode, struct file *file)
        {
        return 0;
        }

        static long s5pc100_pwm_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        {
        switch(cmd)
        {
        case PWM_ON:
        writel((readl(pwm->timer_base + S5PC100_TCON) & ~(0xf << 8)) | (0x9 << 8), pwm->timer_base + S5PC100_TCON);
        break;
        case PWM_OFF:
        writel(readl(pwm->timer_base + S5PC100_TCON) & ~(0xf << 8), pwm->timer_base + S5PC100_TCON);
        break;
        case SET_PRE:
        writel(readl(pwm->timer_base + S5PC100_TCON) & ~(0xf << 8), pwm->timer_base + S5PC100_TCON);
        writel((readl(pwm->timer_base + S5PC100_TCFG0) & ~0xff) | arg, pwm->timer_base + S5PC100_TCFG0);
        writel((readl(pwm->timer_base + S5PC100_TCON) & ~(0xf << 8)) | (0x9 << 8), pwm->timer_base + S5PC100_TCON);
        break;
        case SET_CNT:
        writel(arg, pwm->timer_base + S5PC100_TCNTB1);
        writel(arg >> 1, pwm->timer_base + S5PC100_TCMPB1);
        break;
        }

        return 0;
        }

        static struct file_operations s5pc100_pwm_fops = {
        .owner = THIS_MODULE,
        .open = s5pc100_pwm_open,
        .release = s5pc100_pwm_release,
        .unlocked_ioctl = s5pc100_pwm_unlocked_ioctl,
        };

        static int s5pc100_pwm_init(void)
        {
        int ret;

        dev_t devno = MKDEV(pwm_major, pwm_minor);

        ret = register_chrdev_region(devno, number_of_device, "s5pc100_pwm");
        if (ret < 0) {
        printk("register_chrdev_regionn");
        return ret;
        }

        pwm = kmalloc(sizeof(*pwm), GFP_KERNEL);
        if (pwm == NULL) {
        ret = -ENOMEM;
        goto err1;
        }

        cdev_init(&pwm->cdev, &s5pc100_pwm_fops);
        pwm->cdev.owner = THIS_MODULE;
        ret = cdev_add(&pwm->cdev, devno, 1);
        if (ret < 0) {
        printk("cdev_addn");
        goto err2;
        }

        pwm->gpdcon = ioremap(S5PC100_GPDCON, 4);
        if (pwm->gpdcon == NULL) {
        ret = -EINVAL;
        goto err3;
        }

        pwm->timer_base = ioremap(S5PC100_TIMER_BASE, 0x30);
        if (pwm->timer_base == NULL) {
        ret = -EINVAL;
        goto err4;
        }

        return 0;
        err4:
        iounmap(pwm->gpdcon);
        err3:
        cdev_del(&pwm->cdev);
        err2:
        kfree(pwm);
        err1:
        unregister_chrdev_region(devno, number_of_device);
        return ret;
        }

        static void s5pc100_pwm_exit(void)
        {
        dev_t devno = MKDEV(pwm_major, pwm_minor);
        iounmap(pwm->gpdcon);
        iounmap(pwm->timer_base);
        cdev_del(&pwm->cdev);
        kfree(pwm);
        unregister_chrdev_region(devno, number_of_device);
        }

        module_init(s5pc100_pwm_init);
        module_exit(s5pc100_pwm_exit);

        /**/



        關鍵詞: 外設PW

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 恭城| 吉安县| 桦川县| 邻水| 长兴县| 福海县| 池州市| 桐梓县| 双辽市| 沙坪坝区| 偏关县| 阿巴嘎旗| 桓台县| 肃南| 三都| 巨鹿县| 新巴尔虎左旗| 许昌市| 汝阳县| 阳信县| 郑州市| 宁化县| 宣化县| 都兰县| 宜都市| 岳阳市| 平潭县| 苏州市| 长治县| 沾益县| 瓦房店市| 太保市| 醴陵市| 沧源| 漳平市| 新兴县| 石嘴山市| 怀仁县| 马鞍山市| 金堂县| 盐亭县|