• 4412 gpio读取pwm


    一、可以使用的GPIO管脚

    去掉占用调用的GPIO驱动,包括ledsbuzzercamera ov5640WIFI mt6620 ,Keyboards

    • VIDEO_OV5640Device Drivers
      • Multimedia support(MEDIA_SUPPORT [=y])
      • Video capture adapters(VIDEO_CAPTURE_DRIVERS [=y])(去掉)
    • MTK_COMBO_CHIP_MT6620Device Drivers
      • MediaTek Connectivity Combo Chip Config
      • MediaTek Connectivity Combo Chip Support (MTK_COMBO [=y])(去掉)
      • Select Chip (<choice> [=y])
    • Enable LEDS configDevice Drivers
      • Character devices
      • Enable LEDS config
    • Enable BUZZER config
      • Device Drivers
      • Character devices
      • Enable BUZZER config
    • Enable Keyboards
      • Device Drivers  --->
      • Input device support  --->
      • Keyboards  ---> 
    static int led_gpios[] = {
        EXYNOS4_GPL2(0), EXYNOS4_GPK(1),    /* Led IO 2个 */
        EXYNOS4_GPD0(0),              /* BUZZER IO 1个 */
    
        EXYNOS4_GPX1(0), EXYNOS4_GPX1(3),EXYNOS4_GPX1(5),EXYNOS4_GPX1(6),    /* 矩阵健盘8个 */
        EXYNOS4_GPX3(0),EXYNOS4_GPX2(6),EXYNOS4_GPX2(7),EXYNOS4_GPX3(5),
    
        EXYNOS4212_GPJ1(3),EXYNOS4_GPL0(1),EXYNOS4_GPL0(3),EXYNOS4212_GPJ1(0),      /* 摄像头14个 */
        EXYNOS4212_GPJ1(2),EXYNOS4212_GPJ1(1),EXYNOS4212_GPJ0(7),EXYNOS4212_GPJ0(6),
        EXYNOS4212_GPJ0(5),EXYNOS4212_GPJ0(4),EXYNOS4212_GPJ0(0),EXYNOS4212_GPJ0(3),
       EXYNOS4212_GPJ0(1),EXYNOS4212_GPJ0(2),
    
        EXYNOS4_GPK3(6),EXYNOS4_GPK3(1),EXYNOS4_GPK3(4),EXYNOS4_GPK3(0),      /* WIFI 7个 */
        EXYNOS4_GPK3(3),EXYNOS4_GPK3(5),EXYNOS4_GPC1(1),
    };
    led_gpios数组

    二、设计思路

    • 通过外部中断来处理电路上升沿和下降沿的跳变处理
    • 通过读取IO管脚,来判断是上升沿触发还是下降沿触发
    • 使用do_gettimeofday来获取时间戳,从而计算高电平时间

    下面是我的源码:

    #include <linux/init.h>
    #include <linux/module.h>
    
    /* */
    #include <linux/platform_device.h>
    #include <linux/miscdevice.h>
    #include <linux/fs.h>
    
    #include <linux/gpio.h>
    #include <plat/gpio-cfg.h>
    #include <mach/gpio.h>
    #include <mach/gpio-exynos4.h>
    
    #include <asm/uaccess.h>
    #include <linux/irq.h>
    #include <linux/interrupt.h>
    
    #include <linux/time.h>
    
    #define DRIVER_NAME "ReadPwm"
    #define DEVICE_NAME "read_pwm"
    
    MODULE_LICENSE("Dual BSD/GPL");
    MODULE_AUTHOR("TOPEET");
    
    #define GPIO_CHG_FLT    EXYNOS4_GPX1(0)
    
    static int up_flag = 0;
    struct platform_device *dev_int;
    /* led: KP_COL0, VDD50_EN */
    /* BUZZER: MOTOR_PWM */
    /* keyboards: CHG_FLT, HOOK_DET, CHG_UOK, XEINT14_BAK, GM_INT1,
        6260_GPIO1, CHG_COK, XEINT29/KP_ROW13/ALV_DBG25 */
    /* camera: CAM_MCLK, CAM2M_RST, CAM2M_PWDN, CAM_D5, CAM_D7, CAM_D6,
        CAM_D4, CAM_D3, CAM_D2, CAM_D1, CAM_PCLK, CAM_D0, CAM_VSYNC, CAM_HREF */
    /* WIFI: WIFI_D3, WIFI_CMD, WIFI_D1, WIFI_CLK, WIFI_D0, WIFI_D2,GPC1_1 */
    struct timeval tv_begin, tv_end;
    static int interval = 0;
    struct semaphore sem;
    
    static irqreturn_t qint8_interrupt(int irq, void *dev_id)
    {
        int ret;
        ret = gpio_get_value(GPIO_CHG_FLT);
        if(ret == 0) {
            do_gettimeofday(&tv_end);
            if(tv_end.tv_usec - tv_begin.tv_usec > 0) {
                down(&sem);
                interval = tv_end.tv_usec - tv_begin.tv_usec;
                up(&sem);
            }
            // if(printk_ratelimit()) {
            //     printk("tv_end.usec:%d - tv_begin.usec:%d =
    %d
    ", tv_end.usec,
            //         tv_begin.usec, tv_end.usec - tv_begin.usec);
            // }
        } else if(ret == 1) {
            do_gettimeofday(&tv_begin);
        }
        return IRQ_HANDLED;
    }
    
    static int read_pwm_open(struct inode *inode, struct file *file)
    {
        printk(KERN_EMERG "read pwm open
    ");
        return 0;
    }
    
    static int read_pwm_release(struct inode *inode, struct file *file)
    {
        printk(KERN_EMERG "read pwm release
    ");
        return 0;
    }
    
    static ssize_t read_pwm_read(struct file *filp, char __user *buff, size_t size, loff_t *ppos)
    {
        unsigned int key_value = 0;
        char temp[2];
        int ret;
        // printk(KERN_EMERG "sizeof(key_value) is %d
    ", sizeof(key_value));
        if(size != sizeof(temp)) {
            return -1;
        }
        down(&sem);
        key_value = interval;
        up(&sem);
    
        temp[0] = ((key_value)&0xff);
        temp[1] = ((key_value>>8)&0xff);
    
        ret = copy_to_user(buff, temp, sizeof(temp));
    
        return ret;
    }
    
    static struct file_operations read_pwm_ops = {
        .owner      = THIS_MODULE,
        .open       = read_pwm_open,
        .release    = read_pwm_release,
        .read       = read_pwm_read,
    };
    
    static struct miscdevice read_pwm_dev = {
        .minor  = MISC_DYNAMIC_MINOR,
        .name   = DEVICE_NAME,
        .fops   = &read_pwm_ops,
    };
    
    static int read_pwm_probe(struct platform_device *pdv)
    {
        int ret;
        printk(KERN_EMERG "	read pwm start initialized
    ");
        /* set up gpio */
        // ret = gpio_request(GPIO_CHG_FLT, "GPX1_0");
        // if(ret < 0) {
        //     printk(KERN_EMERG "request GPIO %d for read pwm failed
    ", GPIO_CHG_FLT);
        //     return ret;
        // }
    
        // s3c_gpio_cfgpin(GPIO_CHG_FLT, S3C_GPIO_INPUT);
        // s3c_gpio_setpull(GPIO_CHG_FLT, S3C_GPIO_PULL_NONE);
        ret = request_irq(IRQ_EINT(8), qint8_interrupt, IRQ_TYPE_EDGE_BOTH, "my_eint8", pdv);
        if(ret < 0) {
            printk(KERN_EMERG "request irq 8 failed.
    ");
            return 0;
        }
        up_flag = 1;
        dev_int = pdv;
        sema_init(&sem, 1);
        /* register */
        ret = misc_register(&read_pwm_dev);
        if(ret < 0) {
            gpio_free(GPIO_CHG_FLT);
            misc_deregister(&read_pwm_dev);
            return -EINVAL;
        }
    
        return 0;
    }
    
    static int read_pwm_remove(struct platform_device *pdv)
    {
        printk(KERN_EMERG "	read pwm remove
    ");
    
        // gpio_free(GPIO_CHG_FLT);
        free_irq(IRQ_EINT(8), pdv);
        misc_deregister(&read_pwm_dev);
        return 0;
    }
    
    static void read_pwm_shutdown(struct platform_device *pdv)
    {
    
    }
    
    static int read_pwm_suspend(struct platform_device *pdv, pm_message_t pmt)
    {
        return 0;
    }
    
    static int read_pwm_resume(struct platform_device *pdv)
    {
        return 0;
    }
    
    struct platform_driver read_pwm_driver = {
        .probe      = read_pwm_probe,
        .remove     = read_pwm_remove,
        .shutdown   = read_pwm_shutdown,
        .suspend    = read_pwm_suspend,
        .resume     = read_pwm_resume,
        .driver = {
            .name   = DRIVER_NAME,
            .owner  = THIS_MODULE, 
        }
    };
    
    static int read_pwm_init(void)
    {
        int DriverState;
    
        printk(KERN_EMERG "Read pwm init enter!
    ");
        DriverState = platform_driver_register(&read_pwm_driver);
    
        printk(KERN_EMERG "	DriverState is %d
    ", DriverState);
        return 0;
    }
    
    static void read_pwm_exit(void)
    {
        printk(KERN_EMERG "Read pwm exit!
    ");
        platform_driver_unregister(&read_pwm_driver);
    }
    
    module_init(read_pwm_init);
    module_exit(read_pwm_exit);
    read_pwm.c

    还有一个问题,卸载模块后再装载就会报错,不知道为什么。

    app源码:

    #include <sys/types.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/stat.h>
    
    
    #define READ_PWM "/dev/read_pwm"
    
    int main()
    {
        long value = 0;
        int fd;
        char buff[2];
        int ret;
    
        fd = open(READ_PWM, O_RDWR|O_NDELAY);
        if(fd < 0) {
            perror("open");
        }
    
        while(ret = read(fd, buff, sizeof(buff)) >= 0) {
            printf("value is %d
    ", buff[0]|buff[1]<<8);
            usleep(100000);
        }
        printf("sizeof(value) is %d
    ", sizeof(buff));
        printf("read return is %d
    ", ret);
        return 0;
    }
    read_pwm_app
  • 相关阅读:
    spring mvc 数据回显
    spring mvc 数据校验
    如何构建高性能web站点之:分布式缓存
    面霸吕国栋之:整理的一些面试题
    项目中我为什么用Mongodb取代Mysql
    对mysql存储性能优化的基本理解
    SQL语句面试题(IN、NOT IN、COUNT、GROUP BY)
    java面试题
    java中的网络通信编程之UDP篇
    java中的网络通信编程之TCP篇
  • 原文地址:https://www.cnblogs.com/ch122633/p/9617514.html
Copyright © 2020-2023  润新知