014——超声波模块驱动开发Plus(基于I.MX6uLL、SR04和poll机制)

2024-04-04 16:36

本文主要是介绍014——超声波模块驱动开发Plus(基于I.MX6uLL、SR04和poll机制),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、基础知识

二、分析为什么打印会影响中断 

三、驱动程序

四、应用程序

五、验证及其它


一、基础知识

013——超声波模块驱动开发(基于I.MX6uLL与SR04)-CSDN博客

二、分析为什么打印会影响中断 

 

asmlinkage __visible int printk(const char *fmt, ...)  
{  va_list args;  int r;  // 初始化可变参数列表  va_start(args, fmt);  // 调用 vprintk_func 函数来格式化字符串并输出到内核日志  r = vprintk_func(fmt, args);  // 清理可变参数列表  va_end(args);  // 返回 vprintk_func 的结果  return r;  
}  EXPORT_SYMBOL(printk);

我们一层一层往下找找到了这个

        这是一个保护中断的自旋锁,这里上锁后其它需要用中断的进程就无法使用了。

        所以当超声波模块中断触发后我们没有接收到。这就是为什么打印会影响中断的原因,这里相当于32库函数里面关闭全局中断的那个操作,实现虽然不一样但是作用是一样的。

三、驱动程序

#include "asm-generic/errno.h"
#include "asm-generic/gpio.h"
#include "asm/delay.h"
#include "linux/jiffies.h"
#include <linux/module.h>
#include <linux/poll.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>#define CMD_TRIG  100struct gpio_desc{int gpio;int irq;char *name;int key;struct timer_list key_timer;
} ;static struct gpio_desc gpios[2] = {{115, 0, "trig", },{116, 0, "echo", },
};/* 主设备号                                                                 */
static int major = 0;
static struct class *gpio_class;/* 环形缓冲区 */
#define BUF_LEN 128
static int g_keys[BUF_LEN];
static int r, w;struct fasync_struct *button_fasync;#define NEXT_POS(x) ((x+1) % BUF_LEN)static int is_key_buf_empty(void)
{return (r == w);
}static int is_key_buf_full(void)
{return (r == NEXT_POS(w));
}static void put_key(int key)
{if (!is_key_buf_full()){g_keys[w] = key;w = NEXT_POS(w);}
}static int get_key(void)
{int key = 0;if (!is_key_buf_empty()){key = g_keys[r];r = NEXT_POS(r);}return key;
}static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);/* 实现对应的open/read/write等函数,填入file_operations结构体                   */
static ssize_t sr04_read (struct file *file, char __user *buf, size_t size, loff_t *offset)
{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);int err;int key;if (is_key_buf_empty() && (file->f_flags & O_NONBLOCK))return -EAGAIN;// printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);wait_event_interruptible(gpio_wait, !is_key_buf_empty());key = get_key();if (key == -1)return -ENODATA;err = copy_to_user(buf, &key, 4);return 4;
}static unsigned int sr04_poll(struct file *fp, poll_table * wait)
{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);poll_wait(fp, &gpio_wait, wait);return is_key_buf_empty() ? 0 : POLLIN | POLLRDNORM;
}static int sr04_fasync(int fd, struct file *file, int on)
{if (fasync_helper(fd, file, on, &button_fasync) >= 0)return 0;elsereturn -EIO;
}// ioctl(fd, CMD, ARG)
static long sr04_ioctl(struct file *filp, unsigned int command, unsigned long arg)
{// send trig switch (command){case CMD_TRIG:{//printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);gpio_set_value(gpios[0].gpio, 1);udelay(20);gpio_set_value(gpios[0].gpio, 0);// start timermod_timer(&gpios[1].key_timer, jiffies + msecs_to_jiffies(50));  }}return 0;
}/* 定义自己的file_operations结构体                                              */
static struct file_operations sr04_drv = {.owner	 = THIS_MODULE,.read    = sr04_read,.poll    = sr04_poll,.fasync  = sr04_fasync,.unlocked_ioctl = sr04_ioctl,
};static irqreturn_t sr04_isr(int irq, void *dev_id)
{struct gpio_desc *gpio_desc = dev_id;int val;static u64 rising_time = 0;u64 time;val = gpio_get_value(gpio_desc->gpio);//printk("sr04_isr echo pin %d is %d\n", gpio_desc->gpio, val);if (val){/* 上升沿记录起始时间 */rising_time = ktime_get_ns();}else{if (rising_time == 0){//printk("missing rising interrupt\n");return IRQ_HANDLED;}/* 下降沿记录结束时间, 并计算时间差, 计算距离 */// stop timerdel_timer(&gpios[1].key_timer);time = ktime_get_ns() - rising_time;rising_time = 0;put_key(time);wake_up_interruptible(&gpio_wait);kill_fasync(&button_fasync, SIGIO, POLL_IN);}return IRQ_HANDLED;
}static void sr04_timer_func(unsigned long data)
{put_key(-1);wake_up_interruptible(&gpio_wait);kill_fasync(&button_fasync, SIGIO, POLL_IN);
}/* 在入口函数 */
static int __init sr04_init(void)
{int err;printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);// trig pinerr = gpio_request(gpios[0].gpio, gpios[0].name);gpio_direction_output(gpios[0].gpio, 0);// echo pin{		gpios[1].irq  = gpio_to_irq(gpios[1].gpio);err = request_irq(gpios[1].irq, sr04_isr, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, gpios[1].name, &gpios[1]);setup_timer(&gpios[1].key_timer, sr04_timer_func, (unsigned long)&gpios[1]);}/* 注册file_operations 	*/major = register_chrdev(0, "100ask_sr04", &sr04_drv);  /* /dev/gpio_desc */gpio_class = class_create(THIS_MODULE, "100ask_sr04_class");if (IS_ERR(gpio_class)) {printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);unregister_chrdev(major, "100ask_sr04");return PTR_ERR(gpio_class);}device_create(gpio_class, NULL, MKDEV(major, 0), NULL, "sr04"); /* /dev/sr04 */return err;
}/* 有入口函数就应该有出口函数:卸载驱动程序时,就会去调用这个出口函数*/
static void __exit sr04_exit(void)
{printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);device_destroy(gpio_class, MKDEV(major, 0));class_destroy(gpio_class);unregister_chrdev(major, "100ask_sr04");// trig pingpio_free(gpios[0].gpio);// echo pin{free_irq(gpios[1].irq, &gpios[1]);del_timer(&gpios[1].key_timer);}
}/* 7. 其他完善:提供设备信息,自动创建设备节点                                     */module_init(sr04_init);
module_exit(sr04_exit);MODULE_LICENSE("GPL");

四、应用程序

加入poll机制查询是不是有数据


#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <poll.h>
#include <signal.h>
#include <sys/ioctl.h>#define CMD_TRIG  100static int fd;/** ./button_test /dev/sr04**/
int main(int argc, char **argv)
{int val;struct pollfd fds[1];int timeout_ms = 5000;int ret;int	flags;int i;/* 1. 判断参数 */if (argc != 2) {printf("Usage: %s <dev>\n", argv[0]);return -1;}/* 2. 打开文件 */fd = open(argv[1], O_RDWR);if (fd == -1){printf("can not open file %s\n", argv[1]);return -1;}while (1){ioctl(fd, CMD_TRIG);printf("I am goning to read distance: \n");fds[0].fd = fd;fds[0].events = POLLIN;if (1 == poll(fds, 1, 5000)){if (read(fd, &val, 4) == 4)printf("get distance: %d cm\n", val*17/1000000);elseprintf("get distance err\n");}else{printf("get distance poll timeout/err\n");}sleep(1);}close(fd);return 0;
}

五、验证及其它

我们现在用的4.9.88版本用setup_timer

新的5.几的内核使用timer_setup

key_timer_expire函数的参数也不一样,4点几是long,5点几是把结构体传入。

现象和上次一样

013——超声波模块驱动开发(基于I.MX6uLL与SR04)-CSDN博客

 

这个数据后面需要处理一下不然太不稳定了。

这篇关于014——超声波模块驱动开发Plus(基于I.MX6uLL、SR04和poll机制)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/876292

相关文章

java中反射(Reflection)机制举例详解

《java中反射(Reflection)机制举例详解》Java中的反射机制是指Java程序在运行期间可以获取到一个对象的全部信息,:本文主要介绍java中反射(Reflection)机制的相关资料... 目录一、什么是反射?二、反射的用途三、获取Class对象四、Class类型的对象使用场景1五、Class

Spring Boot结成MyBatis-Plus最全配置指南

《SpringBoot结成MyBatis-Plus最全配置指南》本文主要介绍了SpringBoot结成MyBatis-Plus最全配置指南,包括依赖引入、配置数据源、Mapper扫描、基本CRUD操... 目录前言详细操作一.创建项目并引入相关依赖二.配置数据源信息三.编写相关代码查zsRArly询数据库数

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

Python使用date模块进行日期处理的终极指南

《Python使用date模块进行日期处理的终极指南》在处理与时间相关的数据时,Python的date模块是开发者最趁手的工具之一,本文将用通俗的语言,结合真实案例,带您掌握date模块的六大核心功能... 目录引言一、date模块的核心功能1.1 日期表示1.2 日期计算1.3 日期比较二、六大常用方法详

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件

基于Python开发批量提取Excel图片的小工具

《基于Python开发批量提取Excel图片的小工具》这篇文章主要为大家详细介绍了如何使用Python中的openpyxl库开发一个小工具,可以实现批量提取Excel图片,有需要的小伙伴可以参考一下... 目前有一个需求,就是批量读取当前目录下所有文件夹里的Excel文件,去获取出Excel文件中的图片,并

python中time模块的常用方法及应用详解

《python中time模块的常用方法及应用详解》在Python开发中,时间处理是绕不开的刚需场景,从性能计时到定时任务,从日志记录到数据同步,时间模块始终是开发者最得力的工具之一,本文将通过真实案例... 目录一、时间基石:time.time()典型场景:程序性能分析进阶技巧:结合上下文管理器实现自动计时

mybatis-plus分页无效问题解决

《mybatis-plus分页无效问题解决》本文主要介绍了mybatis-plus分页无效问题解决,原因是配置分页插件的版本问题,旧版本和新版本的MyBatis-Plus需要不同的分页配置,感兴趣的可... 昨天在做一www.chinasem.cn个新项目使用myBATis-plus分页一直失败,后来经过多方

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析

《MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析》本文将详细讲解MyBatis-Plus中的lambdaUpdate用法,并提供丰富的案例来帮助读者更好地理解和应... 目录深入探索MyBATis-Plus中Service接口的lambdaUpdate用法及示例案例背景