cancel
Showing results for 
Search instead for 
Did you mean: 

Square wave FSK issue using PWM ouput

mikeyd0407
Associate

Hi All,

I am trying to impliment a frequency shift keying (FSK) routine to represent a each bit of a byte as FSK.

My routine is kind of working (see the IRQ for TIM3 below). My FSK is :

Bit 0 & Start : 3600Hz 

Bit 1 & Stop : 1200Hz

This ensures that timing is alway 833.3us, and transisitons only occur at the end of a full cycle (avoiding glitches).

In this example pictured I am sending a 'U' to be encoded (this has a binary value of '0b01010101') so its easy to see the FSK changes.

What I've noticed is that when I change from bit from 0 (3600Hz) to 1 (1200Hz) the output polarity keeps the previous polarity level. This makes it look like last pulse of the 3600Hz waveform is streatched.Screenshot 2025-05-30 124318.jpg

My question is, How can I change the polarity of the PWM ouput on each sucessive bit?

Here is my IRQ code:

 

extern volatile uint8_t transmitting;
extern volatile uint8_t transmit_data;
extern volatile uint8_t bit_count;
extern volatile uint8_t bit_index;
extern volatile uint8_t current_bit;
extern volatile uint8_t Finished_TX; //MD


// Working FSK with Start/Stop bits - To be tested
void TIM3_IRQHandler(void) {
    if (__HAL_TIM_GET_FLAG(&htim3, TIM_FLAG_UPDATE) != RESET) {
        __HAL_TIM_CLEAR_IT(&htim3, TIM_IT_UPDATE);  // Ensure interrupt flag is cleared
        HAL_TIM_IRQHandler(&htim3);  // Keep HAL processing

        if (transmitting)
        {
        	//Toggle pin D07
        	HAL_GPIO_TogglePin(GPIOD, GPIO_PIN_7);

            bit_count--;  // Reduce cycle count

            if (bit_count == 0)
            {  // Time to switch to next bit
                if (bit_index == -1)
                {  // Start bit (Before data transmission)
                    bit_count = 3;  // 3 cycles @ 3600Hz
                    ///bit_count = 4;  // 3 cycles @ 3600Hz
                    htim3.Instance->ARR = (48000000 / 3600) - 1;
                    htim3.Instance->CCR1 = (htim3.Instance->ARR * 50) / 100;
                    //htim3.Instance->CCR1 = (htim3.Instance->ARR * 57) / 100;

                    bit_index++;  // Move to first data bit
                }
                else if (bit_index < 8)
                {  // Process next bit in character
                    current_bit = (transmit_data >> bit_index) & 0x01;
                    bit_count = current_bit ? 1 : 3;  // '1' → 1200Hz (1 cycle), '0' → 3600Hz (3 cycles)
                    ///bit_count = current_bit ? 1 : 4;  // '1' → 1200Hz (1 cycle), '0' → 3600Hz (3 cycles)




                    htim3.Instance->ARR = current_bit ? (48000000 / 1200) - 1 : (48000000 / 3600) - 1;
                    htim3.Instance->CCR1 = (htim3.Instance->ARR * 50) / 100;
                    //htim3.Instance->CCR1 = (htim3.Instance->ARR * 57) / 100;

                    bit_index++;  // Move to next bit
                }
                else
                {  // Stop bit handling after last data bit
                    bit_count = 1;
                    htim3.Instance->ARR = (48000000 / 1200) - 1;  // Stop bit at 1200Hz
                    htim3.Instance->CCR1 = (htim3.Instance->ARR * 50) / 100;
                    //htim3.Instance->CCR1 = (htim3.Instance->ARR * 57) / 100;

                    transmitting = 0;  // Ensure transmission reset
                    bit_index = -1;  // Prepare for next transmission
                    Finished_TX = 1;

                    printf("Transmission complete!\n");

                    // Force timer update to ensure it stays at 1200Hz idle
                    __HAL_TIM_SET_AUTORELOAD(&htim3, htim3.Instance->ARR);
                    __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
                }
            }
        }

        // Ensure TIM3 interrupts remain enabled
        __HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
    }
}
1 REPLY 1
Sarra.S
ST Employee

Hello @mikeyd0407

This behavior is likely due to that the timer's output compare does not reset its phase or polarity when the frequency (ARR value) is updated, try forcing the timer to reset its counter by adding this line in your IRQ handler:

htim3.Instance->ARR = current_bit ? (48000000 / 1200) - 1 : (48000000 / 3600) - 1;
htim3.Instance->CCR1 = (htim3.Instance->ARR * 50) / 100;
htim3.Instance->CNT = 0;  // Reset the timer counter to zero

Hope that helps! 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.