2025-03-04 4:57 AM - last edited on 2025-03-04 5:22 AM by mƎALLEm
Hi, I tried to read signal from ultrasonic parking unit by capturing PWM input. Signal has one start pulse 530 Hz width (1.87 ms) and a sequence with 0 and 1 (9.942 kHz and 4,97 kHz) period between pulses sequences is about 193 ms.
I use STM32F103 blue pill board with external 8Mhz quartz oscillator.
My clock config:
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
}
My Timer configuration:
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_SlaveConfigTypeDef sSlaveConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 65535;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_IC_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV1;
sSlaveConfig.TriggerFilter = 0;
if (HAL_TIM_SlaveConfigSynchro(&htim3, &sSlaveConfig) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
sConfigIC.ICFilter = 0;
if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
/* USER CODE END TIM3_Init 2 */
}
Capture callback:
#define RADAR_FRONT_START_PULSE 18000 // Hz
#define RADAR_REAR_START_PULSE 19000 // Hz
#define RADAR_HIGH_PULSE 5000 // Hz
#define RADAR_LOW_PULSE 10000 // Hz
#define RADAR_PULSE_DEVIATION 2000 // Hz
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
if (!CHECK_RADAR_ON) return;
if(htim -> Instance == TIM3 && htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
HandleRearRadarPulses(htim);
}
if(htim -> Instance == TIM2 && htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
HandleFrontRadarPulses(htim);
}
}
void HandleRearRadarPulses(TIM_HandleTypeDef *htim)
{
static int8_t index = 32;
static int8_t start_cpatured = 0;
static uint32_t captured_pulses = 0;
uint16_t packet = 0;
uint32_t pulse = 0;
pulse = SystemCoreClock / (HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2));
if (IS_REAR_START_PULSE(pulse))
{
start_cpatured = 1;
index = 32;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
return;
}
if (start_cpatured){
if (IS_HIGH_PULSE(pulse)) captured_pulses |= (1 << index);
if (index == 0) {
rear_min_distance = 255;
for (int i=0; i<4; i+=1) {
packet = (captured_pulses & (255 << (RADAR_PACKET_LENGTH * i))) >> (RADAR_PACKET_LENGTH * i);
rear_sensors[i] = packet;
if (packet < rear_min_distance) rear_min_distance = packet;
}
captured_pulses = 0;
start_cpatured = 0;
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
}
index --;
}
}
Main problem is to catch start pulse on this config. To work as expected I used to reduce width of start pulse from 530 Hz to 19 kHz to be able to catch it. For example, using timer on black pill STM32F4 with 32 bit AutoRload Register start pulse was captured with 530 Hz.
To detect correct package detection I also set pin state once start pulse was captured and reset after complete package reception.
Is it possible to catch such kind of signals with 16 bit Counter Period (AutoRload Register) with correct start pulse width (530 Hz) or problem with different thing?
If I correctly understand that first pulse tried to capture 2 times because of its width 1.87 ms, as timer capture period is about 0.9 ms (Counter_Period / F clock -> 65535 / 72 Mhz = 0.9 ms).
Thanks in advice!
2025-03-04 6:29 AM
Hi,
>Is it possible to catch such kind of signals with 16 bit Counter Period (AutoRload Register) with correct start pulse width (530 Hz) or problem with different thing?
Yes, no problem. Just use prescaler, maybe :71 , to set the timer to count on 1us clock.
Then 65k gives a range up to 65ms to captureand still good resolution to check 100 or 200 us long pulse coming.