硬件驱动之hcsr04超声波测距传感器

一 操作流程

 二 传感器指标与信息

     基本信息

  1.     工作电压:通常为5V3。
  2.      工作电流:静态工作电流小于5mA,最大工作电流约为15mA2。
  3. 测量范围:2cm至400cm,某些版本可能支持更远的测量距离3。
  4. 测量精度:可达3mm3。
  5. 工作频率:40kHz2。
  6. 工作温度:通常为-10℃至70℃1。

    阴脚定义

  1. VCC:电源正极,通常接5V。
  2. Trig:触发信号输入,用于启动测距。
  3. Echo:回响信号输出,用于接收测距结果3。
  4. GND:电源负极,接地。

代码实现

   配置GPIO口

 超声波测距的实现

      测速时序图     

 代码实现函数

实现总架构 

        内核层:device.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/irqreturn.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>

static void  hcsr04_release(struct device *dev);

static struct resource res[] = {
    [0] = {
       .start = 0x56000050,
       .end = 0x56000050 + 8 - 1,
       .name = "GPF",
       .flags = IORESOURCE_MEM,
    },
};

static struct platform_device hcsr04_device = {
    .name = "hcsr04",
    .id = -1,
    .dev.release = hcsr04_release,
    .resource = res,
    .num_resources = sizeof(res) / sizeof(res[0]),
};

static void  hcsr04_release(struct device *dev)
{

    return;
}

static int __init init_hcsr04_device(void)
{
    int ret = 0;
    
    ret = platform_device_register(&hcsr04_device);
    if (ret != 0)
    {
        return -1;
    } 

    printk("platform hcsr04 device register success!\n");

    return 0;
}

static void __exit exit_hcsr04_device(void)
{
    platform_device_unregister(&hcsr04_device);

    printk("platform hcsr04 device unregister success!\n");

    return;
}

module_init(init_hcsr04_device);
module_exit(exit_hcsr04_device);
MODULE_LICENSE("GPL");

内核层:drive.c 

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <linux/irqreturn.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/delay.h>

static volatile unsigned int *pGPFBase = NULL;
static int hcsr04_probe(struct platform_device *device);
static int hcsr04_open(struct inode *node, struct file *fp);
static ssize_t hcsr04_read(struct file *fp, char __user *puser, size_t n, loff_t *off);
static int hcsr04_release(struct inode *node, struct file *fp);

#define SET_TRIG_OUT         (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3)) | (0x1)))
#define SET_TRIG_IN          (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3))))
#define SET_TRIG_HIGH        (*(pGPFBase+1) = ((*(pGPFBase+1)) | (0x1)))
#define SET_TRIG_LOW         (*(pGPFBase+1) = ((*(pGPFBase+1)) & ~(0x1)))
#define GET_TRIG_STAT        (*(pGPFBase+1) & (0x1))    

#define SET_ECHO_OUT         (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3 << 2)) | (0x1 << 2)))
#define SET_ECHO_IN          (*(pGPFBase+0) = ((*(pGPFBase+0) & ~(0x3 << 2))))
#define SET_ECHO_HIGH        (*(pGPFBase+1) = ((*(pGPFBase+1)) | (0x1 << 1)))
#define SET_ECHO_LOW         (*(pGPFBase+1) = ((*(pGPFBase+1)) & ~(0x1 << 1)))
#define GET_ECHO_STAT        (*(pGPFBase+1) & (0x1 << 1))  

static struct platform_driver hcsr04_driver = {
    .probe = hcsr04_probe,
    .driver.name = "hcsr04",
};

static struct file_operations fops = {
    .owner = THIS_MODULE,
    .open = hcsr04_open,
    .read = hcsr04_read,
    .release = hcsr04_release,
};

static struct miscdevice misc_hcsr04 = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = "hcsr04",
    .fops = &fops,
};  

static int hcsr04_open(struct inode *node, struct file *fp)
{
    SET_TRIG_OUT;
    SET_TRIG_LOW;

    SET_ECHO_OUT;
    SET_ECHO_LOW;

    return 0;
}   

static int hcsr04_release(struct inode *node, struct file *fp)
{
    SET_TRIG_OUT;
    SET_TRIG_LOW;

    SET_ECHO_OUT;
    SET_ECHO_LOW;

    return 0;
}

static ssize_t hcsr04_read(struct file *fp, char __user *puser, size_t n, loff_t *off)
{
    unsigned int consttime = 0;

    //发送声波
    SET_TRIG_HIGH;
    udelay(10);
    SET_TRIG_LOW;

    SET_ECHO_IN;
    while (!GET_ECHO_STAT);

    while (GET_ECHO_STAT)
    {
        consttime++;
        udelay(1);
    }

    SET_ECHO_OUT;
    SET_ECHO_LOW;

    copy_to_user(puser, &consttime, sizeof(consttime));

    return sizeof(consttime);
}

static int hcsr04_probe(struct platform_device *device)
{
    int ret = 0;
    
    ret = misc_register(&misc_hcsr04);
    if (ret != 0)
    {
        return -1;
    }

    pGPFBase = ioremap(device->resource[0].start, device->resource[0].end - device->resource[0].start);
    if (NULL == pGPFBase)
    {
        return -1;
    }

    return 0;
}

static int __init init_hcsr04_driver(void)
{
    int ret = 0;

    ret = platform_driver_register(&hcsr04_driver);
    if (ret != 0)
    {
        return -1;
    }

    printk("platform hcsr04 driver init success!\n");

    return 0;
}

static void __exit exit_hcsr04_driver(void)
{
    platform_driver_unregister(&hcsr04_driver);

    printk("platform hcsr04 driver exit success!\n");

    return;
}

module_init(init_hcsr04_driver);
module_exit(exit_hcsr04_driver);
MODULE_LICENSE("GPL");

应用层代码实现: 

#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdlib.h>

int main(void)
{
    int fd = 0;
    unsigned int costtime = 0;
    ssize_t nret = 0;

    fd = open("/dev/hcsr04", O_RDWR);
    if (-1 == fd)
    {
        perror("fail to open");
        return -1;
    }

    while (1)
    {
        nret = read(fd, &costtime, sizeof(costtime));
        printf("%.2lf cm\n", (0.034 * costtime) / 2);
        sleep(1);
    }

    close(fd);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值