使用STM32定时器输入捕获模块控制3路超声波传感器
本次使用的超声波传感器是常见HC-SR04,该传感器常常使用在小型机器人和智能小车的避障系统中。

在上图中,5v和GND为模块提供电能,Trig用于触发模块测距,Echo用于接受返回电平信号。
其操作时序图如下:

如上图所示,STM32给Trig引脚一个超过10us的高电平,就可以使能模块内部的测距电路,模块会循环发出8个40kHz脉冲,发射出超声波,然后通过检测Echo引脚的高电平时间就可以测量出模块与障碍物之间的距离。其计算公式可表示如下:

distance=340∗Echo高电平时间2distance=340∗Echo高电平时间2

distance=\frac{340*Echo高电平时间}{2}
模块驱动程序如下:

void HC_SR04_Init(void)
{/*初始化GPIO*/GPIO_InitTypeDef  GPIO_InitStructure;TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;NVIC_InitTypeDef         NVIC_InitStructure;TIM_ICInitTypeDef        TIM_ICInitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);//使能GPIOA时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能定时器2GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; //Trig:PA4,PA5,PA6GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;GPIO_Init(GPIOA, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3; //Echo: PA2,PA3对应TIM2的通道3,4GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//打开引脚复用GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_TIM2);GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_TIM2);GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOARCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//Enable GPIOB's ClockGPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PB3 refers to TIM2's channel 2GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHzGPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_TIM2);GPIO_Init(GPIOB, &GPIO_InitStructure);//initialize GPIOB/初始化TIM2*/TIM_TimeBaseStructure.TIM_Period = 0xffffffff; //传感器最大探测距离4000mm,一般不会溢出TIM_TimeBaseStructure.TIM_Prescaler =84-1;  //设置TIM2时钟频率为1MHzTIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化TIM2输入捕获TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge; //上升和下降都触发输入捕获TIM_ICInitStructure.TIM_ICSelection =  TIM_ICSelection_DirectTI;TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x00;TIM_ICInit(TIM2, &TIM_ICInitStructure);TIM_ICInitStructure.TIM_Channel = TIM_Channel_3; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge; TIM_ICInitStructure.TIM_ICSelection =  TIM_ICSelection_DirectTI;TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  TIM_ICInitStructure.TIM_ICFilter = 0x00;TIM_ICInit(TIM2, &TIM_ICInitStructure);TIM_ICInitStructure.TIM_Channel = TIM_Channel_4; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_BothEdge; TIM_ICInitStructure.TIM_ICSelection =  TIM_ICSelection_DirectTI;TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  TIM_ICInitStructure.TIM_ICFilter = 0x00;TIM_ICInit(TIM2, &TIM_ICInitStructure);//设置输入捕获中断NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure);  TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC2|TIM_IT_CC3|TIM_IT_CC4,ENABLE);//使能中断TIM_Cmd(TIM2,ENABLE);     dist.overflow=0;
}

值得注意的是,这里的输入捕获的边缘极性设定为上升和下降沿都捕获,效率比较高,也有大神开始使用上升沿捕获,然后在中断中将捕获记性设定为下降沿捕获,我试过这种办法,程序容易卡死,所以没有采用。
中断程序可以这样编写:

void TIM2_IRQHandler(void)
{static uint16_t cnt_f,cnt_l,cnt_r;if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET){dist.overflow++;TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
//       printf("overflow\n");}if(TIM_GetITStatus(TIM2, TIM_IT_CC2)!=RESET){cnt_f++;if(cnt_f%2==1)//检测到了上升电平{TIM2->CNT=0;//计数器清零}else//检测到了下降沿电平,读取距离值{dist.cnt=TIM2->CNT;TIM2->CNT=0;dist.f_distance=(dist.overflow*0xffffffff+dist.cnt)*0.17f;printf("F_dis=%.2fmm\n",dist.f_distance);dist.overflow=0;}if(cnt_f>65535)cnt_f=0;TIM_ClearITPendingBit(TIM2,  TIM_IT_CC2);}if(TIM_GetITStatus(TIM2, TIM_IT_CC3)!=RESET){cnt_l++;if(cnt_l%2==1)//检测到了上升电平{TIM2->CNT=0;}else{dist.cnt=TIM2->CNT;TIM2->CNT=0;dist.l_distance=(dist.overflow*0xffffffff+dist.cnt)*0.17f;printf("L_dis=%.2fmm\n",dist.l_distance);dist.overflow=0;}if(cnt_l>65535)cnt_l=0;TIM_ClearITPendingBit(TIM2,  TIM_IT_CC3);}if(TIM_GetITStatus(TIM2, TIM_IT_CC4)!=RESET){cnt_r++;if(cnt_r%2==1){TIM2->CNT=0;}else{dist.cnt=TIM2->CNT;TIM2->CNT=0;dist.r_distance=(dist.overflow*0xffffffff+dist.cnt)*0.17f;printf("R_dis=%.2fmm\n",dist.r_distance);dist.overflow=0;}if(cnt_r>65535)cnt_r=0;TIM_ClearITPendingBit(TIM2,  TIM_IT_CC4);}
}

这样设计的好处是中断程序设计简单,可以保证实时性。
触发模块进行测量,通过给模块的Trig引脚一个超过10us高电平信号就可以触发模块进行距离测量,程序代码如下:

/*
function:启动距离测量
choice: 0:左边超声波模块1:中间超声波模块2:右边超声波模块
*/
void Get_Distance(uint8_t choice)
{switch(choice){case 0:GPIO_ResetBits(GPIOA,GPIO_Pin_4);GPIO_SetBits(GPIOA,GPIO_Pin_4);Delay_us(15);GPIO_ResetBits(GPIOA,GPIO_Pin_4);  break;case 1:GPIO_ResetBits(GPIOA,GPIO_Pin_5);GPIO_SetBits(GPIOA,GPIO_Pin_5);Delay_us(15);GPIO_ResetBits(GPIOA,GPIO_Pin_5);  break;case 2:GPIO_ResetBits(GPIOA,GPIO_Pin_6);GPIO_SetBits(GPIOA,GPIO_Pin_6);Delay_us(15);GPIO_ResetBits(GPIOA,GPIO_Pin_6);  break;}
}

STM32控制3路超声波传感器相关推荐

  1. STM32控制两路直流电机_2

    在上一篇博客中讲述了怎样使用STM32输出两路PWM波控制电机转动和使用定时器的编码器模块功能读取电机编码器的信息以获得电机的实时转速. 本篇博客内容包括:控制电机的转向,读取编码器数值,以及速度PI ...

  2. 四轮两驱小车(四):STM32驱动5路灰度传感器PID循迹

    目录 前言: 小车效果展示: 5路数字灰度传感器: 巡线思路: 加入PID调节的代码: 前言: 之前买了一批5路灰度传感器,想用这传感器进行循迹,无奈网上和官方的资料提供的还是比较少,这里还是做一下当 ...

  3. STM32控制16路舵机控制板PCA9685

    介绍 PCA9685 是最新的快速模式 Plus(Fm+)系列中的一员. Fm+器件可以提供更高的频率 (高达 1MHz)和更频繁(densely populated) 的总线操作(高达 4000pF ...

  4. 基于超声波传感器的液位测量及控制系统设计(STM32)

    一.引言 随着工业的发展,计算机.微电子.传感器等高新技术的应用和研究,液位仪表的研制得到了长足的发展,以适应越来越高的应用要求.液位的测量在工业生产过程中已经起着相当重要的作用,其类型大概可以分为接 ...

  5. 详细介绍如何从零开始制作51单片机控制的智能小车(二)———超声波模块、漫反射光电管、4路红外传感器的介绍和使用

       我会通过本系列文章,详细介绍如何从零开始用51单片机去实现智能小车的控制,在本系列的上一篇文章中介绍了如何让小车动起来,本文作为本系列的第二篇文章,主要介绍让小车实现自动避障所涉及的一些传感器, ...

  6. STM32——通用定时器控制超声波传感器HCSR04

    HCSR-04介绍 HC-SR04 超声波测距模块可提供 2cm-400cm 的非接触式距离感测功能,测 距精度可达高到的非接触式距离感测功能,测距精度可达高到 3mm :模块包括超声波发射器.接收器 ...

  7. 距离传感器控制灯泡代码_如何使用颜色传感器和超声波传感器检测障碍物和避障...

    上一期的内容中,我给大家介绍了如何使用触碰传感器检测障碍物和避障,今天我们再来说说如何使用颜色传感器和超声波传感器检测障碍物和避障. 使用颜色传感器 在大多数情况下,EV3颜色传感器并不适合用于障碍物 ...

  8. 树莓派控制超声波传感器

    看到大二的时候有写过关于树莓派控制HC-SR04超声波测距模块的教程,当时并未给出代码(也不知道是什么原因,估计初写博客并不熟悉吧),所以在三年后的今天贴代码出来,给大家参考下. //树莓派控制超声波 ...

  9. 超声波传感器介绍及其使用(STM32)

    超声波传感器介绍及其使用(STM32) 超声波传感器型号 实物图 引脚 超声波传感器原理图 特点 工作原理 超声波传感器时序图 测量误差的产生 注意 超声波传感器部分代码 实验现象 源码获取 超声波传 ...

最新文章

  1. 【怎样写代码】对象克隆 -- 原型模式(一):问题案例
  2. 2014年第五届蓝桥杯决赛Java本科B组试题解析
  3. Leetcode 912.排序算法(快排)
  4. callmode php_Rabbitmq各方法的作用详解
  5. 《App后台开发运维与架构实践》第3章 App后台核心技术
  6. 采集标签_分流器(二):灵活分流能力,数据采集无忧
  7. pytorch创建datset
  8. mysql命令行进入报错ERROR 2002 (HY000)
  9. coreELEC ceemmc 写入 cm311-1a 刷机排坑 Armbian 搞机篇
  10. 电脑小技巧:怎么设置默认浏览器
  11. 量子力学对计算机影响,人们对量子力学的理解有误?
  12. JAVA 图片压缩及png转jpg
  13. VMware copy之后,如何查看网卡地址 HWADDR
  14. 从零开始的iOS开发:10 | 如何构建一个APP
  15. Matlab读取二进制数据文件
  16. element中滑块组件Slider展示一天24小时的时间问题
  17. html如何设置展开全文,Js实现点击查看全文(纯手工代码)
  18. GEE用户贡献的数据列表
  19. web前端CSS选择符:表示要定义样式的对象
  20. k8s集群Deployment与Service+名称空间

热门文章

  1. 寻找hadoop、hive、spark对应版本
  2. 【Web技术】961- 3分钟搞定海报合成
  3. 利用代理IP组建代理IP池
  4. S32DS使用官方SDK建立工程后更改芯片引脚( 以S32K144为例 )
  5. 在keil上编译linux下的STM32裸机工程 arm 编译器介绍
  6. 基于 github issues 实现第三方评论系统
  7. 浅谈jQuery属性获取
  8. 会场安排问题贪心算法
  9. 懒猫社长新便民工程119模式升级:践行“便利店+”战略,推进多元化产业链构建
  10. 初中学历怎么提高学历 有哪些途径