当前位置:网站首页>STM32 - general timer control ultrasonic sensor hcsr04
STM32 - general timer control ultrasonic sensor hcsr04
2022-07-21 19:49:00 【chfens】
HCSR-04 Introduce
HC-SR04 Ultrasonic ranging module can provide 2cm-400cm Non contact distance sensing function of , measuring
Non contact distance sensing function with high distance accuracy , Ranging accuracy can be as high as 3mm ; The module includes an ultrasonic transmitter 、 Receiver and control circuit .
Online materials say that the accuracy of this module is very high , But I actually feel very general , I use 89C52 and STM32F103C8T6 Have written the procedures of ranging respectively , But the range of accurate measurement is 100cm within , The specific reason is not detailed .
working principle
Use IO Trigger port , First of all Trig Set the high level at least 10us, The module will launch 8 individual 40KHz Pulse square wave , after Trig Set low level , from Echo Receive square wave , Then calculate the distance according to the duration of the reverberation level , The principle is very simple .
Procedural thinking
Just put one IO Mouth configuration Push pull output As Trig, One IO Mouth configuration Drop down input As Echo, Because when Echo The received echo signal will be set from low level to high level , So the default setting Echo Low level . distance = High level time * The speed of sound (340M/S)/2;
First use SysTick Software delay control Trig Send out high level , Then wait for the echo signal , When Echo Receive signal , That is, start the timer , But our program runs in the timer , Use the same timer TIM2, Clear the timer after receiving the signal . Then get the level duration , Calculate the distance and reset the timer again , And turn on the timer , Only when the timer is interrupted next time can it be triggered normally .
Code implementation
#include "HCSR04.h"
#include "stm32f10x.h" // Device header
#include "Usart.h"
#include "Buzzer.h"
int HCSR04_Distance1;
int HCSR04_Distance2;
#define RCC_HCSR04 RCC_APB2Periph_GPIOB
#define GPIO_HCSR04_Trig GPIOB
#define PIN_HCSR04_Trig1 GPIO_Pin_8
#define PIN_HCSR04_Trig2 GPIO_Pin_5
#define GPIO_HCSR04_Echo GPIOB
#define PIN_HCSR04_Echo1 GPIO_Pin_9
#define PIN_HCSR04_Echo2 GPIO_Pin_6
void HCSR04_Delay_us(uint32_t xus)
{
SysTick->LOAD = 72 * xus; // Set the timer reload value
SysTick->VAL = 0x00; // Zero clearing
SysTick->CTRL = 0x00000005; // Set the clock source to HCLK, Start timer
while(!(SysTick->CTRL & 0x00010000)); // Wait to count to 0
SysTick->CTRL = 0x00000004; // off timer
}
void HCSR04_Delay_ms(uint32_t xms)
{
while(xms--)
{
HCSR04_Delay_us(1000);
}
}
Here because of the need , I set up two ultrasonic sensors .
First, the macro defines the pin , Then define two distance variables , And initialization Systick Software delay function .
void GPIO_HCSR04Init()
{
RCC_APB2PeriphClockCmd(RCC_HCSR04, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = PIN_HCSR04_Trig1 | PIN_HCSR04_Trig2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIO_HCSR04_Trig,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = PIN_HCSR04_Echo1 | PIN_HCSR04_Echo2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIO_HCSR04_Echo,&GPIO_InitStructure);
}
Initialize the pins of the two functions respectively , One is push-pull output , One is drop-down input .
void TIM_HCSR04Init()
{
// Universal timer 2 3 4,APB1
//TIM2 The passage of 1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_InternalClockConfig(TIM2);// Select internal clock
TIM_TimeBaseInitTypeDef timBaseInit;
TIM_TimeBaseStructInit(&timBaseInit);
timBaseInit.TIM_ClockDivision = TIM_CKD_DIV1;
timBaseInit.TIM_CounterMode = TIM_CounterMode_Up;
timBaseInit.TIM_RepetitionCounter = 0;
timBaseInit.TIM_Period = 10000 - 1;
timBaseInit.TIM_Prescaler = 7200 - 1;
//7200 frequency division , remember 10000 The next is 1 second
TIM_TimeBaseInit(TIM2,&timBaseInit);
TIM_ClearFlag(TIM2,TIM_FLAG_Update);// Manually clear the update interrupt flag bit , Avoid entering interrupt automatically after initialization
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);// Can make TIM2 Update interrupt
// To configure NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef nvic_struct;
nvic_struct.NVIC_IRQChannel = TIM2_IRQn;
nvic_struct.NVIC_IRQChannelCmd = ENABLE;
nvic_struct.NVIC_IRQChannelPreemptionPriority = 1;
nvic_struct.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&nvic_struct);
TIM_Cmd(TIM2,ENABLE);
}
First enable the timer , Then configure the time base unit , take 72MHz7200 frequency division , Every time you add one to the counter, you get 1/10000s, remember 10000 Once is a second . After configuration NVIC passageway , Start timer interrupt , Choose the priority randomly .
void StartMode1()
{
GPIO_ResetBits(GPIO_HCSR04_Trig,PIN_HCSR04_Trig1);// Pre pull down
GPIO_SetBits(GPIO_HCSR04_Trig,PIN_HCSR04_Trig1);
HCSR04_Delay_us(20);
GPIO_ResetBits(GPIO_HCSR04_Trig,PIN_HCSR04_Trig1);//OK
}
void StartMode2()
{
GPIO_ResetBits(GPIO_HCSR04_Trig,PIN_HCSR04_Trig2);// Pre pull down
GPIO_SetBits(GPIO_HCSR04_Trig,PIN_HCSR04_Trig2);
HCSR04_Delay_us(20);
GPIO_ResetBits(GPIO_HCSR04_Trig,PIN_HCSR04_Trig2);//OK
}
Here is Trig Trigger function
void HCSR04Init()
{
GPIO_HCSR04Init();
TIM_HCSR04Init();
}
// Integrate a function , be used for main For function initialization
void HCSR04_GetDistance1()
{
unsigned int time = 0;
TIM_SetCounter(TIM2,0x0000);
StartMode1();
while(GPIO_ReadInputDataBit(GPIO_HCSR04_Echo , PIN_HCSR04_Echo1 ) == 0);
TIM_Cmd(TIM2,ENABLE); //Usart_SendStr("TIM2 ON ");
while(GPIO_ReadInputDataBit(GPIO_HCSR04_Echo , PIN_HCSR04_Echo1 ) == 1);
TIM_Cmd(TIM2,DISABLE); //Usart_SendStr("TIM2 OFF ");
// Company cm
//v = 340m/s = 34000cm/s = 34000cm/10^6us = 0.034cm/us
//s = vt/2
time = TIM_GetCounter(TIM2);
HCSR04_Distance1 = (int)time * 340 / 100 / 2;//cm
TIM_SetCounter(TIM2,0x0000);
}
void HCSR04_GetDistance2()
{
unsigned int time = 0;
TIM_SetCounter(TIM2,0x0000);
StartMode2();
while(GPIO_ReadInputDataBit(GPIO_HCSR04_Echo , PIN_HCSR04_Echo2 ) == 0);
TIM_Cmd(TIM2,ENABLE); //Usart_SendStr("TIM2 ON ");
while(GPIO_ReadInputDataBit(GPIO_HCSR04_Echo , PIN_HCSR04_Echo2 ) == 1);
TIM_Cmd(TIM2,DISABLE); //Usart_SendStr("TIM2 OFF ");
// Company cm
//v = 340m/s = 34000cm/s = 34000cm/10^6us = 0.034cm/us
//s = vt/2
time = TIM_GetCounter(TIM2);
HCSR04_Distance2 = (int)time * 340 / 100 / 2;//cm
TIM_SetCounter(TIM2,0x0000);
}
Here is the function of distance , Here's a point to Particular attention , Don't mix Software delay time The operation of , For example, serial port printing , This bug I've been looking for it for a long time ,Echo No echo signal has been received , So I try to use serial port printing to find out where the program is stuck , Just like in the program TIM2 ON and TIM2 OFF like that , The result is only TIM2 ON, Can't run OFF It's about . After that, I annotated all the prints at once , Leaving only the printing distance , The result was success ... Because of this bug I searched for hours ...o(╥﹏╥)o
void TIM2_IRQHandler()
{
static int LightADTime = 0;// control LightAD Test interval
if(TIM_GetITStatus(TIM2,TIM_IT_Update) == 1)
{
LightADTime++;
if(LightADTime == 10)//
{
// Here is to cooperate with photosensitive sensor AD Conversion and watchdog interrupt program , It will be added later
LightADTime = 0;
}
TIM_SetCounter(TIM2,0x0000);
HCSR04_GetDistance1();
HCSR04_GetDistance2();
if((HCSR04_Distance1 <= 20 || HCSR04_Distance1 >= 1000) )
{
BuzzerOn();
}
else if((HCSR04_Distance2 <= 80 || HCSR04_Distance2 >= 1000) )
{
BuzzerOn();
}
else BuzzerOff();
TIM_Cmd(TIM2,ENABLE);
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
Timer interrupt function , Remember to first judge whether you enter the timer interrupt channel , If it is , After the interrupt function is executed, put The flag bit software is set to zero , Otherwise it will keep cycling , Couldn't go out .
BuzzerOn Is the function of controlling the active buzzer , Buzzer is triggered by low level .
Conclusion
The point to pay attention to is not to perform operations with a certain length of time when calculating the distance , Otherwise, there will be no echo signal , Even waste you hours looking for bug.
There are many blogs that haven't been written ..
If you know why my program accuracy is not high, please tell me in the comment area (*ω*)
边栏推荐
- NXP i.MX 8M Mini 开发板规格参数,四核ARM Cortex-A53 + ARM Cortex-M4
- Quanzhi a40i development board hardware specification - 100% domestic + industrial level scheme (Part 2)
- Assertion failed: inputs.at(2).is_weights
- Jenkins怎么发邮件,自动化大老手把手教你
- Support vector machine (understanding, derivation, MATLAB examples)
- 信号处理系统综合设计-最小阶数的IIR数字高通滤波器
- Sequence model (I) - cyclic sequence model
- Assertion failed: inputs.at(2).is_weights
- 为什么要写单元测试?如何写单元测试?
- 【transformer】ViT
猜你喜欢
ctfshow MengXIn misc1
MySQL (2)
Quanzhi a40i development board hardware specification - 100% domestic + industrial level scheme (Part 2)
从平面设计转行软件测试,喜提11K+13薪,回头看看我很幸运
(1) Analysis of Damon database model
笔试强训第19天
数据中台、BI业务访谈(二):组织架构梳理的坑
Trivy source code analysis (scanning the vulnerability information in the image)
iwemeta:史玉柱的黄金酱酒:贴牌的代工厂都被关停了,谁在生产?
Stop learning! These five programming languages are about to die out
随机推荐
Trivy source code analysis (scanning the vulnerability information in the image)
为什么要写单元测试?如何写单元测试?
How Jenkins sends e-mail? The automation veteran will teach you
342 NLP open source datasets in Chinese and English are shared
Electromagnetic field and electromagnetic wave experiment three familiar with the application of Mathematica software in the field of electromagnetic field
电磁场与电磁波实验二 熟悉Matlab PDEtool在二维电磁问题的应用
How to remove Baidu advertisements
Stop learning! These five programming languages are about to die out
Click the model mode box and the other areas will not disappear except the mode box
STM32——定位模块ATGM336H,数据解析,提取经纬度
Content with element type "resultmap" must match "(constructor?, id*, result*, association*, collection*, discriminato?) “
Common tools and test methods for interface testing
Typescript basic learning notes
22张图带你深入剖析前缀、中缀、后缀表达式以及表达式求值
常用测试用例设计方法之边界值分析法
input: dynamic input is missing dimensions in profile
Unity ECS 测试Demo
input: kMAX dimensions in profile 0 are [2,3,128,128] but input has static dimensions [1,3,128,128]
Sequence model (I) - cyclic sequence model
Jenkins怎么发邮件,自动化大老手把手教你