Tip: After the article is written, the table of contents can be automatically generated. How to generate it can refer to the help document on the right
Article Directory
foreword
Some time ago, I ran into a lot of problems in a project about ultrasonic distance measurement through input capture mode. After I solved it, I had a lot of ideas and recorded some in the article.
1. Introduction to HC-SR04
There are usually two ultrasonic components on the ultrasonic sensor module, one for transmitting and one for receiving.
There are four pins on the board: VCC, GND, Trig (trigger), Echo (response).
Working voltage and current: 5V, 15mA. Special attention must be paid to the 5V power supply here. After the STlink is connected to 32, it cannot provide 5V voltage. The power supply must be connected to the STlink.
Sensing distance: 2~400cm
Sensing angle: not less than 15 degrees
The area of the object to be measured should not be less than 50 square centimeters and should be as flat as possible
Two, the code part
Principle introduction
Use TI1 as the input capture channel, and map the captured level to the two internal channels
Channel 1 is set as a rising edge trigger, and the value of CNT will be recorded into CCR1 at the moment of triggering. At the same time, set channel 1 trigger with slave mode, and set the slave mode to zero CNT
Channel 2 is set as a falling edge trigger, and the CNT will be recorded into CCR2 at the moment of triggering. Since the CNT has been set to zero when the rising edge is triggered, the value of CNT at this time is the duration of the high level.
sample code
IC.c
#include "stm32f10x.h" // Device header void IC_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//turn on the clock RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//drop down input mode GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA,&GPIO_InitStructure); TIM_InternalClockConfig(TIM3);//Use internal clock source to power Timer 3 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//Capture input without division TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//count up mode TIM_TimeBaseInitStructure.TIM_Period = 65536-1; //arr TIM_TimeBaseInitStructure.TIM_Prescaler = 72-1; //PSC TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure); //open channel 1 TIM_ICInitTypeDef TIM_ICInitStructure; TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //Enable capture channel 1 TIM_ICInitStructure.TIM_ICFilter = 0xF;//Filter out high frequency fluctuations TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;//rising trigger capture TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//no frequency division TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;//Direct channel input TIM_ICInit(TIM3,&TIM_ICInitStructure);//Initialize input capture as rising edge capture //open channel 2 TIM_ICInitStructure.TIM_Channel = TIM_Channel_2; //Enable capture channel 2 TIM_ICInitStructure.TIM_ICFilter = 0xF;//Filter out high frequency fluctuations TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;//Falling edge trigger capture TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;//no frequency division TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI;//Cross channel input TIM_ICInit(TIM3,&TIM_ICInitStructure);//Initialize input capture as falling edge capture //TIM_PWMIConfig(TIM3,&TIM_ICInitStructure); //Select trigger slave mode TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//trigger slave mode TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//Set to zeroing mode for CNT TIM_Cmd(TIM3,ENABLE); } uint32_t IC_GetHigttime(void) { return TIM_GetCapture2(TIM3); }
2.HC-SR04.c
#include "stm32f10x.h" #include "ic.h" #include "delay.h" #define Trig_High GPIO_SetBits(GPIOB,GPIO_Pin_7) #define Trig_Low GPIO_ResetBits(GPIOB,GPIO_Pin_7) u32 high_time; float istance; void HC_Sr04Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //Enable peripheral clock for GPIOB GPIO_InitTypeDef GPIO_InitStructure; //Define the structure GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Set GPIO port as push-pull output GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; //Set GPIO port 5 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //Set the GPIO port speed to 50Mhz GPIO_Init(GPIOB,&GPIO_InitStructure); GPIO_ResetBits(GPIOB,GPIO_Pin_7); //output low level Delay_us(15); //Delay 15 microseconds IC_Init(); } void HC_SR04GetDistance(void) { Trig_High; //output high level Delay_us(15); Trig_Low; //output low level high_time = IC_GetHigttime(); istance = high_time*0.17; }
Summarize
It needs to be reminded that after the timer is initialized, the introduction of the input channel must be initialized to the multiplexing push-pull mode if you want to output the load level