前言:最近基于dragonboard410c上做一個demo,其中就要用到超聲波模塊來測距以達(dá)到當(dāng)人靠近超聲波一定距離的時候,驅(qū)動會上報(bào)single,激活應(yīng)用層。這個驅(qū)動寫的有點(diǎn)簡單,如果大家有什么見解可以提出。
一、硬件搭建
1.Dragonboard410c開發(fā)板:
低速接口中pin1,pin23,pin25,ping35對應(yīng)的GPIO接口,見《Low speed Expansion connector》分布圖
2.US-100電平觸發(fā)測距工作原理:
在模塊上電前,首先去掉模式選擇跳線上的跳線帽,使模塊處于電平觸發(fā)模式。
電平觸發(fā)測距的時序如圖:
只需要在 Trig/TX 管腳輸入一個 10US 以上的高電平,系統(tǒng)便可發(fā)出 8 個 40KHZ 的超聲波脈沖,然后檢測回
波信號。當(dāng)檢測到回波信號后,模塊還要進(jìn)行溫度值的測量,然后根據(jù)當(dāng)前溫度對測距結(jié)果進(jìn)行校正,將校正后的結(jié)果通過Echo/RX 管腳輸出。
在此模式下,模塊將距離值轉(zhuǎn)化為 340m/s 時的時間值的 2倍,通過 Echo 端輸出一高電平,可根據(jù)此高電平的持續(xù)時間來計(jì)算距離值。即距離值為:(高電平時間*340m/s)/2。
3.按照下表的方式將US-100與開發(fā)板電氣連接
二、軟件環(huán)境搭建
根據(jù)blog教程在裝有Ubuntu的主機(jī)上下載相應(yīng)源碼以及編譯工具。
注意:在dts中要修改apq8016-sbc.dtsi文件,增加超聲波驅(qū)動的節(jié)點(diǎn)信息:
sonar{
compatible = “thundersoft,sonar”;
thunder,poll_time =<50>;
thunder,gpio_cmd = <&msm_gpio 13 0>;
thunder,gpio_irq = <&msm_gpio 36 0>;
};
三、驅(qū)動編寫
1.//匹配設(shè)備樹定義接口
static int parse_dt(struct platform_device* pdev,struct us100_data* data){
int rc;
struct device_node* node = pdev->dev.of_node;
//將node 50 寫入到poll_time中
rc = of_property_read_u32(node,“thunder,poll_time”,&data->poll_time);
if(rc){
pr_warning(“%s you should point time”,__FUNCTION__);
data->poll_time = 20;
}
/* --TrigPin3---PIN25---- gpio13---- gpio_cmd ---cmd_gpio----------- */
data->cmd_gpio = of_get_named_gpio(node,“thunder,gpio_cmd”,0);
/* --EchoPin2---PIN23---- gpio36---- gpio_irp ---echo_gpio----------- */
data->echo_gpio = of_get_named_gpio(node,“thunder,gpio_irq”,0);
if(data->cmd_gpio<0 || data->echo_gpio<0){
pr_err(“%s,error gpio\n”,__FUNCTION__);
return -EINVAL;
}
return 0;
}
2.//啟動、關(guān)閉方波產(chǎn)生
static ssize_t hs100_store_enable(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t size){
struct us100_data* data = dev_get_drvdata(dev);
int enable = simple_strtoul(buf,NULL,10);
if(enable){
//調(diào)用cmd_work_func
schedule_delayed_work(&data->cmd_work,0);
data->enable =1;
}
else{
//取消調(diào)用cmd_work_func
cancel_delayed_work_sync(&data->cmd_work);
data->enable=0;
}
return size;
}
3.//實(shí)現(xiàn)12us的方波功能
static void cmd_work_func(struct work_struct* work){
struct us100_data* data = container_of(work,struct us100_data,cmd_work.work);
gpio_set_value(data->cmd_gpio,1);
延遲12us產(chǎn)生方波
udelay(12);
gpio_set_value(data->cmd_gpio,0);//genarate a 12 us pluse
// printk(“%s send cmd\n”,__FUNCTION__);
//激活工作隊(duì)列中的cmd_work_func
schedule_delayed_work(&data->cmd_work,msecs_to_jiffies(data->poll_time));
}
//實(shí)現(xiàn)獲得實(shí)際距離的功能
static void report_work_func(struct work_struct* work){
struct timespec now,last;
s64 diff_time;
/*---通過結(jié)構(gòu)體中成員的首地址獲結(jié)構(gòu)體變量首地址---*/
struct us100_data* data = container_of(work,struct us100_data,report_work);
//時間格式轉(zhuǎn)換
now = ktime_to_timespec(data->now_ktime);
last= ktime_to_timespec(data->last_ktime);
//時間差
diff_time = now.tv_sec*1000000000UL+now.tv_nsec-last.tv_sec*1000000000UL-last.tv_nsec;
// printk(“ns=%lld\n”,diff_time);
mutex_lock(&data->data_lock);
//實(shí)際距離
data->distance = diff_time*170*100*10/1000000000UL;
mutex_unlock(&data->data_lock);
data-> data_ready = true;
// 喚醒data_queue 指定的注冊在等待隊(duì)列上的進(jìn)程
wake_up_interruptible(&data->data_queue);
// printk(“dis=%d\n”,data->distance);
}
評論
查看更多