(A)Synchronous serial transmission from uC

Discussion in 'General Electronics Chat' started by kubeek, Oct 28, 2012.

  1. kubeek

    Thread Starter AAC Fanatic!

    Sep 20, 2005
    4,670
    804
    Hi, I need to transmit ~120bits of data serially from a microcontroller at about 800kbps, but I need it to be cycle accurate and without any pauses between the bytes.

    If I were to use SPI or UART, there will not be enough time between the end of transmission of the last bit and start of the next to supply the next byte to the peripheral. For this I am thinking atmega, but I guess it is the same on all small micros.

    So any ideas how I could achieve this, with making a buffered hardware transmitter being my last resort?
     
  2. JohnInTX

    Moderator

    Jun 26, 2012
    2,344
    1,025
    Use a buffered software TX.

    The UART/SPI is at least double buffered so you can fetch and write character to the UART/SPI while one is being transmitted (TXBUF / SSPBUF for a PIC).

    Configure a FIFO in RAM and configure the transmitter to interrupt the processor when TXBUF/SSPBUF is empty (it will have just started transmitting the previous char). You have one char time to check for FIFO empty, grab the next char and write it to TXBUF/SSPBUF. When the previous char has been shifted out, the UART/SSP will immediately load the buffered char and begin to send it AND raise an interrupt (TXIF/SSPIF ?) to indicate that its time to load the next char.

    You might want to consider a prefetch buffer if you are pushed for time i.e. have the next character from the FIFO pre loaded in a known place. On the IRQ, grab that and write it immediately, then pre-fetch the next one moving pointers etc.

    Make the IRQ a high priority and run the processor as fast as you can.
    If you are using an 8 bit PIC, you'll find all of this way easier on the 18F.

    EDIT:
    You can use a linear buffer rather than a circular one. To do this, you'll have to be able to queue up one whole message then send it and wait for complete before starting another. The advantage is simpler pointers (no wrap around etc) and less processor time. If you have the RAM and don't want a circular queue, you can use a ping-pong buffer i.e. 2 linear bufs. One gets loaded while the other is used for transmit.
     
    Last edited: Oct 28, 2012
  3. kubeek

    Thread Starter AAC Fanatic!

    Sep 20, 2005
    4,670
    804
    Thanks John, I had to read the datasheet very carefully to find that the usart in spi mode is buffered, so I can use it that simply. I am using AtXmega128a3u with 8k ram so hopefully no problem there.
    The actuall communication is pretty slow, so no problem with preparing the buffer and then starting the transmitt session when ready, and having the interrupt load the next byte in time.

    The chip even has multiple interrupt priorities and a four channel DMA module so I guess I can do this in multiple ways after all. And since it has almost 1 instruction per clock cycle then running it at 13.56MHz will give me lots of instructions to spare.
     
  4. JohnInTX

    Moderator

    Jun 26, 2012
    2,344
    1,025
    Don't forget that SPI is always bidirectional so as part of writing the next character, you'll have to read the received one, even if you don't need it.

    Have fun!
     
  5. kubeek

    Thread Starter AAC Fanatic!

    Sep 20, 2005
    4,670
    804
    Actually the datasheet doesn´t explicitly say that and even the receiver can stay disabled in the usart module in the spi mode but thanks anyway.
     
Loading...