This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Get nCS delay without using timer or a hard delay: mask SPI-CLK output

Most external SPI ic's want a small delay after you set its nCS and before you start to clock in data.

Setting up a timer for this small 20-100µS delay is over kill
and hard delay loop is a no-no in true state machine programming (and is also dependent on mclk freq)

Solution:
Use a empty spi txbyte to get the delay by masking out the clk output while it "think" it is sending the first byte.
This way the SPI TX IRQ is in charge of the delay.

Use PULL Resistor ENABLE to override the USCI SPI CLK
1 byte = 8µS delay (if spi clk is 1MHz)

 bis.b #BIT5,&P1REN                            ; enable for now
 bis.b #BIT5,&P1OUT                            ; clear or set depending on clk phase at rest
 bis.b #BIT5+BIT6+BIT7,&P1SEL     ; P1.x set as SPI pins (datasheet page 49)
 bis.b #BIT5+BIT6+BIT7,&P1SEL2    ; P1.x set as SPI pins     

I guess you could do the same for MOSI, though if you always write 0x00 or 0xff to it while "delaying" it will not toggle.
and even if toggling it should not cause any harm.


Start your spi_cnt with a negative number (-2 for double the delay etc) and when it hits zero, enable the clk 
USCIB0_TX_ISR 
           inc.w &spi_cnt
 if_z   bic.b #BIT5,&P1REN                       ; did it wrap around to 0? enable spi clk
           cmp.w &spi_cnt,&spi_len             ; sent all bytes yet?

This could also be used for a empty last byte, as when TX IFG is set does not mean the byte got sent yet.
Though right now I use RX_IRQ for that, so I will do some more testing to see what is best.

Apparently PREN disables the module pin driver on most msp430, except these below

On some I/O ports on the MSP430F261x and MSP430F241_6/7/8/9
enabling the pullup/pulldown resistor (PxREN = 1) while the module function is selected (PxSEL = 1)
does not disable the logic output driver.

  • Tony,

    Thanks for sharing your solution to this problem. Hopefully others will be able to use this!

    Mike
  • It's the other way: when the port pin is configured for output, PxREN is ignored. This applies to most 5x family devices, but not to most 2x family devices. Idea is low power: it makes no sense to have a pull-up while the port is diving down (and v.v.). The only use would have been for I2C and here the internal pull-up is too weak, so it doesn't matter.

    Your idea is quite good. However, I would simply de-select PxSEL and configure the port pin to steady clock-inactive level.
    Also, since TXIFG is preceding the transfer, it would be safe to use the RX interrupt for the initial delay and keep TXIE clear. So when the RX interrupt fires, you know that your delay data has been transmitted. When using the TX interrupt, any latency when executing the TX interrupt leaves some uncertainty about where you are on the clock timeline. Your next (real) data byte might have already started. When using RX interrupt, the USCI will stall after this since you didn't write another byte yet. A more safe general setup.
  • >de-select PxSEL

    But you would have to write to both PSEL registers to get it to GIO mode, potentially creating a clock-signal in the transition and that is no good.

    The first delay may be shorter than 8*smlk, as when you write to txbuf the first time it gets transferred to output stage near instantly
    and buf should be ready for another byte asap. but if you use 2-3 dummy bytes and just don't includes the first one in the delay calculations you would be OK.
    Maybe move everything over to RX_ISR instead and it will be more predictable, as enable the clock mid-stream on the TX output stage is really bad.

    I will create a simple library/module this week that use this technique and see if it's fool prof.
    But maybe will only work on x2xx, as I did test it with a oscilloscope on a G2553 and it worked as I described.

  • "But you would have to write to both PSEL registers to get it to GIO mode"
    I see. So on these MSPs it is not a good solution, only on those with just PxSEL and no PxSEL2. Or where PxSEL2 is clear for both.

    "The first delay may be shorter than 8*smlk"
    That's why I suggested RXIFG, as it is triggered after the first byte is sent. However, depending on phase and polarity, it might by 7,5 CLK cycles, not 8.

    IIRC, the eUSCI (for devices that ave one, of course) has an interrupt for busy, so you can start one transfer, and on busy interrupt you enable the clock output and start the real transfer.

**Attention** This is a public forum