I am generating varaiable Frequency and duty cycle PWM pulse using a master STM32F103C8T6 on PB4 pin (TIM3_CH1). The following shows my code:
TIM_HandleTypeDef htim3;
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
uint32_t prescaler;
uint32_t autoreload;
uint32_t pulse;
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) && !HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9))
{
prescaler = 9;
autoreload = 11999;
pulse = 2400;
__HAL_TIM_SET_PRESCALER(&htim3, prescaler);
__HAL_TIM_SET_AUTORELOAD(&htim3, autoreload);
TIM3->CCR1 = pulse;
}
else if(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9))
{
prescaler = 9;
autoreload = 11999;
pulse = 9600;
__HAL_TIM_SET_PRESCALER(&htim3, prescaler);
__HAL_TIM_SET_AUTORELOAD(&htim3, autoreload);
TIM3->CCR1 = pulse;
}
else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) && !HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9))
{
prescaler = 9;
autoreload = 5999;
pulse = 1200;
__HAL_TIM_SET_PRESCALER(&htim3, prescaler);
__HAL_TIM_SET_AUTORELOAD(&htim3, autoreload);
TIM3->CCR1 = pulse;
}
else if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) && HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_9))
{
prescaler = 9;
autoreload = 5999;
pulse = 4800;
__HAL_TIM_SET_PRESCALER(&htim3, prescaler);
__HAL_TIM_SET_AUTORELOAD(&htim3, autoreload);
TIM3->CCR1 = pulse;
}
else
{
prescaler = 9;
autoreload = 11999;
pulse = 1200;
__HAL_TIM_SET_PRESCALER(&htim3, prescaler);
__HAL_TIM_SET_AUTORELOAD(&htim3, autoreload);
TIM3->CCR1 = pulse;
}
}
I configured the TIM3 as follows:
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 10-1;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 0;
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_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
Then I connect this output pin of Master STM32 DIRECTLY to several Slaves STM32.
The slaves using PB4(TIM3_CH1) and PB5(TIM3_CH2) in input capture mode to read frequency and duty cycle of PWM pulse.
This is the code I am using for reading the frequency and duty cycle:
TIM_HandleTypeDef htim3;
uint32_t IC_Val1 = 0;
uint32_t IC_Val2 = 0;
uint32_t Difference = 0;
int Is_First_Captured = 0;
float duty;
float freq;
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim)
{
static uint32_t rising1 = 0, rising2 = 0, falling = 0;
static uint8_t firstCaptured = 0;
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1)
{
if (firstCaptured == 0)
{
rising1 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
firstCaptured = 1;
}
else
{
rising2 = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1);
uint32_t period = (rising2 >= rising1) ? (rising2 - rising1) : (0xFFFF - rising1 + rising2);
uint32_t high = (falling >= rising1) ? (falling - rising1) : (0xFFFF - rising1 + falling);
duty = ((float)high / period) * 100.0f;
freq = (float)SystemCoreClock / (htim->Instance->PSC + 1) / period;
// printf("Freq: %.2f Hz, Duty: %.2f%%\r\n", freq, duty);
firstCaptured = 0;
}
}
if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2)
{
falling = HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_2);
}
}
int main(void)
{
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_1);
HAL_TIM_IC_Start_IT(&htim3, TIM_CHANNEL_2);
while (1)
{
if(freq > 95 && freq < 105)
{
if(duty > 15 && duty < 25)
{
//do something
}
else if(duty > 75 && duty < 85)
{
//do something
}
}
else if(freq > 195 && freq < 205)
{
if(duty > 15 && duty < 25)
{
//do something
}
else if(duty > 75 && duty < 85)
{
//do something
}
}
}
}
And I configured channel 1 and 2 of TIM3 of each slave as follows:
static void MX_TIM3_Init(void)
{
/* USER CODE BEGIN TIM3_Init 0 */
/* USER CODE END TIM3_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_IC_InitTypeDef sConfigIC = {0};
/* USER CODE BEGIN TIM3_Init 1 */
/* USER CODE END TIM3_Init 1 */
htim3.Instance = TIM3;
htim3.Init.Prescaler = 12-1;
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();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != 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();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
}
Everything works fine when I connect only one Slave to Master but when I connect more than one slave, none of slaves does not work correctly and do not read the frequency and duty cycle correctly.
I think the software is correct but in the wiring I have to use a signal conditioning circuit instead of connecting PB4 of Master directly to PB4 and PB5 of slaves.
I attached the schematic of my circuit.
What do I have to do for solving this problem? Is there any signal conditioning circuit to fix this issue?
