2022-05-05 02:38 AM
Hello,
I would like to encode/send and decode/receive data using Manchester communication protocol (per G.E. Thomas) between 1 and 100 kbps with a NUCLEO-L432KC. I have read many topics with multiple solutions but I'm a beginner and I'm quite confused.
I'm looking for a simple and proper way to do it, without external chip. Maybe setting up a timer as counter with an interrupt should be a good idea? I would be pleased to get code examples.
Thanks in advance!
Solved! Go to Solution.
2022-05-05 03:47 AM
Transmitter is relatively easy, as you are under control of the clock - simply perform encoding and transmit using either a timer interrupt, or e.g. SPI.
Receiver is relatively hard. One way to do it is to use input capture on both edges, and perform software decoding in the ISR based on the captured values.
You may want to start with setting up the input capture, in ISR storing the data to an array, and then looking at the content of that array try to decode it by hand.
JW
2022-05-05 03:47 AM
Transmitter is relatively easy, as you are under control of the clock - simply perform encoding and transmit using either a timer interrupt, or e.g. SPI.
Receiver is relatively hard. One way to do it is to use input capture on both edges, and perform software decoding in the ISR based on the captured values.
You may want to start with setting up the input capture, in ISR storing the data to an array, and then looking at the content of that array try to decode it by hand.
JW
2022-05-05 04:42 AM
Hi @Community member !
Thank you for your answer! I'm looking how to do this and trying to do it by myself. It's the first time I'm programming a Nucleo in the STM32CubeIDE so I'll probably reply back for learning more.
2022-05-20 05:03 AM
Hi @Community member !
I managed to make a transmitter, and now I'm trying to make a receiver.
The receiver is using the timer 2 in input capture direct mode. It detects the 2 first rising edge of my Manchester signal to calculate it's frequency. Based on this frequency, I'm starting the timer 16 to trigger a signal state reading on each bit.
For now I'm not reading any signal state, just watching if the timer 16 triggers at the right moment. At low signal frequency (below 10 kHz), it works perfectly. At higher frequency however, it's not synced with the signal bits anymore. That's because the timer 16 takes 18 µs to trigger, between the 2nd rising edge and the state reading.
What could I do to reduce this time? Maybe I should try another way to do it? My code is here attached.
/* USER CODE BEGIN 0 */
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef* htim)
{
if(gu8_State == IDLE)
{
gu32_T1 = TIM2->CCR1;
gu16_TIM2_OVC = 0;
gu8_State = DONE;
}
else if(gu8_State == DONE)
{
gu32_T2 = TIM2->CCR1;
// Wait for 3/4 of period before measuring signal state
DelayCounterPeriod = (uint32_t)((gu32_T2 + (gu16_TIM2_OVC * 65536)) - gu32_T1) / PSC * 0.75;
__HAL_TIM_SET_AUTORELOAD(&htim16, DelayCounterPeriod - 1);
HAL_TIM_Base_Start_IT(&htim16);
HAL_TIM_Base_Stop_IT(&htim2);
HAL_TIM_IC_Stop_IT(&htim2, TIM_CHANNEL_1);
}
}
// Callback: timer has rolled over
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
// Check which version of the timer triggered this callback and toggle LED
if (htim == &htim16)
{
if(callbackCount == 1)
{
// Change timer 16 Counter period for signal state detection
SignalCounterPeriod = DelayCounterPeriod / 0.75;
__HAL_TIM_SET_AUTORELOAD(&htim16, SignalCounterPeriod - 1);
}
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
callbackCount++;
}
if(htim == &htim2)
{
gu16_TIM2_OVC++;
}
}
/* USER CODE END 0 */
Best regards,
Loïc
2022-05-20 06:06 AM
General purpose MCU are not well suited to these tasks, especially as rates increase and you drive the interrupt system into saturation. The ceiling there relates to how convoluted your handler code is.
The route to higher rates would be to decimate the interrupt loading, and using DMA to capture event time stamps, and reconstruct more bits in each DMA interrupt.
If you're new to this type of problem solving, you'll need to start by getting a functional understanding of the capabilities and modes of the timers, and then thinking about how those might be applied or scaled for speed.
2022-05-21 12:09 PM
The bl*ckm*g*c debug probe https://github.com/bl*ckm*g*c-debug/bl*ckm*gic.git has optimized code to decode manchester swo in src/platforms/stm32/traceswo.c, based on libopencm3.
2022-05-23 12:47 AM
Hi @Community member !
Thank you for the information, indeed that makes sense. I was heading for doing it using Timer 2 input capture mode with DMA. I'll let you know if I manage to make it work.
Best regards,
Loïc
2022-05-23 12:49 AM
Hi @Uwe Bonnes !
Thanks for the help. However the link is dead and I didn't found what your are talking about. Do you have new link to it?
Best regards,
Loïc
2022-05-23 04:28 AM
So I managed to make a Manchester receiver (tested and working from 2 to 100 kHz) using input capture with DMA. If you want to take a look at it to see if I was supposed to do it this way, or if something could be improved, you can find my code attached. Any return will be appreciated.
Best regards,
Loïc
2022-05-23 04:36 AM