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

相关文章

一文深入详解Python的secrets模块

《一文深入详解Python的secrets模块》在构建涉及用户身份认证、权限管理、加密通信等系统时,开发者最不能忽视的一个问题就是“安全性”,Python在3.6版本中引入了专门面向安全用途的secr... 目录引言一、背景与动机:为什么需要 secrets 模块?二、secrets 模块的核心功能1. 基

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

使用Python开发一个现代化屏幕取色器

《使用Python开发一个现代化屏幕取色器》在UI设计、网页开发等场景中,颜色拾取是高频需求,:本文主要介绍如何使用Python开发一个现代化屏幕取色器,有需要的小伙伴可以参考一下... 目录一、项目概述二、核心功能解析2.1 实时颜色追踪2.2 智能颜色显示三、效果展示四、实现步骤详解4.1 环境配置4.

Maven 配置中的 <mirror>绕过 HTTP 阻断机制的方法

《Maven配置中的<mirror>绕过HTTP阻断机制的方法》:本文主要介绍Maven配置中的<mirror>绕过HTTP阻断机制的方法,本文给大家分享问题原因及解决方案,感兴趣的朋友一... 目录一、问题场景:升级 Maven 后构建失败二、解决方案:通过 <mirror> 配置覆盖默认行为1. 配置示

MyBatis Plus 中 update_time 字段自动填充失效的原因分析及解决方案(最新整理)

《MyBatisPlus中update_time字段自动填充失效的原因分析及解决方案(最新整理)》在使用MyBatisPlus时,通常我们会在数据库表中设置create_time和update... 目录前言一、问题现象二、原因分析三、总结:常见原因与解决方法对照表四、推荐写法前言在使用 MyBATis

Mybatis Plus Join使用方法示例详解

《MybatisPlusJoin使用方法示例详解》:本文主要介绍MybatisPlusJoin使用方法示例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录1、pom文件2、yaml配置文件3、分页插件4、示例代码:5、测试代码6、和PageHelper结合6

Redis过期删除机制与内存淘汰策略的解析指南

《Redis过期删除机制与内存淘汰策略的解析指南》在使用Redis构建缓存系统时,很多开发者只设置了EXPIRE但却忽略了背后Redis的过期删除机制与内存淘汰策略,下面小编就来和大家详细介绍一下... 目录1、简述2、Redis http://www.chinasem.cn的过期删除策略(Key Expir

Python使用smtplib库开发一个邮件自动发送工具

《Python使用smtplib库开发一个邮件自动发送工具》在现代软件开发中,自动化邮件发送是一个非常实用的功能,无论是系统通知、营销邮件、还是日常工作报告,Python的smtplib库都能帮助我们... 目录代码实现与知识点解析1. 导入必要的库2. 配置邮件服务器参数3. 创建邮件发送类4. 实现邮件

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中