当前位置:   article > 正文

基于stm32的超声波模块(中断实现)_超声波 中断 stm32f030

超声波 中断 stm32f030

开发板:秉火-霸道V1
芯片:STM32F103ZET6
定时器:TIM2
通道: 3

模块工作原理

  • 采用 IO 触发测距,给 Trig 引脚至少 10us 的高电平信号;
  • 模块自动发送 8 个 40khz 的方波,自动检测是否有信号返回;
  • 有信号返回,通过引脚 Echo 输出一高电平,高电平持续的时间就是 超声波从发射到返回的时间.
  • 测试距离 = (高电平时间 * 声速(340M/S)) / 2;

时序图

在这里插入图片描述

我们可以借助通用定时器的 输入捕获 来测量 Echo 引脚高电平持续的时间

HC_SR04.h

#ifndef _BSP_HCSR04_H
#define _BSP_HCSR04_H

#include"stm32f10x.h"
#include"stm32f10x_tim.h"

//TIM2
#define GENERAL_TIMx            TIM2
#define GENERAL_TIMx_CLK_FUN    RCC_APB1PeriphClockCmd
#define GENERAL_TIMx_CLK        RCC_APB1Periph_TIM2

//Trig引脚定义---PA10
#define HCSR04_GPIO_CLK_FUN  RCC_APB2PeriphClockCmd
#define HCSR04_GPIO_CLK      RCC_APB2Periph_GPIOA
#define HCSR04_GPIO_TRIG_PORT GPIOA
#define HCSR04_GPIO_TRIG_PIN  GPIO_Pin_10

#define HCSR04_TRIG_Hight   HCSR04_GPIO_TRIG_PORT->BSRR = HCSR04_GPIO_TRIG_PIN
#define HCSR04_TRIG_Low     HCSR04_GPIO_TRIG_PORT->BRR = HCSR04_GPIO_TRIG_PIN

//TIM引脚定义
#define GENERAL_TIMx_CH3_CLK_FUN    RCC_APB2PeriphClockCmd
#define GENERAL_TIMx_CH3_CLK        RCC_APB2Periph_GPIOA
#define GENERAL_TIMx_CH3_PORT       GPIOA
#define GENERAL_TIMx_CH3_PIN        GPIO_Pin_2
#define GENERAL_TIMx_CHANNEL_x      TIM_Channel_3

//TIM2中断
#define GENERAL_TIMx_IRQn       TIM2_IRQn
#define GENERAL_TIMx_IRQHandler TIM2_IRQHandler 


typedef struct {
    uint8_t Capture_FinishFlag; // 捕获结束标志位
    uint8_t Capture_StartFlag;  // 捕获开始标志位
    uint16_t Capture_CcrValue;  // 捕获寄存器的值
    uint16_t Capture_Period;    // 自动重装载寄存器更新标志
} TIM_ICUserValueTypeDef;

extern TIM_ICUserValueTypeDef TIM_ICUserValueStruct;

void TIM_Config(void);

void HCSR04_GPIO_Config(void);
void HCSR04_TRIG_Send(void);


#endif /*_BSP_HCSR04_H*/
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

HC_SR04.c

/*
    Trig: PA2
    Echo: PA10
*/

#include"bsp_HCSR04.h"
#include "bsp_delay.h"

TIM_ICUserValueTypeDef TIM_ICUserValueStruct = {0,0,0,0};

//HCSR04初始化引脚
void HCSR04_GPIO_Config(void)
{
    //定义GPIO结构体变量
    GPIO_InitTypeDef GPIO_InitStruct;
    //打开时钟
    HCSR04_GPIO_CLK_FUN(HCSR04_GPIO_CLK,ENABLE);

    //Trig引脚
    GPIO_InitStruct.GPIO_Pin = HCSR04_GPIO_TRIG_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(HCSR04_GPIO_TRIG_PORT,&GPIO_InitStruct);
}

void HCSR04_TRIG_Send(void)
{
    HCSR04_TRIG_Hight;
    Delay_Us(15);
    HCSR04_TRIG_Low;
}


static void GENERAL_TIMx_GPIO_Config(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    GENERAL_TIMx_CH3_CLK_FUN(GENERAL_TIMx_CH3_CLK,ENABLE);

    GPIO_InitStruct.GPIO_Pin = GENERAL_TIMx_CH3_PIN;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;

    GPIO_Init(GENERAL_TIMx_CH3_PORT,&GPIO_InitStruct);
}

//中断初始化
static void GENERAL_TIMx_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStruct;

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

    //设置中断通道
    NVIC_InitStruct.NVIC_IRQChannel = GENERAL_TIMx_IRQn;
    //设置子优先级
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
    //设置抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
    //中断通道使能
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStruct);
}

static void GENERAL_TIMx_Mode_Config(void)
{
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_ICInitTypeDef TIM_ICInitStruct;

    GENERAL_TIMx_CLK_FUN(GENERAL_TIMx_CLK,ENABLE);

    //初始化时基
    TIM_TimeBaseInitStruct.TIM_Prescaler = (72-1);
    TIM_TimeBaseInitStruct.TIM_Period = 0xFFFF;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
    
    TIM_TimeBaseInit(GENERAL_TIMx,&TIM_TimeBaseInitStruct);

    //初始化 IC
    TIM_ICInitStruct.TIM_Channel = GENERAL_TIMx_CHANNEL_x;
    TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInitStruct.TIM_ICFilter = 0;

    TIM_ICInit(GENERAL_TIMx,&TIM_ICInitStruct);

    //清楚更新中断标志
    TIM_ClearFlag(GENERAL_TIMx,TIM_FLAG_Update | TIM_FLAG_CC3);
    //中断初始化
    TIM_ITConfig(GENERAL_TIMx,TIM_FLAG_Update | TIM_FLAG_CC3,ENABLE);
    //使能TIM
    TIM_Cmd(GENERAL_TIMx,ENABLE);
}

void TIM_Config(void)
{
    GENERAL_TIMx_GPIO_Config();
    GENERAL_TIMx_NVIC_Config();
    GENERAL_TIMx_Mode_Config();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103

TIM2中断函数

详细过程参考野火例徎 32-TIM—高级定时器

//TIM2中断函数
void GENERAL_TIMx_IRQHandler(void)
{
  //判断是否超出Period   检测位为更新中断
  //若是更新,改变Capture_Period值
  if(TIM_GetITStatus(GENERAL_TIMx,TIM_IT_Update) != RESET)
  {
    TIM_ICUserValueStruct.Capture_Period++;
    //清除中断等待
    TIM_ClearITPendingBit(GENERAL_TIMx,TIM_IT_Update);
  }
  //捕获边沿
  if(TIM_GetITStatus(GENERAL_TIMx,TIM_IT_CC3) != RESET)
  {
    //表示第一次捕获  清除CCR
    if(TIM_ICUserValueStruct.Capture_StartFlag == 0)
    {
      
      TIM_SetCounter(GENERAL_TIMx,0);              //从0开始计数
     TIM_ICUserValueStruct.Capture_CcrValue = 0;  //捕获值为0 
     // 自动重装载寄存器更新标志清0
			TIM_ICUserValueStruct.Capture_Period = 0;
      //改变捕获极性
      TIM_OC3PolarityConfig(GENERAL_TIMx,TIM_ICPolarity_Falling);
      TIM_ICUserValueStruct.Capture_StartFlag = 1;
    }
    //第二次捕获
    else
    {
      //得到CCR的值
      TIM_ICUserValueStruct.Capture_CcrValue = TIM_GetCapture3(GENERAL_TIMx);
      //改变捕获极性
      TIM_OC3PolarityConfig(GENERAL_TIMx,TIM_ICPolarity_Rising);
      //改变标志
      TIM_ICUserValueStruct.Capture_StartFlag = 0;
      TIM_ICUserValueStruct.Capture_FinishFlag = 1;
    }
    TIM_ClearITPendingBit (GENERAL_TIMx,TIM_IT_CC3);	
  }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

在这里插入图片描述

在这里插入图片描述

delay函数

#include "bsp_delay.h"

void Delay_Us( __IO uint32_t us)
{
    uint32_t i;
    SysTick_Config(SystemCoreClock/1000000);
    for (i=0; i<us; i++) 
    {

    // 当计数器的值减小到 0 的时候,CRTL 寄存器的位 16 会置 1

    while ( !((SysTick->CTRL)&(1<<16)) );

    }

    // 关闭 SysTick 定时器

    SysTick->CTRL &=~SysTick_CTRL_ENABLE_Msk;

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

main.c

/*
	按下 K1 启动测量
*/
#include"bsp_HCSR04.h"
#include"bsp_usart.h"
#include"bsp_key.h"

int main()
{
	uint32_t time;
	
	// TIM 计数器的驱动时钟
	uint32_t TIM_PscCLK = 72000000 / (71+1);
	float d = 0;

	USART_Config();
	HCSR04_GPIO_Config();
	TIM_Config();
	KEY_GPIO_Config();
	
	printf("\rHC_SR04实验\n");
	
	while (1)
	{
		if(Key_Scan(KEY1_GPIO_PORT,KEY1_GPIO_PIN)== KEY_ON)
			HCSR04_TRIG_Send();
		if(TIM_ICUserValueStruct.Capture_FinishFlag == 1)
		{
			// 计算高电平时间的计数器的值
			time = TIM_ICUserValueStruct.Capture_Period * (0xFFFF+1) + (TIM_ICUserValueStruct.Capture_CcrValue+1);

			printf ( "\r\n测得高电平脉宽时间:%ld.%ld s\r\n",time/TIM_PscCLK,time%TIM_PscCLK );
			d = (float)time * 170 / 10000;
			printf("距离为:");
			Print_Float(d);

			TIM_ICUserValueStruct.Capture_FinishFlag = 0;			
		}		
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

上述部分代码移植了野火的例程代码

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

闽ICP备14008679号