Generating four synchronised Signals with Timer, PWM, and DMA (XY2-100)
Hi everyone,
I'm encountering a problem with PWM generation using timers and DMA on the STM32F723.
I've worked through some examples from ST and Controllerstech, such as this one:
https://controllerstech.com/pwm-with-dma-in-stm32/
I managed to get this example running, but now I need to develop something more advanced.
We want to develop a protocol called XY2-100. Here's a description of the protocol:
https://dvd.ilphotonics.com/Ray-Motion%20-%20galvanometers%20-%201D-2D-3D%20scanners/Motion%20Control%20-%20Optomechanics/Interface%20XY2-100.pdf
The protocol consists of four signals: Clock, ChannelX, ChannelY, Sync.
- The data of each axis consist of 20-bit words.The first 3 bits are used as a control word(C2-C0).The next 16 bits are data information(D15-D0, offset binary) and the last bit is a parity bit(P, even parity).
- The clock signal runs at a frequency of 2 MHz.When it goes high,the data bit changes.When it goes low,the data bit is sampled by the deflection system.
- The transfer of data is synchronised using a synchronisation signal.The SYNC bit goes high when the first bit can be sent. It remains high for 19 bits and goes low when the parity can be sent.

We would like to generate these signals as efficiently as possible. Thus, I attempted to implement these signals using the same Timer 3. Here's how the "pseudocode" looks:
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1,(uint32_t *)dataClk, 20);
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_2,(uint32_t *)dataSync, 20);
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_3,(uint32_t *)dataX, 20);
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_4,(uint32_t *)dataY, 20);
Initially, I successfully generated the clock of 2MHz with the following function:
void startScannerClk(void){
TIM3->CCR3 = 27;
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_3);
}
Then, I attempted to try this function:
void send_Scanner_CHX(void){
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_3,(uint32_t *)chx_buf, 32);
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_4,(uint32_t *)chy_buf, 32);
}
The chx_buf and chy_buf contain the same data and are initialized like this:
#define DMA_Scanner_BUFFER_SIZE 50
uint16_t chx_buf[DMA_Scanner_BUFFER_SIZE];
uint16_t chy_buf[DMA_Scanner_BUFFER_SIZE];
I observed these signals:: red TIM_CHANNEL_3; blue TIM_CHANNEL_4

The clock of 20 periods, which is what is stored in chx_buf, works perfectly and the channel_4 generates the same signals but it starts around 2ns later, which would be a problem.
So my questions are:
- Is it possible to generate the XY2-100 protocol with timers, PWM_DMA, and synchronization as described in the definition?

- If yes, do I have to use 4 different timers, or can I use one timer with 4 channels, as I did in my test?
- Is there an example of generating more than one signal and synchronizing these signals?
- Would it make more sense to "bitbang" the protocol (using all the CPU power)?
Best regards, Corsin
