前言
本次驅動用的是這款超聲波,超聲波的驅動大同小異,均可參考
一、引腳定義
引腳 | 功能 |
---|---|
VCC | 接直流5V電 |
TRIG | 接外部電路的TRIG端,向此引腳輸入10us以上的高電平可觸發超聲波測距 |
ECHO | 接外部電路的ECHO端,測距結束時該引腳會輸出一個高電平,電平寬度為超聲波往返時間之和 |
GND | 接地 |
二、工作原理
1、采用 IO 觸發測距,給至少 10us 的高電平信號;
2、模塊自動發送 8 個 40khz 的方波,自動檢測是否有信號返回;
3、有信號返回,通過 IO 輸出一高電平,高電平持續的時間就是超聲波從發射到返回的時間
4、測試距離=(高電平時間*聲速(340M/S))/2;
三、引腳時序圖
建議測量周期在60ms以上,防止發射信號對回響信號的有影響
四、創建RTT工程(開始動手)
五、打開CubeMX
六、配置串行調試口
七、配置使用外部高速晶振
八、創建工程時默認使用了串口一,這里也打開串口一
九、開啟定時器三,定時器三是用來給超聲波回波信號計時的,計算高電平時間從而得到測量距離
十、配置時鐘線
十一、生成代碼
十二、打開定時器設備驅動程序
十三、使能定時器模塊
十四、打開定時器三的注釋(使用哪個定時器就打開哪個,沒有的就自己寫上去)
十五、在主函數中寫入如下代碼
/** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date Author Notes* 2024-05-10 先睡個好覺 first version*/#include <rtthread.h>
#include <rtdevice.h> //加載設備驅動頭文件
#include <board.h>#include <hwtimer.h>#define HWTIMER_DEV_NAME "timer3" /* 定時器名稱 */
rt_device_t hw_dev; /* 定時器設備句柄 */rt_err_t ret = RT_EOK; //返回值判斷是否成功
rt_uint32_t timer_cb_num = 0; /*進定時器超調函數次數 */
rt_uint32_t level_flag = 1; /*判斷超聲波接受引腳是否是第一個上升沿*/
rt_uint32_t echo_high_time = 0; //超聲波接受引腳高電平總時間,單位為us
rt_uint32_t freq = 1000000; /* 計數頻率 */
rt_hwtimer_mode_t mode; /* 定時器模式 */
rt_hwtimerval_t timeout_s; /* 定時器超時值 */rt_uint32_t distance_cm = 0; //超聲波測量出的距離#define SR04T_PIN_TRIG GET_PIN(C, 9) //獲取sr04t超聲波觸發引腳號
#define SR04T_PIN_ECHO GET_PIN(C, 8) //獲取sr04t超聲波接收引腳號/* 定時器3超時回調函數,每10us會進來一次*/
static rt_err_t timeout3_cb(rt_device_t dev, rt_size_t size)
{timer_cb_num++;//每進一次超調函數,該變量加一if((rt_pin_read(SR04T_PIN_ECHO) == PIN_HIGH)&&(level_flag)){timer_cb_num = 0; //如果超聲波接收引腳被拉高了,重新進行計數level_flag = 0;}if ((rt_pin_read(SR04T_PIN_ECHO) == PIN_LOW)&&(level_flag == 0)){echo_high_time = timer_cb_num*10; //一個timer_cb_num是10uslevel_flag = 1;rt_kprintf("%d\n",timer_cb_num/9);}return 0;
}int sr04_Init(void)
{//設置sr04t超聲波引腳的模式rt_pin_mode(SR04T_PIN_TRIG, PIN_MODE_OUTPUT);//設置引腳為輸出模式rt_pin_mode(SR04T_PIN_ECHO, PIN_MODE_INPUT_PULLDOWN);//設置ECHO引腳為輸入模式rt_pin_write(SR04T_PIN_TRIG, PIN_LOW);//拉低引腳rt_pin_write(SR04T_PIN_ECHO, PIN_LOW);//拉低引腳/* 查找定時器設備 */hw_dev = rt_device_find(HWTIMER_DEV_NAME);if(hw_dev == RT_NULL){rt_kprintf("hwtimer sample run failed! can't find %s device! \n",HWTIMER_DEV_NAME);return RT_ERROR;}/* 以讀寫方式打開設備 */rt_device_open(hw_dev, RT_DEVICE_OFLAG_RDWR);if(ret != RT_EOK){rt_kprintf("open %s device failed!\n",RT_DEVICE_OFLAG_RDWR);return ret;}/* 設置超時回調函數 */rt_device_set_rx_indicate(hw_dev, timeout3_cb);/* 設置計數頻率(若未設置該項,默認為1Mhz 或 支持的最小計數頻率) */rt_device_control(hw_dev, HWTIMER_CTRL_FREQ_SET, &freq);/* 設置模式為周期性定時器(若未設置,默認是HWTIMER_MODE_ONESHOT)*/mode = HWTIMER_MODE_PERIOD;rt_device_control(hw_dev, HWTIMER_CTRL_MODE_SET, &mode);/* 設置定時器超時值為10us并啟動定時器 */timeout_s.sec = 0; /* 秒 */timeout_s.usec = 10; /* 微秒 */if (rt_device_write(hw_dev, 0, &timeout_s, sizeof(timeout_s)) != sizeof(timeout_s)){rt_kprintf("set timeout value failed\n");return RT_ERROR;}return RT_EOK;
}//信號觸發
void US_SendStartSignal(void)
{rt_pin_write(SR04T_PIN_TRIG, PIN_HIGH);//拉高引腳,觸發信號rt_hw_us_delay(20); //給20us的延時//rt_thread_mdelay(5);rt_pin_write(SR04T_PIN_TRIG, PIN_LOW);//拉低引腳
}//數據處理
//count傳進去的參數是us
float SR04T_DataConversion(rt_uint32_t *count)
{float result = 0;result = (float)((float)(*count * 340) / 2000000.0);*count = 0;result = result*100.0; //將米轉化為厘米return result;
}//-------------------超聲波線程-----------------------------------------------
rt_thread_t Sr04Th_Handler; //姿態解算線程句柄
#define Sr04_TH_PRIO 10 //姿態解算線程優先級
#define Sr04_STK_SIZE 700 //姿態解算線程堆棧大小
#define Sr04_TICK_LEN 5 //姿態解算線程執行時間void th_sr04_entry(void *parameter)
{rt_uint16_t num_trig_time=0;while(1){num_trig_time++;if(num_trig_time>12){num_trig_time = 0;US_SendStartSignal();//超聲波信號觸發}distance_cm = SR04T_DataConversion(&timer_cb_num);//超聲波數據處理//rt_kprintf("%d\n",echo_high_time/28);rt_thread_mdelay(5);}
}int sr04_th_creat(void)
{//超聲波線程Sr04Th_Handler = rt_thread_create("th_sr04_entry",th_sr04_entry,NULL,Sr04_STK_SIZE,Sr04_TH_PRIO,Sr04_TICK_LEN);if(Sr04Th_Handler == NULL){rt_kprintf("th_sr04_entry(create)failed...\n");return -ENOMEM;}return RT_EOK;
}void th_start(void)
{rt_thread_startup(Sr04Th_Handler); //開啟超聲波線程線程調度
}int main(void)
{sr04_Init(); //超聲波初始化sr04_th_creat();//超聲波線程創建th_start();//開啟線程調度return RT_EOK;
}
十六、編譯,有如下報錯,先雙擊進入第一個錯誤
十七、把這段代碼進行注釋
十八、再編譯還剩這個報錯,找不到hwtimer.h文件
十九、跳轉進入這個頭文件
二十、找到它的文件路徑
二十一、打開構建配置,進行路徑包含,應用后關閉
二十二、再次編譯,報錯解決
二十三、連接好硬件
二十四、下載程序,查看串口一,有數據輸出,并且隨著遮擋物的遠近,數據大小有變化
二十五、這里需要注意一下,如果你使用的定時器里面沒有,需要模仿里面的結構自行添加
二十六、最后提醒一下,代碼中輸出的并不是準確的cm數,我只是隨意除了一個數字就輸出了,數據轉換函數在代碼中我也寫了,不過沒有使用,因為它輸出的是浮點數,rtthread要想打印浮點數需要另行配置,在這個工程里我沒有配置,所以要想得到精確的cm數,請自行數據轉換。
rtthread輸出浮點數,可以參考我的這篇文章
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
RT-Thread(RTT)如何打印輸出浮點數