1 #include <twr_hc_sr04.h>
2 #include <twr_system.h>
7 #define _TWR_HC_SR04_RESOLUTION 5
9 static void _twr_hc_sr04_task_interval(
void *param);
10 static void _twr_hc_sr04_task_notify(
void *param);
11 static void _twr_hc_sr04_tim2_iqr_handler(
void *param);
12 static void _twr_hc_sr04_tim3_iqr_handler(
void *param);
21 memset(
self, 0,
sizeof(*
self));
36 if (self->_echo == TWR_HC_SR04_ECHO_P5)
43 RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
49 TIM2->CCMR1 |= TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC1S_0;
52 TIM2->CCER |= 1 << TIM_CCER_CC2P_Pos;
55 TIM2->PSC = _TWR_HC_SR04_RESOLUTION * 32 - 1;
60 NVIC_EnableIRQ(TIM2_IRQn);
62 else if (self->_echo == TWR_HC_SR04_ECHO_P8)
69 RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
75 TIM3->CCMR2 |= TIM_CCMR2_CC4S_1 | TIM_CCMR2_CC3S_0;
78 TIM3->CCER |= 1 << TIM_CCER_CC4P_Pos;
81 TIM3->PSC = _TWR_HC_SR04_RESOLUTION * 32 - 1;
86 NVIC_EnableIRQ(TIM3_IRQn);
94 self->_event_handler = event_handler;
95 self->_event_param = event_param;
100 self->_update_interval = interval;
116 if (self->_measurement_active)
122 twr_system_pll_enable();
124 self->_measurement_active =
true;
126 self->_measurement_valid =
false;
130 if (self->_echo == TWR_HC_SR04_ECHO_P5)
133 TIM2->CCR3 = 250000 / _TWR_HC_SR04_RESOLUTION;
136 TIM2->EGR = TIM_EGR_UG;
139 TIM2->SR &= ~(TIM_SR_CC1OF | TIM_SR_CC2OF);
142 TIM2->SR &= ~(TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF);
145 TIM2->CR1 |= TIM_CR1_CEN;
148 TIM2->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E;
151 TIM2->DIER |= TIM_DIER_CC2IE | TIM_DIER_CC3IE;
153 else if (self->_echo == TWR_HC_SR04_ECHO_P8)
156 TIM3->CCR1 = 250000 / _TWR_HC_SR04_RESOLUTION;
159 TIM3->EGR = TIM_EGR_UG;
162 TIM3->SR &= ~(TIM_SR_CC4OF | TIM_SR_CC3OF);
165 TIM3->SR &= ~(TIM_SR_CC4IF | TIM_SR_CC3IF | TIM_SR_CC1IF);
168 TIM3->CR1 |= TIM_CR1_CEN;
171 TIM3->CCER |= TIM_CCER_CC4E | TIM_CCER_CC3E;
174 TIM3->DIER |= TIM_DIER_CC4IE | TIM_DIER_CC1IE;
192 if (!self->_measurement_valid)
199 *millimeter = _TWR_HC_SR04_RESOLUTION * (float) self->_echo_duration / 5.8;
204 static void _twr_hc_sr04_task_interval(
void *param)
213 static void _twr_hc_sr04_task_notify(
void *param)
218 twr_system_pll_disable();
220 self->_measurement_active =
false;
224 if (!self->_measurement_valid)
226 if (self->_event_handler != NULL)
231 else if (self->_event_handler != NULL)
237 static void _twr_hc_sr04_tim3_iqr_handler(
void *param)
242 TIM3->DIER &= ~(TIM_DIER_CC4IE | TIM_DIER_CC1IE);
245 TIM3->CCER &= ~(TIM_CCER_CC4E | TIM_CCER_CC3E);
248 TIM3->CR1 &= ~TIM_CR1_CEN;
251 if ((TIM3->SR & TIM_SR_CC1IF) == 0)
254 if ((TIM3->SR & TIM_SR_CC4OF) == 0 && (TIM3->SR & TIM_SR_CC3OF) == 0)
257 if ((TIM3->SR & TIM_SR_CC4IF) != 0)
260 uint16_t falling_capture = TIM3->CCR4;
263 if ((TIM3->SR & TIM_SR_CC3IF) != 0)
266 uint16_t rising_capture = TIM3->CCR3;
269 self->_echo_duration = falling_capture - rising_capture;
271 if (self->_echo_duration <= 30000 / _TWR_HC_SR04_RESOLUTION)
274 self->_measurement_valid =
true;
285 static void _twr_hc_sr04_tim2_iqr_handler(
void *param)
290 TIM2->DIER &= ~(TIM_DIER_CC2IE | TIM_DIER_CC3IE);
293 TIM2->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC2E);
296 TIM2->CR1 &= ~TIM_CR1_CEN;
299 if ((TIM2->SR & TIM_SR_CC3IF) == 0)
302 if ((TIM2->SR & TIM_SR_CC1OF) == 0 && (TIM2->SR & TIM_SR_CC2OF) == 0)
305 if ((TIM2->SR & TIM_SR_CC2IF) != 0)
308 uint16_t falling_capture = TIM2->CCR2;
311 if ((TIM2->SR & TIM_SR_CC1IF) != 0)
314 uint16_t rising_capture = TIM2->CCR1;
317 self->_echo_duration = falling_capture - rising_capture;
319 if (self->_echo_duration <= 30000 / _TWR_HC_SR04_RESOLUTION)
322 self->_measurement_valid =
true;
void twr_gpio_set_output(twr_gpio_channel_t channel, int state)
Set output state for GPIO channel.
void twr_gpio_init(twr_gpio_channel_t channel)
Initialize GPIO channel.
twr_gpio_channel_t
GPIO channels.
void twr_gpio_set_mode(twr_gpio_channel_t channel, twr_gpio_mode_t mode)
Set mode of operation for GPIO channel.
@ TWR_GPIO_MODE_OUTPUT
GPIO channel operates as output.
@ TWR_GPIO_MODE_ALTERNATE_2
GPIO channel operates in alternate mode AF2.
@ TWR_GPIO_MODE_ALTERNATE_5
GPIO channel operates in alternate mode AF5.
@ TWR_GPIO_P8
GPIO channel P8.
@ TWR_GPIO_P5
GPIO channel P5, A5, DAC1.
@ TWR_GPIO_P4
GPIO channel P4, A4, DAC0.
void twr_hc_sr04_init_sensor_module(twr_hc_sr04_t *self)
Initialize HC-SR04 for sensor module.
void twr_hc_sr04_set_update_interval(twr_hc_sr04_t *self, twr_tick_t interval)
Set measurement interval.
void twr_hc_sr04_init(twr_hc_sr04_t *self, twr_gpio_channel_t trig, twr_hc_sr04_echo_t echo)
Initialize HC-SR04.
struct twr_hc_sr04_t twr_hc_sr04_t
HC-SR04 instance.
bool twr_hc_sr04_measure(twr_hc_sr04_t *self)
Start measurement manually.
bool twr_hc_sr04_get_distance_millimeter(twr_hc_sr04_t *self, float *millimeter)
Get measured distance in millimeters.
void twr_hc_sr04_set_event_handler(twr_hc_sr04_t *self, void(*event_handler)(twr_hc_sr04_t *, twr_hc_sr04_event_t, void *), void *event_param)
Set callback function.
@ TWR_HC_SR04_EVENT_ERROR
Error event.
@ TWR_HC_SR04_EVENT_UPDATE
Update event.
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
void twr_scheduler_plan_now(twr_scheduler_task_id_t task_id)
Schedule specified task for immediate execution.
void twr_scheduler_plan_relative(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to tick relative from current spin.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
#define TWR_TICK_INFINITY
Maximum timestamp value.
uint64_t twr_tick_t
Timestamp data type.
void twr_timer_init(void)
Initialize timer.
void twr_timer_delay(uint16_t microseconds)
Relative delay.
void twr_timer_stop(void)
Stop timer.
void twr_timer_start(void)
Start timer.
bool twr_timer_set_irq_handler(TIM_TypeDef *tim, void(*irq_handler)(void *), void *irq_param)
Register timer IRQ handler.