您的位置:首页 > 其它

基于stm32f10x的超声波模块HC-SR04的测距示例,并用串口将数据打印出来

2019-04-11 23:06 393 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_42465397/article/details/89221858

 

一.所需材料:

1任何一种型号的stm32f10x的微控制器

2.HC-SR04模块

3.安装串口驱动与串口助手(这里用的火哥的串口调试助手)

4.ST-link或者串口等下载方式都可以

二。超声波原理

网上一大堆,这里我就大体说一下:单片机先给TRIG一个大于10us的高电平,然后模块ECHO引脚会发出一个高电平,检测高电平的时间乘声速便可算出距离。这里ECHO发出也接收,所以检测的时间,假设按秒算,然后乘170便是以m为单位的距离。

三.源代码分析

1.接口定义:

//由于只是用的定时器的基本计时功能,所以IO口随便找两个便可以
#define HCSR04_PORT              GPIOB
#define HCSR04_PORTC_CLK_FUN     RCC_APB2PeriphClockCmd
#define HCSR04_CLK               RCC_APB2Periph_GPIOB
#define HCSR04_TRIG              GPIO_Pin_11
#define HCSR04_ECHO              GPIO_Pin_10

2.驱动函数分析

//超声波计数,记录有几个更新中断,由于在.c文件中定义,中断函数中测试其值,故加个extern
extern u16 msHcCount = 0; 

//IO口初始化 TRIG为普通推挽输出,ECHO为浮空输入,
//配置时基结构体
void Hcsr04Init(void)
{  
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;   
    GPIO_InitTypeDef GPIO_InitStructure;
    HCSR04_PORTC_CLK_FUN(HCSR04_CLK, ENABLE);
   
    GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;      
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
    GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
     
    GPIO_InitStructure.GPIO_Pin =   HCSR04_ECHO;     
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);  
    GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);    
     
          
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);   
     
    TIM_DeInit(TIM2);
    TIM_TimeBaseStructure.TIM_Period = (1000-1);         //定时器时钟1MHZ,自动重装载寄存器的值为1000, 也就是说满一次为1MS
    TIM_TimeBaseStructure.TIM_Prescaler =(72-1); 
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);          
        
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);  
    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);    
    hcsr04_NVIC();
    TIM_Cmd(TIM4,DISABLE);     
}

//中断配置,这里只用了一个中断,不用考虑中断嵌套等等,所以中断优先级以及次优先级可以随便配置,只用到了定时器update中断

void hcsr04_NVIC(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;             
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;         
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;       
NVIC_Init(&NVIC_InitStructure);
}

//关闭定时器4
static void CloseTimerForHc(void)    
{
   TIM_Cmd(TIM4, DISABLE); 

//打开定时器4
static void OpenTimerForHc(void)  
{
   TIM_SetCounter(TIM4,0);
   msHcCount = 0;
   TIM_Cmd(TIM4, ENABLE); 
}
//获取定时器4计数器值,此值为更新中断的次数*1000+计数器的值
u32 GetEchoTimer(void)
{
   u32 t = 0;
   t = msHcCount*1000;
   t += TIM_GetCounter(TIM4);
   TIM4->CNT = 0;  
   Systick_DelayMs(50);
   return t;
}

//通过定时器4计数器值推算距离,单位厘米,假设测试值为x,距离y=x/1M*17000

//这里每测出5此求个平均值输出
float Hcsr04GetLength(void )
{
   u32 t = 0;
   int i = 0;
   float lengthTemp = 0;
   float sum = 0;
   while(i!=5)
   {
      GPIO_SetBits(HCSR04_PORT,HCSR04_TRIG);
      Systick_DelayUs(20);
      GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
      while(GPIO_ReadInputDataBit(HCSR04_PORT,HCSR04_ECHO)==RESET);
      OpenTimerForHc();
      i = i + 1;
      while(GPIO_ReadInputDataBit(HCSR04_PORT,HCSR04_ECHO)==SET);
      CloseTimerForHc();
      t = GetEchoTimer();
      lengthTemp = ((float)t*0.017);//cm
     
      sum = lengthTemp + sum ;
        
    }
    lengthTemp = sum/5.0;
    return lengthTemp;
}

 

3.主函数测试程序:

float length;
  //延时函数初始化
  Systick_DelayMs(10); //这里用的系统滴答定时器延时  
  hcsr04_NVIC(); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
  
  USART_Config();//串口服务程序,这里我用的火哥的串口一
   Hcsr04Init();  

  while(1) 
  {  
     length = Hcsr04GetLength();
     printf("距离为:%.3fcm\n",length);
     Systick_DelayMs(1000);
  }

 

四.效果图

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: