关于SR04模块驱动 关中断的方式,数据不准确的问题

image
上面是运行结果,什么原因使得他数据不准确的情况下,而且还夹杂着错误输出,谢谢大家!

static ssize_t sr04_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offset){
int ret = 0;
int clock = 0;
int time_out = 1000000;
unsigned long flags;

local_irq_save(flags);

/*发送高电平*/
gpio_set_value(sr04dev.trig_gpio,1);
udelay(15);
gpio_set_value(sr04dev.trig_gpio,0);
while(!gpio_get_value(sr04dev.echo_gpio)&&time_out){
    udelay(1);
    time_out--;
}//等待高电平;
if(!time_out){
    local_irq_restore(flags);
    ret = -EAGAIN;
    goto fail_time_out;
}
time_out = 1000000;
while(gpio_get_value(sr04dev.echo_gpio)&&time_out){
    udelay(1);
    clock++;
    time_out--;
}
if(!time_out){
    local_irq_restore(flags);
    ret = -EAGAIN;
    goto fail_time_out;
}
local_irq_restore(flags);
/*计算数值*/
ret = copy_to_user(buf,&clock,sizeof(clock));
if(ret < 0) {
    ret = -EINVAL;
    goto fail_time_out;
}
return 0;

fail_time_out:
return ret;
}
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;
}

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_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;
}这个是主要的驱动函数

这个是应用函数
while(1){
ret = read(fd,&value,sizeof(value));
if(ret >= 0)
printf(“The distance index : %d mm\r\n”,value*340/2/1000);//mm为单位
else
printf(“error=%d value = %d\r\n”,ret,value);
}

下面是设备树
pinctrl_sr04:sr04grp{
fsl,pins = <
MX6UL_PAD_GPIO1_IO01__GPIO1_IO01 0x10b0
MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0xf080

;
};
sr04{
compatible = “HC-SR04”;
pinctrl-names = “default”;
pinctrl-0 = <&pinctrl_sr04>;
trig-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
echo-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
interrupt-parent = <&gpio1>;
interrupts = <2 IRQ_TYPE_EDGE_BOTH>;
status = “okay”;
};

gpio_set_value(sr04dev.trig_gpio,1);
udelay(15);
gpio_set_value(sr04dev.trig_gpio,0);
while((!gpio_get_value(sr04dev.echo_gpio))&&time_out){
udelay(1);
time_out–;
}//等待高电平;
printk(“time_out = %d\r\n”,time_out);
if(!time_out){
local_irq_restore(flags);
ret = -EAGAIN;
goto fail_time_out;
}
我发现他是每间隔一次,倒计时就会为0;导致一个错误输出,不知道为什么
而且数据不正确,这个暂时没有找到;