STM32控制3路超声波传感器
2018-03-06 20:17
555 查看
使用STM32定时器输入捕获模块控制3路超声波传感器
本次使用的超声波传感器是常见HC-SR04,该传感器常常使用在小型机器人和智能小车的避障系统中。
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/18/1258732bcbbe38bcd7fa7c5c51bfc72a)
在上图中,5v和GND为模块提供电能,Trig用于触发模块测距,Echo用于接受返回电平信号。
其操作时序图如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/202009/18/ebc359c0c6fd79890a31e49517044637)
如上图所示,STM32给Trig引脚一个超过10us的高电平,就可以使能模块内部的测距电路,模块会循环发出8个40kHz脉冲,发射出超声波,然后通过检测Echo引脚的高电平时间就可以测量出模块与障碍物之间的距离。其计算公式可表示如下:
distance=340∗Echo高电平时间2distance=340∗Echo高电平时间2
模块驱动程序如下:
值得注意的是,这里的输入捕获的边缘极性设定为上升和下降沿都捕获,效率比较高,也有大神开始使用上升沿捕获,然后在中断中将捕获记性设定为下降沿捕获,我试过这种办法,程序容易卡死,所以没有采用。
中断程序可以这样编写:
这样设计的好处是中断程序设计简单,可以保证实时性。
触发模块进行测量,通过给模块的Trig引脚一个超过10us高电平信号就可以触发模块进行距离测量,程序代码如下:
本次使用的超声波传感器是常见HC-SR04,该传感器常常使用在小型机器人和智能小车的避障系统中。
在上图中,5v和GND为模块提供电能,Trig用于触发模块测距,Echo用于接受返回电平信号。
其操作时序图如下:
如上图所示,STM32给Trig引脚一个超过10us的高电平,就可以使能模块内部的测距电路,模块会循环发出8个40kHz脉冲,发射出超声波,然后通过检测Echo引脚的高电平时间就可以测量出模块与障碍物之间的距离。其计算公式可表示如下:
distance=340∗Echo高电平时间2distance=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);//使能定时器2 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6; //Trig:PA4,PA5,PA6 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_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,4 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//打开引脚复用 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_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);//初始化GPIOA RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//Enable GPIOB's Clock GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PB3 refers to TIM2's channel 2 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_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时钟频率为1MHz TIM_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.STM32中对EXTI_PE5_Config()函数的理解(自定义)之中断控制按键LED
- STM32(Cortex-M3) 中NVIC(嵌套向量中断控制)的理解
- STM32 控制GSM模块收发信息 F407 discovery
- Stm32串口控制
- STM32控制步进电机实现精确转动
- 使用stm32主从门控模式精确控制脉冲个数
- stm32----通过电调控制无刷电机
- STM32控制IO基本配置的讲解
- STM32 (Cortex-M3) 中NVIC(嵌套向量中断控制)的理解
- STM32控制三轴加速度传感器实现分析(1)
- STM32按键控制LED(不用固件库)
- STM32 控制步进电机 28BYJ-48
- 关于stm32 控制SIM900A的控制心得与体会
- STM32 精确输出PWM脉冲数控制电机(转)
- stm32 按键(中断)控制LED的亮灭,按一次亮,再按一次灭;
- STM32按键控制开关灯
- STM32中控制I/O口的寄存器们
- STM32按键控制灯
- stm32控制2.4G芯片的应用