sr04模块总结
设备树添加
/*sr04 gpio4 21 gpio4 22*/
/{sr04 {compatible = "imx6ull,sr04";pinctrl-names = "default";pinctrl-0 = <&pinctrl_sr04>;// TRIG 引脚和 ECHO 引脚trig-gpios = <&gpio4 21 GPIO_ACTIVE_HIGH>; // TRIG 引脚配置echo-gpios = <&gpio4 22 GPIO_ACTIVE_HIGH>; // ECHO 引脚配置status = "okay";};
}
驱动代码
sr04工作原理:
驱动代码实现:
/** 中断处理函数:当echo信号变化时触发* 负责记录回声信号的开始和结束时间,并通过等待队列通知主程序* 上升沿开始,下降沿结束*/
static irqreturn_t sr04_isr(int irq, void *dev_id)
{int val = gpiod_get_value(sr04_echo); // 获取echo信号的电平u64 now = ktime_get_ns(); // 获取当前时间戳if (val) { // 回声信号的上升沿,表示回声开始echo_start_time = now;} else { // 回声信号的下降沿,表示回声结束echo_time = now - echo_start_time; // 计算回声时间echo_done = true; // 设置回声完成标志wake_up_interruptible(&sr04_wait); // 唤醒等待队列}return IRQ_HANDLED; // 标记中断已处理
}/*
*读取传感器接收的信号,引用程序
*/
static ssize_t sr04_read(struct file *file, char __user *buf, size_t size, loff_t *off)
{int ret;// 发出触发脉冲:先设置trig为高电平,然后立即设置为低电平,产生超声波信号gpiod_set_value(sr04_trig, 1);udelay(12); // 延时12微秒gpiod_set_value(sr04_trig, 0); echo_done = false; // 重置回声完成标志// 等待回声完成(1秒超时)ret = wait_event_interruptible_timeout(sr04_wait, echo_done, HZ);if (ret == 0) // 如果超时,返回-ETIMEDOUTreturn -ETIMEDOUT;// 将回声时间(纳秒)传输到用户空间if (copy_to_user(buf, &echo_time, sizeof(u64)))return -EFAULT;return sizeof(u64); // 返回复制的字节数
}
应用程序代码
使用read读取echo引脚的高电平时间,然后将电平时间转换为距离
#include "sr04.h"
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <QDebug>
#include <QThread>distance::distance()
{stop = 0;distanceData = 0;
}distance::~distance()
{
}void distance::run()
{// 打开设备节点int fd = open("/dev/sr04", O_RDONLY);if (fd < 0) {qDebug() << "sr04 open failed! errno=" << errno;return;}while (!stop) {u64 echo_time = 0;// 调用 read() 读取 echo_time(单位:纳秒)ssize_t ret = read(fd, &echo_time, sizeof(echo_time));if (ret < 0) {qDebug() << "sr04 read failed! errno=" << errno;} else if (ret == sizeof(echo_time)) {// 将时间转为距离,单位:cm// 声速 = 343m/s = 34300 cm/s// 距离 = (时间 / 1e9) * 34300 / 2distanceData = (echo_time / 1e9) * 34300 / 2;qDebug() << "Distance:" << distanceData << "cm";} else {qDebug() << "sr04 read size error!";}QThread::msleep(1000); // 1秒读取一次}close(fd);
}void distance::distanceStop()
{stop = 1;
}
QT程序
距离检测线程启动
// 启动距离感应线程myDistance = new distance(); // 创建距离感应线程对象myDistance->start(); // 启动线程ui->lineEdit_3->setText("距离:0cm"); // 设置距离为0
``