混杂设备驱动主要用于一些功能简单的器件,将之整合到一起,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");

嵌入式学习4--混杂设备驱动相关推荐

  1. Linux内核学习-字符设备驱动学习(二)

    在Linux内核学习-字符设备驱动学习(一)中编写字符设备驱动的一种方法,但是需要手动创建设备节点. 有没有能够自动的创建设备节点的呢? 有!使用class_create()和device_creat ...

  2. 嵌入式linux下网卡设备驱动与网络协议栈的设计实现.pdf,嵌入式系统的通用网络驱动模型设计与实现.pdf...

    维普资讯 第3O卷第4期 长春理工大学学报 (自然科学版 ) VO1.3O N0.4 2007年 12月 JournalofChangchunUniversityofScienceandTechnol ...

  3. linux 混杂设备驱动之adc驱动

    linux2.6.30.4中,系统已经自带有了ADC通用驱动文件---arch/arm/plat-s3c24xx/adc.c,它是以平台驱动设备模型的架构来编写的,里面是一些比较通用稳定的代码,但是l ...

  4. Linux驱动之混杂设备(misc)

    字符设备之混杂设备: 定义混杂设备: struct misdevice{ int  minor; //为什么这里只有次设备号,因为混杂设备是一种在                          / ...

  5. 从零开始学习linux的I2C设备驱动框架——写一个简单的SHT20驱动

    目录 0.测试环境说明 1.设备树的修改 2.设备驱动框架 3.I2C数据传输过程 3.1 struct i2c_msg 3.2 SHT20的数据收发 4.I2C适配器超时等待时间的修改 本文资源 参 ...

  6. char添加一个字符_LINUX字符设备驱动模型分析(起始篇)

    在前面几个模块的介绍中,我们主要以vfs为起始,完成了sysfs.设备-总线-驱动模型.platform设备驱动模型.i2c设备驱动模型.spi设备驱动模型的分析.在对这些模块进行分析的时候,我们或多 ...

  7. linux mdev 命令,linux设备驱动----利用mdev(udev)自动创建设备文件节点

    1.mdev的使用方法和原理: mdev是busybox 自带的一个简化版的udev,适合于嵌入式的应用埸合.其具有使用简单的特点.它的作用,就是在系统启动和热插拔或动态加载驱动程序时,自动产生驱动程 ...

  8. linux2.6驱动学习笔记之字符驱动

    1.字符驱动组成 1.1字符驱动的模块加载与卸载 //设备结构体模板 struct xxx_dev_t { struct cdev cdev; ...... }xxx_dev; 在字符驱动模块加载函数 ...

  9. (六)Linux之设备驱动模型(续)

    前面我们学习了杂项设备驱动模型.早期经典字符设备驱动模型,这一小节来讲解Linux中的标准字符设备驱动. 目录 (一)为什么引入标准字符设备驱动模型 (二)相关接口 (三)注册流程 (四)程序示例 ( ...

  10. linux major头文件_《Linux设备驱动程序》(四)——字符设备驱动(上)

    之前我们说过,Linux设备主要分为三类:字符设备.块设备和网络接口. 字符设备相对于另外两个设备更加容易理解,同时,这类设备也适合大多数简单的硬件设备,因此,接下来我们学习一下字符设备驱动. 字符驱 ...

最新文章

  1. phpstrom+xdebug调试PHP代码
  2. [pymongo] pymongo.errors.CursorNotFound Exception
  3. iPhoneUI元素的大小
  4. linux故障排除与修复(troubleshooting)
  5. SDNU 1469.校门外的树(水题)
  6. 一步步编写操作系统 25 cpu的保护模式
  7. 10.傅里叶变换——傅里叶变换、计算傅里叶变换_3
  8. android room 线程,Android协程——RoomCoroutines-Go语言中文社区
  9. 怎么增加一个工位?ApiPost工位有什么用?
  10. S5PV210 Uboot开发与移植02:Uboot配置与编译
  11. 有时候,一个人也挺好
  12. HTML思维导图+学习笔记+实际案例
  13. 阿里云一个账号给多个主体备案
  14. 计算机基础课教学心得,浅谈高专院校计算机基础课程的教学心得体会养
  15. 毒论--不要再面向对象(续)
  16. 使用PDF编辑器为PDF文档添加页码教程
  17. PowerBI - 10.功能丰富的报表展示工具
  18. Windows .bat 脚本简单用法介绍
  19. jquery.SuperSlide
  20. 十进制数转换为二进制,八进制,十六进制数的算法(欢迎拍砖)

热门文章

  1. 淘宝店铺装修如何实现全屏轮播
  2. sir模型matlab案例_直播案例 | 人群接触网络中的 SIR 疫情模拟
  3. oracle中打钩,wps文档如何在小方块里打钩?
  4. Windows 系统:没有远程桌面授权服务器可以提供许可证
  5. 视频教程-产品原型图设计Axure教程-Axure
  6. RADIUS服务器的演变过程
  7. fluent瞬态_瞬态环境
  8. 淘淘商城第107讲——添加购物车
  9. canvas 加载图片
  10. c语言知识点总结大全(史上最全)