前言:最近基于dragonboard410c上做一個demo,其中就要用到超聲波模塊來測距以達到當人靠近超聲波一定距離的時候,驅動會上報single,激活應用層。這個驅動寫的有點簡單,如果大家有什么見解可以提出。
一、硬件搭建
1.Dragonboard410c開發板:
低速接口中pin1,pin23,pin25,ping35對應的GPIO接口,見《Low speed Expansion connector》分布圖
2.US-100電平觸發測距工作原理:
在模塊上電前,首先去掉模式選擇跳線上的跳線帽,使模塊處于電平觸發模式。
電平觸發測距的時序如圖:
只需要在 Trig/TX 管腳輸入一個 10US 以上的高電平,系統便可發出 8 個 40KHZ 的超聲波脈沖,然后檢測回
波信號。當檢測到回波信號后,模塊還要進行溫度值的測量,然后根據當前溫度對測距結果進行校正,將校正后的結果通過Echo/RX 管腳輸出。
在此模式下,模塊將距離值轉化為 340m/s 時的時間值的 2倍,通過 Echo 端輸出一高電平,可根據此高電平的持續時間來計算距離值。即距離值為:(高電平時間*340m/s)/2。
3.按照下表的方式將US-100與開發板電氣連接
二、軟件環境搭建
根據blog教程在裝有Ubuntu的主機上下載相應源碼以及編譯工具。
注意:在dts中要修改apq8016-sbc.dtsi文件,增加超聲波驅動的節點信息:
sonar{
compatible = “thundersoft,sonar”;
thunder,poll_time =<50>;
thunder,gpio_cmd = <&msm_gpio 13 0>;
thunder,gpio_irq = <&msm_gpio 36 0>;
};
三、驅動編寫
1.//匹配設備樹定義接口
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.//啟動、關閉方波產生
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){
//調用cmd_work_func
schedule_delayed_work(&data->cmd_work,0);
data->enable =1;
}
else{
//取消調用cmd_work_func
cancel_delayed_work_sync(&data->cmd_work);
data->enable=0;
}
return size;
}
3.//實現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產生方波
udelay(12);
gpio_set_value(data->cmd_gpio,0);//genarate a 12 us pluse
// printk(“%s send cmd\n”,__FUNCTION__);
//激活工作隊列中的cmd_work_func
schedule_delayed_work(&data->cmd_work,msecs_to_jiffies(data->poll_time));
}
//實現獲得實際距離的功能
static void report_work_func(struct work_struct* work){
struct timespec now,last;
s64 diff_time;
/*---通過結構體中成員的首地址獲結構體變量首地址---*/
struct us100_data* data = container_of(work,struct us100_data,report_work);
//時間格式轉換
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);
//實際距離
data->distance = diff_time*170*100*10/1000000000UL;
mutex_unlock(&data->data_lock);
data-> data_ready = true;
// 喚醒data_queue 指定的注冊在等待隊列上的進程
wake_up_interruptible(&data->data_queue);
// printk(“dis=%d\n”,data->distance);
}
評論
查看更多