cancel
Showing results for 
Search instead for 
Did you mean: 

How to make a Manchester communication with a NUCLEO-L432KC ?

Loic1
Associate III

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!

1 ACCEPTED SOLUTION

Accepted Solutions

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

View solution in original post

11 REPLIES 11

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

Loic1
Associate III

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.

Loic1
Associate III

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

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.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Uwe Bonnes
Principal III

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.

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

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

Loic1
Associate III

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

Loic1
Associate III

Also, for people who might be interested, here's my Manchester transmitter (tested and working up to 125 kHz) using timer 16 interruptions for clock. Again, any return will be appreciated.

Best regards,

Loïc