其他分享
首页 > 其他分享> > 嵌入式学习4--混杂设备驱动

嵌入式学习4--混杂设备驱动

作者:互联网

混杂设备驱动主要用于一些功能简单的器件,将之整合到一起,major为10,minor一般为动态分配,其实实际的还是字符设备驱动。

比常规字符设备驱动更好的地方就是在于它简化了编写过程,将一些步骤整合到了一起,使代码更加简洁,可读性更高,也便于维护和移植。

以下代码为超声波传感器的驱动代码

1.超声波SRF05传感器,在这里只用了Vcc、Trig、Echo、GND四个脚

A.Vcc 接5V电源

B.Trig接主板输出端,主要是发送启动信号

C.Echo接输入端,主要检测这个脚传回来的值进行距离计算

D.GND接地

使用注意:如果带电操作,一定要保证先接地,否则极易损坏器件

 

 

2.时序图

A.触发信号为至少维持20uS的高电平信号,需要控制Trig引脚来做启动

B.模块会发出8个40KHz的脉冲信号,并检测回波

C.如果有回波,就输出回响信号,回响信号会通过Echo引脚检测,检测到后做相应的处理

D.计算的公式为

 

3.以下为驱动代码,Linux驱动代码需要从下向上看

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <mach/platform.h>
#include <linux/errno.h>
#include <linux/input.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>

#define DEVICE_NAME "ultra_drv"
#define GPIOC_CFG_ULTRA_TRIG (PAD_GPIO_B + 28)    //Trig引脚
#define GPIOC_CFG_ULTRA_ECHO (PAD_GPIO_B + 29)  //Echo引脚

static int echo_data_in(void)   
{
    gpio_direction_input(GPIOC_CFG_ULTRA_ECHO);  //设置为输入引脚
    return gpio_get_value(GPIOC_CFG_ULTRA_ECHO);  //检测当前电平
}

static int ultra_read_data(void)
{
    unsigned int time_cnt = 0;
    unsigned int distance = 0;
    int ret = 0;
    
    ret = echo_data_in();                    

    if(ret){
        while(echo_data_in() && ((time_cnt++) < 50000))      //如果返回的是高电平代表有回波信号,开始记录高电平持续时间
        {
            udelay(10);
        }
        
        distance = ((time_cnt * 3) / 2);  //当Echo拉低的时候,代码测距完成,开始计算
    }

    return (distance);
}

int ultra_drv_open(struct inode *inode, struct file *filp)
{
    printk("<4>" "ultra drv open\n");
    
    return 0;
}

ssize_t ultra_drv_read(struct file *filp, char __user *user_buf, size_t size, loff_t *offset)
{
    int ret = 0;
    unsigned int distance = 0;
    
    if(size != 4)
        return -EINVAL;
    
    gpio_direction_output(GPIOC_CFG_ULTRA_TRIG, 1);  //启动信号,控制Trig引脚拉高
    udelay(20);                                                                       //至少维持10uS的高电平
    gpio_set_value(GPIOC_CFG_ULTRA_TRIG, 0);            //拉低Trig引脚,启动成功
    
    distance = ultra_read_data();                                            //开始检测Echo是否有回波信号
    
    ret = copy_to_user((int *)user_buf, &distance, sizeof(distance));  //将检测到的距离copy到用户空间,通过read读取到
    
    return 0;
}

static struct file_operations ultra_drv_fops = {      //文件操作集
    .owner = THIS_MODULE,
    .open  = ultra_drv_open,
    .read  = ultra_drv_read
};

static struct miscdevice ultra_drv_miscdev = {   //混杂设备
    .minor = MISC_DYNAMIC_MINOR,  //动态分配minor(此设备号)
    .name  = DEVICE_NAME,                 //设备名,使用open打开的就是这个名字
    .fops  = &ultra_drv_fops                     //文件操作集
}; 

static int __init ultra_drv_init(void)
{
    int ret = 0;
    
    gpio_free(GPIOC_CFG_ULTRA_TRIG);     //野路子,避免内核中已经有功能使用该引脚,先释放掉
    
    ret = gpio_request(GPIOC_CFG_ULTRA_TRIG, "ultra_drv");       //释放后再申请给我们使用
    if(ret < 0){
        printk("<4>" "gpio_request %s %d fail\n", DEVICE_NAME, GPIOC_CFG_ULTRA_TRIG);
        return ret;
    }

    ret = misc_register(&ultra_drv_miscdev);        //注册混杂设备
    if(ret < 0){
        printk("<4>" "misc_register fail\n");
        return ret;
    }
    
    printk("<4>" "ultra drv init\n");
    
    return 0;
}

static void __exit ultra_drv_exit(void)
{
    gpio_free(GPIOC_CFG_ULTRA_TRIG);
    
    misc_deregister(&ultra_drv_miscdev);
    
    printk("<4>" "ultra drv exit\n");
}

module_init(ultra_drv_init);
module_exit(ultra_drv_exit);

MODULE_AUTHOR("ayl0521@sina.com");  //如有问题,可邮件探讨
MODULE_DESCRIPTION("ultrasonic drv");
MODULE_LICENSE("GPL");

标签:ULTRA,include,混杂,int,ret,drv,嵌入式,驱动,ultra
来源: https://blog.csdn.net/origina1s/article/details/89477569