2025-05-30 4:47 AM
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.
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);
}
}
2025-05-30 9:42 AM
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.