关于sr04Linux驱动,一旦距离超过1m就会出现负数以及错误数据(与老师代码一致),恳请大家帮帮忙

就是采用老师编写的代码,但是打印出的距离超过1m就错误


而且还会发生离谱的计算错误,下图中val1和val2分别是中断前后的两个值,但是居然
val1 = -1912706231 val2 = -1842502231
The distance index : -950 m
这个做差怎么会是负数呢?

#define SR04_CNT 1
#define SR04_NAME “HC-SR04”

struct sr04_dev{
dev_t devid;
int major;
int minor;
int irqnum;
struct cdev cdev;
struct class *class;
struct device *device;
struct device_node *nd;
int trig_gpio;/trig-GPIO的编号/
int echo_gpio;
wait_queue_head_t r_wait;
int queue_value;

};

static struct sr04_dev sr04dev;

static int sr04_open(struct inode *inode, struct file *filp){
int ret = 0;
printk(“opening…\r\n”);
return ret;
}

static ssize_t sr04_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offset){
int ret = 0;
/发送高电平/
gpio_set_value(sr04dev.trig_gpio,1);
udelay(15);
gpio_set_value(sr04dev.trig_gpio,0);
/等待数据/
ret = wait_event_interruptible(sr04dev.r_wait, sr04dev.queue_value);
if (ret) {
goto wait_error;
}
ret = copy_to_user(buf,&sr04dev.queue_value,sizeof(sr04dev.queue_value));
sr04dev.queue_value = 0;
return 0;
wait_error:
return ret;
}

static unsigned int sr04_poll(struct file *filp, struct poll_table_struct *poll_table){
int ret = 0;
return ret;
}

static const struct file_operations sr04_fops = {
.owner = THIS_MODULE,
.read = sr04_read,
.open = sr04_open,
.poll = sr04_poll,
};

/中断函数/
static irqreturn_t sr04_irq(int irq,void *dev_d){

struct sr04_dev *dev = (struct sr04_dev*)dev_d;
int val = gpio_get_value(dev->echo_gpio);
if (val)
{
    dev->queue_value = ktime_get_ns();
}else{

    dev->queue_value = ktime_get_ns() - dev->queue_value;
    wake_up(&dev->r_wait);  
}

return IRQ_HANDLED;

}

static int sr04_probe(struct platform_device *prev){
int ret = 0;
/设备号/
if(sr04dev.major){
sr04dev.devid = MKDEV(sr04dev.major,0);
ret = register_chrdev_region(sr04dev.devid,SR04_CNT,SR04_NAME);
}
else{
ret = alloc_chrdev_region(&sr04dev.devid,0,SR04_CNT,SR04_NAME);
sr04dev.major = MAJOR(sr04dev.devid);
sr04dev.minor = MINOR(sr04dev.devid);
}
if (ret < 0 )
{
goto fail_devid;
}
printk(“sr04 major=%d,minor=%d\r\n”,sr04dev.major, sr04dev.minor);

/*注册设备cdev*/
sr04dev.cdev.owner = THIS_MODULE;
cdev_init(&sr04dev.cdev,&sr04_fops);
ret = cdev_add(&sr04dev.cdev,sr04dev.devid,SR04_CNT);
if (ret)
{
    goto fail_cdev;
}
/*create class*/
sr04dev.class = class_create(THIS_MODULE,SR04_NAME);
if (IS_ERR(sr04dev.class)){
    ret =  PTR_ERR(sr04dev.class); 
    goto fail_class;
} 

sr04dev.device = device_create(sr04dev.class,NULL,sr04dev.devid,NULL,SR04_NAME);
if(IS_ERR(sr04dev.device)) {
    ret = PTR_ERR(sr04dev.device);
    goto fail_device;
}

sr04dev.nd = of_find_node_by_path("/sr04");
if(sr04dev.nd == NULL){
    printk("sr04 node don't find!\r\n");
    ret = -EINVAL;
    goto fail_nd;
}
sr04dev.trig_gpio = of_get_named_gpio(sr04dev.nd,"trig-gpios",0);
sr04dev.echo_gpio = of_get_named_gpio(sr04dev.nd,"echo-gpios",0);
if (sr04dev.trig_gpio < 0 || sr04dev.echo_gpio < 0)
{
    printk("can't get gpio\r\n");
    ret = -EINVAL;
    goto fail_gpio;
}   
printk("trig-gpio num = %d\r\n", sr04dev.trig_gpio);
printk("echo-gpio num = %d\r\n", sr04dev.echo_gpio); 

gpio_request(sr04dev.trig_gpio,"trig-gpio");
ret = gpio_direction_output(sr04dev.trig_gpio,0);
if (ret < 0) {
	printk("Fail gpio_direction_output gpio\r\n");
	goto fail_dir1;
}
gpio_request(sr04dev.echo_gpio,"echo-gpio"); 
ret = gpio_direction_input(sr04dev.echo_gpio);
if (ret < 0) {
	printk("Fail gpio_direction_input gpio\r\n");
	goto fail_dir2;
}
sr04dev.irqnum = gpio_to_irq(sr04dev.echo_gpio);
ret = request_irq(sr04dev.irqnum,sr04_irq,IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING,SR04_NAME,&sr04dev);
if (ret)
{
    printk("irq %d request failed!\r\n",sr04dev.irqnum);           
    goto fail_irq;
}          

/*注册初始化等待队列*/
init_waitqueue_head(&sr04dev.r_wait);


printk("init finished...........\r\n");
printk("trig-gpio output = %d  echo-gpio input = %d\r\n", gpio_get_value(sr04dev.trig_gpio),gpio_get_value(sr04dev.echo_gpio));
return 0;

fail_irq:
free_irq(sr04dev.irqnum,&sr04dev);
fail_dir2:
gpio_free(sr04dev.echo_gpio);
fail_dir1:
gpio_free(sr04dev.trig_gpio);
fail_gpio:
fail_nd:
device_destroy(sr04dev.class,sr04dev.devid);
fail_device:
class_destroy(sr04dev.class);
fail_class:
cdev_del(&sr04dev.cdev);
fail_cdev:
unregister_chrdev(sr04dev.devid,SR04_NAME);
fail_devid:
return ret;
}
static int sr04_remove(struct platform_device *dev){
free_irq(sr04dev.irqnum,&sr04dev);
gpio_free(sr04dev.trig_gpio);
gpio_free(sr04dev.echo_gpio);
device_destroy(sr04dev.class,sr04dev.devid);
class_destroy(sr04dev.class);
cdev_del(&sr04dev.cdev);
unregister_chrdev(sr04dev.devid,SR04_NAME);
return 0;
}

static const struct of_device_id sr04_of_match[] = {
{.compatible = “HC-SR04”},
{}
};

static const struct platform_device_id sr04_table_id[] = {
{.name = “HC-SR04”},
{},
};

static struct platform_driver sr04_driver = {
.driver = {
.owner = THIS_MODULE,
.name = “HC_SR04”,
.of_match_table = sr04_of_match,
},
.probe = sr04_probe,
.remove = sr04_remove,
.id_table = sr04_table_id,
};

static int __init sr04_init(void){
return platform_driver_register(&sr04_driver);
}

static void __exit sr04_exit(void){
platform_driver_unregister(&sr04_driver);
}

module_init(sr04_init);
module_exit(sr04_exit);

MODULE_LICENSE(“GPL”);
MODULE_AUTHOR(“zhangyuan”);

老师的代码就可以看,顺便问一个问题如果设备树中不设置中断,那么程序可以申请到中断号吗?我看见例程就没有,但是依然可以驱动,是不是因为这里借用了GPIO的中断,所以不需要自己设置了?