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 =\n%d\n", 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\n");
    return 0;
}

static int read_pwm_release(struct inode *inode, struct file *file)
{
    printk(KERN_EMERG "read pwm release\n");
    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\n", 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 "\tread pwm start initialized\n");
    /* set up gpio */
    // ret = gpio_request(GPIO_CHG_FLT, "GPX1_0");
    // if(ret < 0) {
    //     printk(KERN_EMERG "request GPIO %d for read pwm failed\n", 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.\n");
        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 "\tread pwm remove\n");

    // 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!\n");
    DriverState = platform_driver_register(&read_pwm_driver);

    printk(KERN_EMERG "\tDriverState is %d\n", DriverState);
    return 0;
}

static void read_pwm_exit(void)
{
    printk(KERN_EMERG "Read pwm exit!\n");
    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\n", buff[0]|buff[1]<<8);
        usleep(100000);
    }
    printf("sizeof(value) is %d\n", sizeof(buff));
    printf("read return is %d\n", ret);
    return 0;
}
read_pwm_app

 

posted @ 2018-09-10 10:03  习惯就好233  阅读(1016)  评论(0编辑  收藏  举报