当前位置:   article > 正文

STM32:两种方式实现超声波测距_stm32超声波测距代码

stm32超声波测距代码

超声波模块HC-SR04的工作原理很简单,有很多办法可以完成超声波测距,这里简单介绍两种。

1.定时器中断法

配置定时器的中断并声明一个Time的变量,在中断中先判断标志位,然后检查echo端口是否为高电平,如果是,Time++,然后变量time乘以定时时间就能得到echo端口高电平持续的时间,经过计算就可以得到距离。

Timer.c

  1. #include "stm32f10x.h" // Device header
  2. #include "Timer.h"
  3. extern uint16_t Time; //Time变量在HCSR04.c文件中定义
  4. void Timer_Init()
  5. {
  6. Time = 0;
  7. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //选择APB1总线下的定时器Timer3
  8. TIM_InternalClockConfig(TIM3); //TIM3使用内部时钟
  9. //默认使用内部时钟,不写这句代码也没关系
  10. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
  11. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟1分频
  12. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数模式,此处为向上计数
  13. TIM_TimeBaseInitStructure.TIM_Period = 7200 - 1; //ARR 1 = 0.0001S,自动重装器的值
  14. TIM_TimeBaseInitStructure.TIM_Prescaler = 0; //PSC,预分频器的值
  15. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //高级计时器特有,重复计数
  16. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  17. TIM_ClearFlag(TIM3, TIM_FLAG_Update);
  18. TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); //使能中断
  19. NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //将中断优先级分为两组,即组1和组2。
  20. NVIC_InitTypeDef NVIC_InitStructure;// 定义一个NVIC_InitTypeDef结构体变量,用于初始化中断控制器
  21. NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;// 设置中断通道为TIM3的IRQn中断
  22. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;// 使能中断通道
  23. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;// 设置中断优先级为2,表示高优先级
  24. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;// 设置中断子优先级为1,表示低优先级
  25. NVIC_Init(&NVIC_InitStructure);// 使用NVIC_Init函数初始化中断控制器
  26. TIM_Cmd(TIM3, ENABLE);// 使能定时器TIM3
  27. }
  28. void TIM3_IRQHandler(void) // 定时器3的中断函数
  29. {
  30. if(TIM_GetITStatus(TIM3, TIM_IT_Update) == SET) // 检查定时器3的更新中断标志位是否被设置
  31. {
  32. if (GPIO_ReadInputDataBit(Echo_Port, Echo_Pin) == 1) // 读取回声传感器端口上的引脚状态
  33. {
  34. Time++; // 如果引脚状态为高电平,则增加时间计数器
  35. }
  36. TIM_ClearITPendingBit(TIM3, TIM_IT_Update); // 清空标志位,表示中断已经处理完毕
  37. }
  38. }

Timer.h

  1. #ifndef __TIMER_H
  2. #define __TIMER_H
  3. #define Trig_Port GPIOA
  4. #define Trig_Pin GPIO_Pin_5
  5. #define Trig_RCC RCC_APB2Periph_GPIOA
  6. #define Echo_Port GPIOA
  7. #define Echo_Pin GPIO_Pin_6
  8. #define Echo_RCC RCC_APB2Periph_GPIOA
  9. void Timer_Init(void);
  10. #endif

2.输入捕获法

配置定时器的输入捕获,在echo端口的上升沿捕获一次,下降沿捕获一次,通过“TIM_GetCapture2(TIM3)”这句代码直接可以将时间读取出来。

IC.c

  1. #include "stm32f10x.h" // Device header
  2. void IC_Init(void)
  3. {
  4. RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // TIM3->使用引脚PA6
  5. //在超声波模块已经配置过
  6. // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  7. // GPIO_InitTypeDef GPIO_InitStructure;
  8. // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  9. // GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;//PB6引脚,接入超声波Echo引脚
  10. // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  11. // GPIO_Init(GPIOA, &GPIO_InitStructure);
  12. TIM_InternalClockConfig(TIM3);
  13. TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//配置时基单元
  14. TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  15. TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
  16. TIM_TimeBaseInitStructure.TIM_Period = 65536 - 1; //ARR
  17. TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1; //PSC分频系数
  18. TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
  19. TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStructure);
  20. //通道一
  21. TIM_ICInitTypeDef TIM_ICInitStructure;
  22. TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;//TIM3的通道1
  23. TIM_ICInitStructure.TIM_ICFilter = 0xF;//配置滤波器,参数决定滤波效果,高频滤波
  24. TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性选择,选择上升沿触发
  25. TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//每次都触发捕获
  26. TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//通道触发选择
  27. //通道二
  28. // TIM_ICInitStructure.TIM_Channel=TIM_Channel_2;//捕获通道二
  29. // TIM_ICInitStructure.TIM_ICFilter=0xF;//滤除高频波动
  30. // TIM_ICInitStructure.TIM_ICPolarity=TIM_ICPolarity_Falling;//下降触发捕获
  31. // TIM_ICInitStructure.TIM_ICPrescaler=TIM_ICPSC_DIV1;//不分频
  32. // TIM_ICInitStructure.TIM_ICSelection=TIM_ICSelection_IndirectTI;//交叉通道输入
  33. // TIM_ICInit(TIM3,&TIM_ICInitStructure);
  34. TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);//pwmi模式配置通道2,效果相当于上面的代码
  35. TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
  36. TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
  37. TIM_Cmd(TIM3, ENABLE);
  38. }

IC.h

  1. #ifndef __IC_H
  2. #define __IC_H
  3. void IC_Init(void);
  4. #endif

#超声波部分

这里将展示如何将获取到的时间值计算得到距离,定时器中断和输入捕获两种方法的实现都在下面的文件中,我们正确添加完文件后,在main文件中直接调用就可以实现测距的功能了。

HCSR04.c

  1. #include "stm32f10x.h" // Device header
  2. #include "HCSR04.h"
  3. #include "Timer.h"
  4. #include "Delay.h"
  5. uint16_t Time;
  6. void HCSR04_Init()
  7. {
  8. RCC_APB2PeriphClockCmd(Trig_RCC, ENABLE);
  9. GPIO_InitTypeDef GPIO_InitStruct;
  10. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
  11. GPIO_InitStruct.GPIO_Pin = Trig_Pin;
  12. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  13. GPIO_Init(Trig_Port, &GPIO_InitStruct);
  14. GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
  15. GPIO_InitStruct.GPIO_Pin = Echo_Pin;
  16. GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  17. GPIO_Init(Echo_Port, &GPIO_InitStruct);
  18. GPIO_ResetBits(Trig_Port, Trig_Pin);//Trig引脚给低电平,为后续启动做准备
  19. }
  20. void HCSR04_Start(void)
  21. {
  22. GPIO_SetBits(Trig_Port, Trig_Pin);
  23. Delay_us(40);
  24. GPIO_ResetBits(Trig_Port, Trig_Pin);
  25. Timer_Init();//定时器初始化
  26. }
  27. uint16_t HCSR04_GetValue(void) //定时器中断测距
  28. {
  29. HCSR04_Start();
  30. Delay_ms(100);
  31. return ((Time * 0.0001) * 34000) / 2;
  32. // return Time;
  33. }
  34. float GetLength(void) //输入捕获测距
  35. {
  36. int i=0;
  37. float length=0;
  38. float sum=0;
  39. float Length;
  40. for(i=0;i<5;i++)
  41. {
  42. //减小误差,计算五次
  43. GPIO_SetBits(GPIOA,GPIO_Pin_5);
  44. Delay_us(20);//发送一段40us的高电平
  45. GPIO_ResetBits(GPIOA,GPIO_Pin_5);
  46. Time=TIM_GetCapture2(TIM3); //获取捕获值
  47. length=(Time/58.0);//固定计算超声波距离公式:时间/58.0;单位厘米
  48. sum=sum+length;
  49. }
  50. Length=sum/5.0;
  51. return Length;
  52. }

HCSR04.h

  1. #ifndef __HCSR04_H
  2. #define __HCSR04_H
  3. #define Trig_Port GPIOA
  4. #define Trig_Pin GPIO_Pin_5
  5. #define Trig_RCC RCC_APB2Periph_GPIOA
  6. #define Echo_Port GPIOA
  7. #define Echo_Pin GPIO_Pin_6
  8. #define Echo_RCC RCC_APB2Periph_GPIOA
  9. void HCSR04_Init(void);
  10. uint16_t HCSR04_GetValue(void);
  11. float GetLength(void);
  12. #endif

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/930426
推荐阅读
相关标签
  

闽ICP备14008679号