generated from Template/H563ZI-HAL-CMake-Template
90 lines
2.5 KiB
C++
90 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include "../Helper/delay_helper.h"
|
|
#include "stm32h563xx.h"
|
|
#include "stm32h5xx_hal_tim.h"
|
|
#include <cstdint>
|
|
#include <stdexcept>
|
|
|
|
#include "../Helper/gpio_helper.hpp"
|
|
#include "../Helper/task_helper.hpp"
|
|
|
|
class Ultrasonic {
|
|
public:
|
|
Ultrasonic(GPIO_TypeDef* gpio, uint16_t pin, TIM_HandleTypeDef* timer, uint32_t channel)
|
|
: Ultrasonic({gpio, pin}, timer, channel) {}
|
|
|
|
Ultrasonic(const GpioHelper::Gpio& trigger, TIM_HandleTypeDef* timer, uint32_t channel)
|
|
: trigger(trigger), timer(timer), channel(channel) {
|
|
captureFlag = GetCaptureFlag(channel);
|
|
}
|
|
|
|
double GetDistance(uint32_t time = 1) {
|
|
double distance = 0;
|
|
for (uint32_t cnt = 0; cnt < time; ++cnt) {
|
|
Trigger();
|
|
auto echoTime = MeasureEchoTime();
|
|
distance += CalculateDistance(echoTime);
|
|
}
|
|
return distance / time;
|
|
}
|
|
|
|
private:
|
|
constexpr static uint32_t kTimeout = 100;
|
|
|
|
GpioHelper::Gpio trigger;
|
|
TIM_HandleTypeDef* timer;
|
|
uint32_t channel;
|
|
uint32_t captureFlag;
|
|
|
|
void Trigger() {
|
|
trigger.Set();
|
|
DelayUs(10);
|
|
trigger.Reset();
|
|
}
|
|
|
|
double MeasureEchoTime() {
|
|
timer->Instance->CNT = 0;
|
|
uint32_t data[2];
|
|
HAL_TIM_IC_Start(timer, channel);
|
|
try {
|
|
for (auto& value : data) {
|
|
TaskHelper::WaitFor(
|
|
[&]() {
|
|
if (__HAL_TIM_GET_FLAG(timer, captureFlag)) {
|
|
__HAL_TIM_CLEAR_FLAG(timer, captureFlag);
|
|
value = HAL_TIM_ReadCapturedValue(timer, channel);
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
kTimeout);
|
|
}
|
|
HAL_TIM_IC_Stop(timer, channel);
|
|
return (data[1] - data[0]) / 250.0;
|
|
} catch (const std::exception& e) {
|
|
HAL_TIM_IC_Stop(timer, channel);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
[[nodiscard]] static double CalculateDistance(double echoTime) {
|
|
return (echoTime * 0.0343) / 2.0;
|
|
}
|
|
|
|
static uint32_t GetCaptureFlag(uint32_t channel) {
|
|
switch (channel) {
|
|
case TIM_CHANNEL_1:
|
|
return TIM_SR_CC1IF;
|
|
case TIM_CHANNEL_2:
|
|
return TIM_SR_CC2IF;
|
|
case TIM_CHANNEL_3:
|
|
return TIM_SR_CC3IF;
|
|
case TIM_CHANNEL_4:
|
|
return TIM_SR_CC4IF;
|
|
default:
|
|
throw std::invalid_argument("Invalid timer channel");
|
|
}
|
|
}
|
|
};
|