0
\$\begingroup\$

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.

Schematic

What do I have to do for solving this problem? Is there any signal conditioning circuit to fix this issue?

\$\endgroup\$
5
  • 1
    \$\begingroup\$ We cannot know what the problem is. You are not showing any code, any schematics, or how many meters of wire there is between MCUs, or if they are on the same PCB right next to each other. Can you explain the experiment in a way that someone else would be able to replicate your setup to recreate the issue? \$\endgroup\$ Commented Oct 14 at 12:57
  • \$\begingroup\$ That's not a schematic, that's a block diagram. Are those squares on your block diagram just MCUs on same PCB, or some separate boards wired together? We still don't have enough info to solve the issue, or even suggest a signal conditioning circuit, or if it would even help at all. \$\endgroup\$ Commented Oct 15 at 6:14
  • \$\begingroup\$ each STM32 located on the separate boards and connect togethter with wires. my schematic exactly same as my block diagram. i wired the master and slaves according to the above block diagram only with some wires. the distance between the boards are not to long. their distance is about 20cm. \$\endgroup\$ Commented Oct 15 at 17:16
  • 1
    \$\begingroup\$ Not related to the problem, but you should declare freq and duty as volatile and make a copy of them in the main loop before you test the values. The original values may change in the middle of one of these if conditions. \$\endgroup\$ Commented Oct 16 at 17:28
  • \$\begingroup\$ "none of slaves does not work correctly" everything as designed?! Use negation sparingly. Why use "[variable frequency] and duty cycle PWM" to communicate what? \$\endgroup\$ Commented Oct 17 at 10:46

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.