01模块来源
资料下载链接:https://pan.baidu.com/s/1sSah9PvLBrmbA7So-6YcSw
资料提取码:qq35
02 规格参数
工作电压:3-5.5V
工作电流:5.3MA
感应角度:小于15度
探测距离:2CM-600CM
探测精度:0.1CM+1%
输出方式: GPIO
管脚数量:4 Pin
以上信息见厂家资料文件
03移植过程
我们的目标是将例程移植至CW32F030C8T6开发板上【能够判断前方障碍物距离的功能】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。
3.1查看资料
只需要在 Trig 管脚(触发信号)输入一个 10US 以上的高电平,系统便可发出 8 个 40KHZ 的超声波脉冲,然后检测回波信号。当检测到回波信号后,通过 Echo 管脚输出。根据 Echo 管脚输出高电平的持续时间可以计算距离值。即距离值为:(高电平时间*340m/s)/2。
当测量距离超过 HC-SR04 的测量范围时,仍会通过 Echo管脚输出高电平的信号,高电平的宽度约为 66ms。如图所示:
测量周期:当接收到 HC-SR04 通过 Echo 管脚输出的高电平脉冲后,便可进行下一次测量,所以测量周期取决于测量距离,当距离被测物体很近时,Echo 返回的脉冲宽度较窄,测量周期 就很短;当距离被测物体比较远时,Echo 返回的脉冲宽度较宽,测量周期也就相应的变长。最坏情况下,被测物体超出超声波模块的测量范围,此时 返回的脉冲宽度最长,约为 66ms,所以最坏情况下的测量周期稍大于 66ms 即可(取 70ms 足够)。
3.2引脚选择
接线表
3.3移植至工程
工程模板参考入门手册的工程模板
移植步骤中的导入.c和.h文件与【CW32模块使用】DHT11温湿度传感器相同,只是将.c和.h文件更改为bsp_ultrasonic.c与bsp_ultrasonic.h。这里不再过多讲述,移植完成后面修改相关代码。
在文件bsp_ultrasonic.c中,编写如下代码。
/** Change Logs:* Date Author Notes* 2024-06-20 LCKFB-LP first version*/#include "bsp_ultrasonic.h"unsigned char msHcCount = 0;//ms计数float distance = 0;/******************************************************************* 函 数 名 称:bsp_ultrasonic* 函 数 说 明:超声波初始化* 函 数 形 参:无* 函 数 返 回:无* 作 者:LC* 备 注:TRIG引脚负责发送超声波脉冲串******************************************************************/void Ultrasonic_Init(void){GPIO_InitTypeDef GPIO_InitStructure;BTIM_TimeBaseInitTypeDef BTIM_TimeBaseInitStruct; // 定时器基本初始化结构体RCC_SR04_ENABLE(); // 使能GPIO时钟RCC_TIMER_ENABLE(); // 使能定时器时钟// GPIO配置参数GPIO_InitStructure.Pins = GPIO_TRIG;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;GPIO_Init(PORT_SR04, &GPIO_InitStructure);GPIO_InitStructure.Pins = GPIO_ECHO;GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP; // 上拉输入GPIO_Init(PORT_SR04, &GPIO_InitStructure);// 禁止中断,以安全地配置NVIC__disable_irq();// 开启BTIM1中断,并关联到NVICNVIC_EnableIRQ(TIMER_IRQ);// 允许中断,恢复中断状态__enable_irq();// 配置定时器模式、周期和预分频器BTIM_TimeBaseInitStruct.BTIM_Mode = BTIM_Mode_TIMER; // 设置为定时器模式BTIM_TimeBaseInitStruct.BTIM_Period = 1000 - 1; // 设置周期,使得定时器每1ms产生一次溢出中断BTIM_TimeBaseInitStruct.BTIM_Prescaler = BTIM_PRS_DIV64; // 预分频器设置为64,以降低时钟频率// 使用上述配置初始化定时器BTIM1BTIM_TimeBaseInit(PORT_TIMER, &BTIM_TimeBaseInitStruct);// 使能BTIM1的溢出中断BTIM_ITConfig(PORT_TIMER, BTIM_IT_OV, ENABLE);// // 启动定时器BTIM1// BTIM_Cmd(PORT_TIMER, ENABLE);}/******************************************************************* 函 数 名 称:Open_Timer* 函 数 说 明:打开定时器* 函 数 形 参:无* 函 数 返 回:无* 作 者:LC* 备 注:******************************************************************/void Open_Timer(void){BTIM_SetCounter(PORT_TIMER, 0); // 清除定时器计数msHcCount = 0;BTIM_Cmd(PORT_TIMER, ENABLE); // 使能定时器}/******************************************************************* 函 数 名 称:Get_TIMER_Count* 函 数 说 明:获取定时器定时时间* 函 数 形 参:无* 函 数 返 回:数据* 作 者:LC* 备 注:******************************************************************/uint32_t Get_TIMER_Count(void){uint32_t time = 0;time = msHcCount*1000; // 得到ustime += BTIM_GetCounter(PORT_TIMER); // 得到msBTIM_SetCounter(PORT_TIMER, 0); // 清除定时器计数delay_ms(10);return time ;}/******************************************************************* 函 数 名 称:Close_Timer* 函 数 说 明:关闭定时器* 函 数 形 参:无* 函 数 返 回:无* 作 者:LC* 备 注:******************************************************************/void Close_Timer(void){BTIM_Cmd(PORT_TIMER, DISABLE); // 关闭定时器}/******************************************************************* 函 数 名 称:TIMER_IRQHandler* 函 数 说 明:定时器中断服务函数* 函 数 形 参:无* 函 数 返 回:无* 作 者:LC* 备 注:1ms进入一次******************************************************************/void TIMER_IRQHandler(void){if (BTIM_GetITStatus(CW_BTIM1, BTIM_IT_OV)) // 检查定时器中断发生{msHcCount++;BTIM_ClearITPendingBit(PORT_TIMER, BTIM_IT_OV); // 清除中断标志}}/******************************************************************* 函 数 名 称:Hcsr04GetLength* 函 数 说 明:获取测量距离* 函 数 形 参:无* 函 数 返 回:测量距离* 作 者:LC* 备 注:无******************************************************************/float Hcsr04GetLength(void){/*测5次数据计算一次平均值*/float length = 0;float t = 0;float sum = 0;unsigned int i = 0;while(i != 10){SR04_TRIG(1);//trig拉高信号,发出高电平delay_1us(20);//持续时间超过10usSR04_TRIG(0);//trig拉低信号,发出低电平/*Echo发出信号 等待回响信号*//*输入方波后,模块会自动发射8个40KHz的声波,与此同时回波引脚(echo)端的电平会由0变为1;(此时应该启动定时器计时);当超声波返回被模块接收到时,回波引 脚端的电平会由1变为0;(此时应该停止定时器计数),定时器记下的这个时间即为超声波由发射到返回的总时长;*/while(SR04_ECHO() == GPIO_Pin_RESET);//echo等待回响Open_Timer(); //打开定时器i++;while(SR04_ECHO() == GPIO_Pin_SET);Close_Timer(); // 关闭定时器t = Get_TIMER_Count(); // 获取时间,分辨率为1uslength = (float)t / 58.0f; // cmsum += length;}length = sum/10;//五次平均值distance = length;return length;}
在文件bsp_ultrasonic.h中,编写如下代码。
/** Change Logs:* Date Author Notes* 2024-06-20 LCKFB-LP first version*/#ifndef _BSP_ULTRASONIC_H_#define _BSP_ULTRASONIC_H_#include "board.h"#define RCC_SR04_ENABLE() __RCC_GPIOA_CLK_ENABLE()#define PORT_SR04 CW_GPIOA#define GPIO_TRIG GPIO_PIN_1#define GPIO_ECHO GPIO_PIN_2#define RCC_TIMER_ENABLE() __RCC_BTIM_CLK_ENABLE()#define PORT_TIMER CW_BTIM1#define TIMER_IRQ BTIM1_IRQn#define TIMER_IRQHandler BTIM1_IRQHandler#define SR04_TRIG(x) GPIO_WritePin( PORT_SR04, GPIO_TRIG, x?GPIO_Pin_SET:GPIO_Pin_RESET)#define SR04_ECHO() GPIO_ReadPin( PORT_SR04, GPIO_ECHO )void Ultrasonic_Init(void);//超声波初始化float Hcsr04GetLength(void );//获取超声波测距的距离#endif
04移植验证
在自己工程中的main主函数中,编写如下。
/** Change Logs:* Date Author Notes* 2024-06-20 LCKFB-LP first version*/#include "board.h"#include "stdio.h"#include "bsp_uart.h"#include "bsp_ultrasonic.h"int32_t main(void){board_init(); // 开发板初始化uart1_init(115200); // 串口1波特率115200Ultrasonic_Init();printf("Start.......rn");while(1){printf((const char *)"距离为 = %.2fCMrn",Hcsr04GetLength() );delay_ms(500);}}
移植现象:距离20CM处摆放障碍物,输出换算后的实际距离。
模块移植成功案例代码:
链接:https://pan.baidu.com/s/1AwXOFbLryUoYPW-ueRZ_qA?pwd=LCKF
提取码:LCKF
1051