CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

Fast UART transmission

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
stoyanoff



Joined: 20 Jul 2011
Posts: 375

View user's profile Send private message

Fast UART transmission
PostPosted: Wed Feb 17, 2016 9:14 am     Reply with quote

Greetings! I'm using CCS v5.024, MPLab v 8.91 and dsPIC30F5015. I want to use UART interface, but normally if I have baudrate=9600 and this code:
Code:

putc(char);

This command takes 1ms. Is there a way I can just put the value into the output buffer and continue with the rest of the program - without waiting transmission to complete?!
Thanks!
temtronic



Joined: 01 Jul 2010
Posts: 9207
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Feb 17, 2016 10:22 am     Reply with quote

Use an ISR for the transmit. Either it's in the examples or one was posted here. You just load up a buffer and when the xmit section of the UART says I'm empty, it'll grab a character from the buffer and send it.

Jay
BTW 1ms for 9600 baud is correct.
stoyanoff



Joined: 20 Jul 2011
Posts: 375

View user's profile Send private message

PostPosted: Wed Feb 17, 2016 10:40 am     Reply with quote

Just a second! If I use IRS am I going to decrease the transmition time to a few cycles or I`ll have 1ms in the interrupt?!
Thanks!
Ttelmah



Joined: 11 Mar 2010
Posts: 19466

View user's profile Send private message

PostPosted: Wed Feb 17, 2016 10:42 am     Reply with quote

As Jay says, 1mSec/byte is roughly correct.

9600bps = 0.10416mSec/bit

8bit byte, involves 1 start bit, 8 data bits, 1 stop bit.

So 10 bits/byte transmitted.

1.04mSec/byte.

ex_stisr.c shows how to use a interrupt driven serial transmit.

Or on any recent compiler, you can add a transmit ISR to the #use rs232

#use rs232(UART1, BAUD=9600, TRANSMIT_BUFFER=64, TXISR, STREAM=RS232)

Then in the 'main', just enable_interrupts(GLOBAL); and you can fputc/fprintf directly to this buffered UART. Use tx_buffer_available(RS232) to find how much space is available in the buffer.

So if you want to send twenty characters, provided tx_buffer_available is greater than 21, you can print and it will all be buffered almost immediately.
gaugeguy



Joined: 05 Apr 2011
Posts: 301

View user's profile Send private message

PostPosted: Wed Feb 17, 2016 11:17 am     Reply with quote

I am not sure about that particular processor, but typically putc or fputc will only wait if the buffer is full. If the buffer is not full it will place the byte into the buffer and return without waiting for the transmit to complete.
This assumes there is no flow control or enable line set up.
Ttelmah



Joined: 11 Mar 2010
Posts: 19466

View user's profile Send private message

PostPosted: Wed Feb 17, 2016 3:32 pm     Reply with quote

Yes.

The hardware transmission buffer though is very small. On PIC18's, just two characters (one 'in transmission', and one extra). On the PIC30, just four characters.
The only reason it'd wait for a single character, is either using a software UART, or that the hardware buffer is full.
The point about using the transmit interrupt is it allows you to 'extend' the transmission buffer size.
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Wed Feb 17, 2016 3:53 pm     Reply with quote

If you use a dsPIC that has DMA, you can then employ the DMA to automatically send your message for you, with no processor involvement required beyond the initial setup.
Ttelmah



Joined: 11 Mar 2010
Posts: 19466

View user's profile Send private message

PostPosted: Thu Feb 18, 2016 1:37 am     Reply with quote

Not actually that easy or advantageous for simple data transmission.
It's great for 'packet based' transmission (if you have a packet of fixed size, that is transmitted), but gains you little or nothing for more basic data.
Where DMA is great, is when you can set up a linear block of data to send. Then program the UART interrupt to occur every four bytes, and the DMA interrupt to occur when you reach the end of the block. It then handles automatically re-filling the UART buffer, and sends the whole block without processor intervention. However for normal transmissions involving data of variable size, it doesn't gain you anything.
Ttelmah



Joined: 11 Mar 2010
Posts: 19466

View user's profile Send private message

PostPosted: Thu Feb 18, 2016 5:04 am     Reply with quote

stoyanoff wrote:
Just a second! If I use IRS am I going to decrease the transmition time to a few cycles or I`ll have 1ms in the interrupt?!
Thanks!


No, you won't have 1mSec in the interrupt, and the transmission time will remain the same.

The sequence will be:

1) Your call loads the data into the software buffer. Total time a few hundred machine cycles.

2) Interrupt occurs when the UART _can_ receive a byte. Code then transfers one byte to the UART transmit buffer, and immediately exits. Tiny delay.

3) '2' repeats until all bytes are sent. Meanwhile your code can keep running as normal, but will be slowed fractionally as each byte is transferred when the UART signals it can take another byte. A few machine cycles, every 1.04mSec.

So interrupt is being called every 1.04mSec to load the next byte from the software buffer, to the UART hardware.

The actual transmission time is fixed by the baud rate. Nothing else. However instead of having to wait for all the bytes to send, they are transferred to the software buffer (provided it has enough space), and the transmission carries on under control of the interrupt. Meanwhile your code can carry on doing other things.
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Thu Feb 18, 2016 8:04 am     Reply with quote

Ttelmah wrote:
Not actually that easy or advantageous for simple data transmission.
It's great for 'packet based' transmission (if you have a packet of fixed size, that is transmitted), but gains you little or nothing for more basic data.
Where DMA is great, is when you can set up a linear block of data to send. Then program the UART interrupt to occur every four bytes, and the DMA interrupt to occur when you reach the end of the block. It then handles automatically re-filling the UART buffer, and sends the whole block without processor intervention. However for normal transmissions involving data of variable size, it doesn't gain you anything.


I agree that it's not easy to set up, but I respectfully must disagree regarding variable sized data. You just fill your "outbound" buffer (not the UART's buffer) and set the DMA count to however many bytes are in your buffer. Finally, trigger the DMA and let it do its' thing. The DMA interrupt fires when it's done. At that point, repeat if necessary and do nothing if not. I have two different products in the field that use this idea, and they're rock solid.

Where DMA and UARTs doesn't make sense is in data reception with variable sized packets. In that situation, DMA actually makes your job harder to do.
Ttelmah



Joined: 11 Mar 2010
Posts: 19466

View user's profile Send private message

PostPosted: Thu Feb 18, 2016 3:22 pm     Reply with quote

It still requires the buffer to be linear, and with known blocks to transmit.

I've used it on known 'pre-prepared' packets, and it is great for this, but for normal UART I/O, using single byte, or normal printf I/O, it is very hard indeed to handle adding characters dynamically.
It's the difference between things that are suited to a linear buffer, and a circular buffer. 90% of standard UART comms is better suited to the latter....
temtronic



Joined: 01 Jul 2010
Posts: 9207
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Sat Feb 20, 2016 6:36 am     Reply with quote

Have to ask an obvious question..
Can you increase the baudrate or is it fixed on the other device at 9600?
I know 9600 seems to a defacto standard these days, but modern chips can easily push 38400, even 115K200 without errors.

Maybe an option ?

Jay
avatarengineer



Joined: 13 May 2013
Posts: 51
Location: Arizona

View user's profile Send private message Visit poster's website

Baudrate
PostPosted: Mon Feb 29, 2016 10:00 am     Reply with quote

@temtronic
You can any baud rate you wish (within reason);
i.e. a software UART version or hardware version can be described

#DEFINE SWUART FORCE_SW,xmit=Tx2,rcv=Rx2,BRGH1OK,bits=8,parity=n,Stop=1
#USE rs232(SWUART,baud=200000,DISABLE_INTS,stream=COMport)

Looking at the PIC in mind, the UART clock divider, per spec, has pre & post scalers that if you create a spreadsheet, like I do,
will calculate actual versus programmed baud with an error rate based on packet size.
Helps to know drift and offset of Fosc, too.

The old increments of Baud such as 9600 or 115.2K aren't the only choices.
You can use 400Kbaud (it divides evenly from an 8 or 16MHz clock) as long as your receiver is the same or using AutoBaud.
Ttelmah



Joined: 11 Mar 2010
Posts: 19466

View user's profile Send private message

PostPosted: Mon Feb 29, 2016 10:04 am     Reply with quote

Temtronic knows full well what baud rates can be done. He was asking the _thread poster_ whether he could use a higher baud rate, if he was worried by how long a byte takes to send at 9600bps.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group