完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
下面是讲解使用ST MCU中的HAL库来实现,超声波测距的功能。
1、MCU主控: STM32L052C8T6 2、超声波模块: SR04 基本工作原理: 1、采用IO口TRIG触发测距,给至少10us的高电平信号; 2、模块自动发送8个40khz的方波,自动检测是否有信号返回; 3、有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2; 本模块使用方法简单,一个控制口发一个10US以上的高电平,就可以在接收口等待高电平输出.一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离.如此不断的周期测,即可以得到你移动测量的值。超声波模块时序图如下: 3、输入捕获简介 输入捕获可以用来测量脉冲宽度或者测量频率。超声波用到的是测量脉宽,这里我以测量脉宽为例,用一个简图来说明输入捕获的原理,如下图: 如上图所示,就是输入捕获测量高电平脉宽的原理,假定定时器工作在向上计数模式,图中t1-t2时间,就是我们需要测量的高电平时间。测量方法如下:首先设置定时器通道x为上升沿捕获,这样,t1时刻就会捕捉到CNT值,然后立即清零CNT,并设置通道x为下降沿捕获,这样t2时刻又会发生捕获事件,得到此时的CNT值,记为CCRx2。这样,根据定时器的计数频率,我们就可以算出t1-t2的时间,从而得到高电平的脉宽。 在t1-t2之间,可能产生N次定时器溢出,这就要求我们对定时器溢出做处理,防止高电平太长,导致数据不准确。如上图所示,t1-t2之间CNT计数的的次数等于:N*ARR+CRRx2,有了这个计数次数,再乘以CNT的计数周期,即可得到t1-t2的时间长度,即高电平持续时间。 4、STM32CubeMx 配置 1)系统时钟配置(这里不做介绍,前查看以往教程) 2)定时器21配置 5、代码说明: 1)、tim.c文件 /* Includes ------------------------------------------------------------------*/ #include "tim.h" /* USER CODE BEGIN 0 */ #include "gpio.h" #include "stdio.h" uint8_t text_flag = 0; uint8_t dis_fm = 0; uint8_t Channel1Edge = 0; uint16_t Channel1HighTime, Channel1RisingTime, Channel1FallingTime; /* USER CODE END 0 */ /* USER CODE BEGIN 1 */ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) { /*防止未使用参数(s)编译警告*/ UNUSED(htim); if(htim->Instance == htim21.Instance) { if(htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { if(Channel1Edge == 0) //捕获上升沿 { Channel1RisingTime = HAL_TIM_ReadCapturedValue(&htim21, TIM_CHANNEL_1); //获取上升沿开始时间点 __HAL_TIM_SET_CAPTUREPOLARITY(&htim21, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_FALLING); //切换捕获极性 HAL_TIM_IC_Start_IT(&htim21, TIM_CHANNEL_1); //切换捕获极性后需重新启动 Channel1Edge = 1; //上升沿、下降沿捕获标志位 } else if(Channel1Edge == 1) //捕获下降沿 { Channel1FallingTime = HAL_TIM_ReadCapturedValue(&htim21, TIM_CHANNEL_1); //获取下降沿时间点 __HAL_TIM_SET_CAPTUREPOLARITY(&htim21, TIM_CHANNEL_1, TIM_INPUTCHANNELPOLARITY_RISING); //切换捕获极性 HAL_TIM_IC_Start_IT(&htim21, TIM_CHANNEL_1); //切换捕获极性后需重新启动 Channel1HighTime = Channel1FallingTime < Channel1RisingTime ? Channel1FallingTime + 0xffff - Channel1RisingTime + 1 : Channel1FallingTime - Channel1RisingTime; //高电平持续时间 = 下降沿时间点 - 上升沿时间点 dis_fm = Channel1HighTime * 17 / 100; //计算超声波测量距离 printf("dis_fm = %dcm rn", dis_fm); if(dis_fm<30) Beep_on; else Beep_off; //i++;//累加计数 Channel1Edge = 0; //一次采集完毕,清零 } HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin); } } } /* USER CODE END 1 */ 3)、main.c文件 /* Includes ------------------------------------------------------------------*/ #include "main.h" #include "i2c.h" #include "tim.h" #include "usart.h" #include "gpio.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "task.h" #include "stdio.h" /* USER CODE END Includes */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ int main(void) { /* USER CODE BEGIN 1 */ static uint8_t Flag=0; /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_I2C1_Init(); MX_TIM2_Init(); MX_TIM21_Init(); MX_USART1_UART_Init(); /* USER CODE BEGIN 2 */ Moter_StartPWM(); OLED_Init(); OLED_Clear(); OLED_ShowString(0,0,"www.taxing.com",16); OLED_ShowCHinese(0,4,0);// OLED_ShowCHinese(16,4,1);// OLED_ShowCHinese(32,4,2);// OLED_ShowCHinese(48,4,6);// OLED_ShowCHinese(0,6,3);// OLED_ShowCHinese(16,6,4);// OLED_ShowCHinese(32,6,5);// OLED_ShowCHinese(48,6,6);// HAL_TIM_IC_Start_IT(&htim21, TIM_CHANNEL_1); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ #if 0 if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==1&&Flag==0) { HAL_Delay(100); if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==1) { Car_Track(); Flag=1; } } else { Moter_off(); } #endif Trig_On; HAL_Delay(1); Trig_Off; HAL_Delay(100); } /* USER CODE END 3 */ } 别忘了打开定时器21的总中断哦 基本配置完成,打开串口助手即可看到打印距离信息 |
|
|
|
只有小组成员才能发言,加入小组>>
3310 浏览 9 评论
2991 浏览 16 评论
3492 浏览 1 评论
9057 浏览 16 评论
4086 浏览 18 评论
1176浏览 3评论
604浏览 2评论
const uint16_t Tab[10]={0}; const uint16_t *p; p = Tab;//报错是怎么回事?
597浏览 2评论
用NUC131单片机UART3作为打印口,但printf没有输出东西是什么原因?
2334浏览 2评论
NUC980DK61YC启动随机性出现Err-DDR是为什么?
1895浏览 2评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-22 16:54 , Processed in 1.395016 second(s), Total 77, Slave 59 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号