Friday, 26 May 2017

Can I use SPI for asynchronous serial output?


I need a second serial async output channel on the MSP430G2553 and would like to use the SPI USCI to do this.


Is the USCI SPI baud rate stable enough to do this at 300 baud, 2400 baud or 9600 baud? I am currently using the 8 MHz clock.


Is there any other option that can save me from bit-banging?


My current thinking for 300 bd Tx is as follows:



  1. set prescaler to 26666 LSB first

  2. load byte into Txbuf

  3. load 0x7F into Txbuf to generate stop and start bits

  4. repeat 2-3


  5. send final stop bits 0xFF


It might also be possible to send ten bits of data on other members of the MSP430 family that contains a SPI.


Thanks for your responses.



Answer



Using SPI to output more than eight bits is possible, as long as you can ensure that TXBUF is always filled.


Your scheme of using 0x7F every second byte becomes unreliable if a delay happens; it might be a better idea to distribute the actual data over two bytes:


1110xxxx xxxx1111
iiisdddd ddddSiii


(i = idle, s = start bit, S = stop bit, d = data)


Then you only have to keep these two bytes together and can allow a pause after them.



  1. Wait for TXBUF empty (TXIFG);

  2. disable interrupts;

  3. write 1st byte to TXBUF;

  4. wait for TXBUF empty;

  5. write 2nd byte to TXBUF;

  6. enable interrupts.



However, check that the SPI module of your MCU actually outputs 1 (the most recent value) when it's idle. It might output the first bit of the last byte instead; in that case, you need to send 0xFF afterwards (or the next valid two-byte combination).


Receiving with SPI might be more dangerous. Any interupt latency will affect the at which you sample the data bits, so you will have a delay that, in practice, is uncontrollable.




Alternatively, you can use a timer output to emulate a UART. Use continuous mode, program a CCR for the time of the next signal edge, and with set or reset output mode as needed. In the interrupt handler, program the following edge (add the bit length to the CCR, and switch set/reset mode, if needed). This is similar to bit-banging, but guarantees the timing as long as you can handle the interrupt for each bit fast enough.


Similarly, you can use a timer for receiving: program a CCR in capture mode on the falling edge. When you get an interrupt, you get the exact time of the edge in the CCR register, and you can then reprogram the CCR for compare mode, triggering in the middle of the respective next bit; in the interrupt handler, the SCCI bit shows the value of the timer input when it was triggered.


No comments:

Post a Comment

arduino - Can I use TI's cc2541 BLE as micro controller to perform operations/ processing instead of ATmega328P AU to save cost?

I am using arduino pro mini (which contains Atmega328p AU ) along with cc2541(HM-10) to process and transfer data over BLE to smartphone. I...