cancel
Showing results for 
Search instead for 
Did you mean: 

Emulating a shift register in STM32G0

MPrat.1
Associate II

Hi all.

My objective is to read a stream of data intended for a shift register with 1.5us clock period.

There are 17 clock cycles and I want to sample the data at the transition (upper or lower).

Can this be achieved using SPI or should I just bit-bang it?

I have tried using HAL_SPI_Receive but the results are not consistent.

I wait until the data line goes down and call HAL_SPI_Receive to read 2 or 3 bytes, but the data returned is incomplete.

Maybe I am not understanding HAL_SPI_Receive correctly. The timeout is milliseconds? Can I set it to 1 ms to timeout trying to read the 24 bits where only 17 exist? And will it return the data read so far?

Thank You

0693W00000Bd7H6QAJ.png 

 

6 REPLIES 6

The SPI is limited to 16 bits, and changing bit number within the tight clock period here is probably unfeasible. I don't think there is any trivial method to achieve what you want.

One trick which comes into mind would be to have a different pin of the same SPI_SCK connected to another pin, and before (or after) the received frame, swap the SCK from the real clock to this "other SCK" in the GPIO matrix and "manually" perform the remaining clocks to a full SPI frame. This assumes enough time is between the frames to do this, and the cost is the extra 2 pins (and there must be such "other SCK" available on the given package, at all).

Other is the full-fledged DMA transferring from GPIO to memory upon the clocks. Traditionally, this is pulled out by connecting clock to some of the timers' channels, and make the timer's input capture trigger the DMA (se AN4666); maybe DMAMUX allows to use an EXTI for this (but that's another chapter to be studied thoroughly). [EDIT] on 'G0 (Cortex-M0+), GPIO is not available for DMA transfer [EDIT]

Start with forgetting about Cube, it will only get into your way.

JW

Thank you

I know I can disregard the first 1 to 9 bits. Since the data line comes down before the clock starts pulsing, I could use that to trigger the SPI read just after the 1st clock cycle and then only have 16bits to read. Could that work?

Sounds viable, but how do you intend to time the "trigger SPI read", whatever that entails?

One way might perhaps be to use the clock as input to a timer set to external clock, and use PWM on other channel of the same timer to generate a framing (NSS) signal, fed back to NSS of the SPI.

JW

The STM32G0 is the only slave so I guess no need for NSS.

The data line stays idle at high and comes down just before the clock starts to pulse.

I was hoping to use that to be able to call HAL_SPI_Receive at the right time to ignore the first clock cycle and read 2 bytes.

As an alternative can't I just ask to read 3 bytes in HAL_SPI_Receive with a 1ms timeout? I would expect for it to get the 17 bits of data, timeout for not receiving the remaining 7 bits, and return what was read so far?

Tks

Slave SPI should ignore clocks outside NSS, that's why NSS, as a way to ignore clocks you want to ignore.

> HAL_SPI_Receive 

I told you, forget about Cube/HAL. Start reading the Reference Manual.

> at the right time to ignore the first clock cycle and read 2 bytes.

And how do you intend to time the "right time"?

> As an alternative can't I just ask to read 3 bytes in HAL_SPI_Receive with a 1ms timeout? I would expect for it to get the 17 bits of data, timeout for not receiving the remaining 7 bits, and return what was read so far?

No. That receives 2 bytes, the 17th bit remains in the shift register which is user-inaccessible, and the Cube function probably just results in it being forgotten.

JW

Gotcha

I think for now I will just bit-bang this until I get more familiar with the platform and then try to implement it without using hal later on.

Thank You