首页 > 技术知识 > 正文

【摘要】 当前采用的这种超声波测距模块在各大高校实验室、毕设、课设里用的很多,原理很简单,通过声波测距,发出的声音碰到障碍物会反弹,声音在空气里传播的速度是已知的,根据时间就能计算出测量的距离。这款超声波模块内部自带了时间计算电路,型号是HC-SR04 ,它可提供 2cm-400cm 的非接触式距离感测功能,距精度可达高到 3mm; 整个模块包括了超声波发射器、 接收器与控制电路。

1. 介绍

当前采用的这种超声波测距模块在各大高校实验室、毕设、课设里用的很多,原理很简单,通过声波测距,发出的声音碰到障碍物会反弹,声音在空气里传播的速度是已知的,根据时间就能计算出测量的距离。这款超声波模块内部自带了时间计算电路,型号是HC-SR04 ,它可提供 2cm-400cm 的非接触式距离感测功能,距精度可达高到 3mm; 整个模块包括了超声波发射器、 接收器与控制电路。

基本工作原理:

(1) 采用 IO 口 TRIG 触发测距, 给至少 10us 的高电平信号;

(2) 模块自动发送 8 个 40khz 的方波, 自动检测是否有信号返回;

(3) 有信号返回, 通过 IO 口 ECHO 输出一个高电平, 高电平持续的时间就是超声波从发射到返回的时间。

测量距离的公式:

复制uS/58=厘米或者 uS/148=英寸; 或是: 距离=高电平时间*声速(340M/S)/2; 建议测量周期为 60ms 以上, 以防止发射信号对回响信号的影响。

下面是超声波模块与开发板的连线方式:

2. 示例代码

下面是超声波测距模块的驱动代码,将超声波模块的输出脚接在开发板支持中断的IO口上,配置为上升沿触发,当超声波输出脚检测到高电平就进去中断服务函数,在中断服务函数里调度工作队列,最终在工作函数里完成高电平的时间长度获取,计算测量的距离,直接在驱动代码里打印出来。

下面是测量的结果:

Linux驱动开发-编写超声波测距模块的驱动-超声测距系统

2.1 驱动代码

复制#include #include #include #include #include #include #include static struct timer_list timer; static struct work_struct work; static int irq; #define TRIG EXYNOS4_GPB(7) //输出触发信号 第8个IO口 #define ECHO EXYNOS4_GPX1(0) //ECHO 回响信号输出–中断 第9个IO口 /*获取高电平持续时间–us单位*/ static u32 GetTimeH(void) { ktime_t my_time,my_time2; unsigned int i,j; my_time=ktime_get(); //获取当前时间 i=ktime_to_us(my_time); //转 us while(gpio_get_value(ECHO)){} my_time2=ktime_get(); //获取当前时间 j=ktime_to_us(my_time2); //转 us return j-i; } /* 工作函数 */ static void csb_work_func(struct work_struct *work) { u32 time=GetTimeH(); printk(“厘米:%d cm\n”,time/58); } /*外部中断服务函数*/ irqreturn_t csb_irq_handler_func(int irq, void *dev) { /*添加工作到工作队列*/ schedule_work(&work); return IRQ_HANDLED; } /*内核定时器中断服务函数*/ static void timer_function(unsigned long data) { static u8 i=0; mod_timer(&timer,msecs_to_jiffies(1000)+jiffies); i=!i; if(i) { gpio_set_value(TRIG,1); } else { gpio_set_value(TRIG,0); } } static int __init tiny4412_linux_csb_init(void) { /*请求GPIO口使用权*/ gpio_request(TRIG,”CSB”); /*配置GPIO引脚*/ s3c_gpio_cfgpin(TRIG,S3C_GPIO_OUTPUT); /*GPIO默认输出值*/ gpio_set_value(TRIG,0); /*初始化工作函数*/ INIT_WORK(&work,csb_work_func); /*1. 获取中断号*/ irq=gpio_to_irq(ECHO); /*2. 注册中断*/ request_irq(irq,csb_irq_handler_func,IRQF_TRIGGER_RISING,”tiny4412_csb”,NULL); timer.expires=HZ+jiffies; /*单位是节拍*/ timer.function=timer_function; timer.data=666; /*1. 初始化定时器*/ init_timer(&timer); /*2. 添加定时器到内核*/ add_timer(&timer); printk(“驱动测试: 驱动安装成功\n”); return 0; } static void __exit tiny4412_linux_csb_cleanup(void) { /*3. 删除定时器*/ del_timer_sync(&timer); free_irq(irq,NULL); printk(“驱动测试: 驱动卸载成功\n”); } module_init(tiny4412_linux_csb_init); /*驱动入口–安装驱动的时候执行*/ module_exit(tiny4412_linux_csb_cleanup); /*驱动出口–卸载驱动的时候执行*/ MODULE_LICENSE(“GPL”); /*设置模块的许可证–GPL*/

2.2 Makefile

复制KER_DRI=/home/wbyq/work/linux-3.5/linux-3.5 all: make -C $(KER_DRI) M=`pwd` modules cp *.ko /home/wbyq/work/rootfs/code -f make -C $(KER_DRI) M=`pwd` modules clean obj-m += linux_csb.o

猜你喜欢