新聞中心

        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

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 图木舒克市| 扎赉特旗| 定安县| 海晏县| 东乌珠穆沁旗| 西乌珠穆沁旗| 青海省| 桐柏县| 大足县| 融水| 鄂托克前旗| 灵武市| 丰镇市| 磐石市| 宿迁市| 通化市| 泰兴市| 武夷山市| 揭阳市| 嘉定区| 逊克县| 西乡县| 大邑县| 宁海县| 牙克石市| 潍坊市| 溧水县| 永济市| 砚山县| 北宁市| 淅川县| 博客| 沅江市| 碌曲县| 兰西县| 衢州市| 建瓯市| 楚雄市| 宽城| 印江| 巴林右旗|