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 CCS Technical Support

Changing baud rate on software UART?
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

Changing baud rate on software UART?
PostPosted: Tue Oct 29, 2013 10:00 am     Reply with quote

Is it possible to set or change the baud rate of a software UART at run time?

I've got a design that uses two serial ports, but the chip has only one hardware EUSART (it's a 16F1459). I'd like to be able to change the speed of the non-EUSART serial port at will. The set_uart_speed() function only works with hardware UARTs, according to the help file, and I verified that even if you specify the stream of the software UART, it sets the baud rate of the hardware UART (it would be nice to have an error message in that case).

Switching to a chip with two UARTs is not a viable option.
stinky



Joined: 05 Mar 2012
Posts: 99
Location: Central Illinois

View user's profile Send private message

PostPosted: Tue Oct 29, 2013 11:46 am     Reply with quote

I haven't done this myself but I believe this will work. Obviously set you desired I/O pins and baud rate.

Code:
#use RS232(baud = 9600, RCV = PIN_A3, XMIT = PIN_A1, STREAM = A)
#use RS232(baud = 1200, RCV = PIN_A3, XMIT = PIN_A1, STREAM = B)


Then use fprintf() to specify which stream to use:
Code:
fprintf(A, "9600 BAUD");
fprintf(B, "1200 BAUD");
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Oct 29, 2013 12:34 pm     Reply with quote

Thanks for the reply. I had thought of that -- a separate stream for each baudrate -- but it would mean that every fprintf() would need to be duplicated with if() or case() wrapped around each one. I guess I could wrap a function around it.

Given that this is for GPS data, I suppose I could just make it a fixed 9600BPS and tell the users to make the GPS conform. I do like the idea of being able to set it to a different baud rate if needed, though.

Edit: Hmmm. tried it... it seems to only act on one of the streams.


Code:
.................... #use rs232(stream=GPS9600,baud=9600,parity=N,rcv=PIN_B6,xmit=PIN_B4,bits=8,restart_wdt,errors)
*
0809:  MOVF   04,W
080A:  MOVWF  78
080B:  MOVLB  01
080C:  BSF    0D.6
080D:  CLRWDT
080E:  MOVLB  00
080F:  BTFSS  0D.6
0810:  GOTO   013
0811:  MOVLB  01
0812:  GOTO   00D
0813:  MOVLW  08
0814:  MOVWF  77
0815:  MOVLB  03
0816:  CLRF   55
0817:  BSF    77.7
0818:  GOTO   02B
0819:  BCF    77.7
081A:  GOTO   02B
081B:  BCF    03.0
081C:  MOVLB  00
081D:  BTFSC  0D.6
081E:  BSF    03.0
081F:  MOVLB  03
0820:  RRF    55,F
0821:  BSF    77.6
0822:  GOTO   02B
0823:  BCF    77.6
0824:  DECFSZ 77,F
0825:  GOTO   01B
0826:  MOVF   78,W
0827:  MOVWF  04
0828:  MOVF   55,W
0829:  MOVWF  78
082A:  GOTO   040
082B:  MOVLW  01
082C:  MOVWF  04
082D:  MOVLW  00
082E:  BTFSC  77.7
082F:  MOVLW  55
0830:  MOVWF  78
0831:  DECFSZ 78,F
0832:  GOTO   031
0833:  DECFSZ 04,F
0834:  GOTO   02D
0835:  MOVLW  98
0836:  BTFSC  77.7
0837:  MOVLW  29
0838:  MOVWF  78
0839:  DECFSZ 78,F
083A:  GOTO   039
083B:  BTFSC  77.7
083C:  GOTO   019
083D:  BTFSC  77.6
083E:  GOTO   023
083F:  GOTO   01B
.................... #use rs232(stream=GPS4800,baud=4800,parity=N,rcv=PIN_B6,xmit=PIN_B4,bits=8,restart_wdt,errors)
.................... #use rs232(stream=RPT,baud=9600,parity=N,rcv=PIN_B5,xmit=PIN_B7,bits=8,restart_wdt,RECEIVE_BUFFER=32,errors)
*
05AA:  CLRWDT
05AB:  MOVF   49,W
05AC:  SUBWF  48,W
05AD:  BTFSC  03.2
8< snip...
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Tue Oct 29, 2013 3:54 pm     Reply with quote

It'll only generate the assembly if you use the stream in your code. Did you make sure to make a call to getc for each stream?
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Tue Oct 29, 2013 10:16 pm     Reply with quote

Yes, I did.
jeremiah



Joined: 20 Jul 2010
Posts: 1349

View user's profile Send private message

PostPosted: Tue Oct 29, 2013 10:32 pm     Reply with quote

I just tried the following test program in 5.010 and it generated code for each stream:

Code:

#case

#include <16F1459.h>

#use delay(clock=22118400)

#use rs232(stream=GPS9600,baud=9600,parity=N,rcv=PIN_B6,xmit=PIN_B4,bits=8,restart_wdt,errors)
#use rs232(stream=GPS4800,baud=4800,parity=N,rcv=PIN_B6,xmit=PIN_B4,bits=8,restart_wdt,errors)
#use rs232(stream=RPT,baud=9600,parity=N,rcv=PIN_B5,xmit=PIN_B7,bits=8,restart_wdt,errors)


void main() {
   char c;
   
   
   enable_interrupts(GLOBAL);
   
   c = fgetc(GPS9600);
   c = fgetc(GPS4800);
   c = fgetc(RPT);
   fputc(c,GPS9600);
   fputc(c,GPS4800);
   fputc(c,RPT);
   
   
   while(TRUE);
}


I wasn't able to include the buffer on the last stream (compiler error prevented it), but each #use gets its own code. You'll need to post your test program probably.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

Re: Changing baud rate on software UART?
PostPosted: Wed Oct 30, 2013 5:55 am     Reply with quote

dbotkin wrote:
I verified that even if you specify the stream of the software UART, it sets the baud rate of the hardware UART (it would be nice to have an error message in that case).
I consider this a bug. Would you please be so kind as to report this to CCS? It will help others in the future.

I don't like the CCS software UART. Simple, but limited in too many ways. Whenever possible I try to use a processor with hardware UART on every stream as it saves me from so many hard to find problems.

As you already discovered the CCS software UART can not change baud rates. Multiple streams are the only option here. Search the forum, this topic has been discussed many times. You can create a wrapper function that uses a global variable to switch between the different streams.

How many different baud rates do you want to support? Each baud rate requires it's own hard coded routines so this could get quiet large.

You want to connect to a GPS, that makes me assume this is for receive only?
Receiving with the software UART is tricky. Interrupts will be disabled during receiving, is that what you want? (1ms disabled for each character at 9600bps)
When the other (hardware) UART is transmit only, you could split the UART to receive from the GPS and transmit to the other. Different baud rates on both would be difficult though.

If you have some extra time it would be nice to create a software UART based on interrupts. This would be way more flexible than the CCS polling method and can support multiple baud rates too.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Wed Oct 30, 2013 7:06 am     Reply with quote

I did post a simple receive UART based on a a timer interrupt here some time ago.

It would be pretty easy to just change the values used in this, to give different baud rates, for a simple couple of rates as involved here.
A search should find it.

Best Wishes
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Wed Oct 30, 2013 4:16 pm     Reply with quote

seriously:
the software based serial routines are not reliable and can fail under many different circumstances that are hard to predict in advance.

No way to tell just how bad your risk is w/o seeing the whole program.

The hardware UART, when used with an RX interrupt driven buffer can be six sigma reliable, and very robust.

if this is a commercial product you are working on,
you are ill advised to use any form of software based serial datacom.

sooner or later it will fail.
the ONLY decently safe soft serial fucntion is for TX only ,
with NO Interrupts enabled. just my 2 cents
temtronic



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

View user's profile Send private message

PostPosted: Wed Oct 30, 2013 5:53 pm     Reply with quote

I'm assuming you're using the USB peripheral is that why you said using a PIC with 2 UARTs is not a viable option...but...would be the best solution. How about adding an I2C<>UART chip ? Is that possible?

Software UARTS, unless s...l....o....w will be real pain.

It might be worth 1/2 day R&D to source a better PIC or configuration to get real UARTs.In the long run it will save a LOT of grey hairs and wasted time.I always use a 'big' PIC,yeah 'overkill' but time is money and 'saving' a few pennies on a small PIC doesn't really work.An extra buck now, spread over say 1000 units is only $1000 compared to a week or more of R&D time used up on problems due to the software UART code.

To put it into perspective , these days the BOX costs a LOT more than the PICs do !

Just thinking of options for you.
hth
jay
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Wed Oct 30, 2013 10:44 pm     Reply with quote

Thanks for the input, guys.

So here's the deal. One serial interface connects to another PIC based device on another board, and that link needs to be reliable, as in hardware UART.

The second interface is receive-only for a GPS, which may or may not be attached. If it is attached, I need to read the NMEA sentence and send it out the other serial port. The GPS data is extremely low priority. The only thing we care about is occasionally capturing a sentence that has valid time information. If we get one intact packet forwarded every few minutes, it's fine. Most of the time (like 99.999% of the time) the processor will have nothing to do but watch the GPS port.

Given the above facts, I'm OK with using the sucky software UART for receiving GPS data. When there is something else to do, I'll simply ignore it. Yes, I could have selected a PIC with two hardware UARTS, but it would have been a waste of board space, money and pins... a 28-pin PIC doing an 18-pin job.

Jay, I agree with you - up to a point. In this case, saving a buck per unit is worth a little "play time" during development. And as I mentioned, less than stellar reliability is not an issue as long as I can receive a packet at 9600 BPS once every few seconds -- or even every few minutes, really. It's just a feature to allow the use of a GPS receiver to set and occasionally sync a real-tine clock on another board. Most users won't have one attached, but I do want it to work right for the few who will.

I think most GPS receivers will support 9600. I know I can buy little $20 modules on Fleabay that run 9600. I'm going to write the firmware for 9600 BPS only. If there's enough program space left when I have everything else working, I'll wrap a function around the GPS side to support a couple of other choices... but I don't know that it's going to be worth sinking a whole lot of effort into.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Oct 31, 2013 3:05 am     Reply with quote

There are still problems....

Key to understand is that when receiving a character, timings have to be accurate. Hence for non interrupt based software receive (or transmit), interrupts have to be disabled.

Now provided the other link is at the same baud rate _or slower_ than the software link, then using the disable_ints option is OK, since interrupts will be enabled momentarily between characters, allowing interrupt driven serial RX on the other channel to work reliably.

I've put the timer based serial I mentioned earlier, up into the code library.
This potentially could do what you need from the GPS, though you would need to enlarge the buffer, if you are not going to be able to parse the strings fairly often.
<http://www.ccsinfo.com/forum/viewtopic.php?p=180938>

Worth saying that the 'historic' rate for NME GPS strings is 4800bps.
Look up NMEA 0183.
Running at the lower rate, means you can do things slower (interrupt at lower frequency on the example given), and this is the default 'start up' rate on a lot of devices. It is the 9600bps rate that is 'less standard' speed, and for your application, I'd suggest using the slower rate.

Best Wishes
dbotkin



Joined: 08 Sep 2003
Posts: 197
Location: Omaha NE USA

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Thu Oct 31, 2013 11:15 pm     Reply with quote

Ttelmah wrote:
Worth saying that the 'historic' rate for NME GPS strings is 4800bps.
Look up NMEA 0183.
Running at the lower rate, means you can do things slower (interrupt at lower frequency on the example given), and this is the default 'start up' rate on a lot of devices. It is the 9600bps rate that is 'less standard' speed, and for your application, I'd suggest using the slower rate.


Yeah, I'm aware of the "historical default" 4800 BPS rate. A lot (most?) of the inexpensive GPS receiver modules now available default to 9600, and lack any sort of documentation whatsoever. I shudder to think of even attempting to walk a customer through changing the baud rate, especially since they're not even RS232 devices (TTL level only). So I've got to be able to talk to the majority of the probable candidates with no user intervention at all.

What you said about disabling interrupts and such got me thinking, though. Really, when listening for GPS data I can afford to just do that and nothing else -- I'll get an external interrupt if the other task needs attention, at which time I can simply ignore the GPS data for as long as needed. So that got me thinking. I don't want to waste the space, pin count and expense of a device with two hardware UARTS... but hey!! I really need two UARTs, since I only have to actually use one at a time. How about a device whose UART pins I can MOVE at will? Bingo. 16F1827/1847. OK, so I can really only move the RX pin; there are three pins total that can be used for RX/TX. But I don't need to send data to the GPS, only to the other device. So TX to the host board stays on B5, and I can switch RX between pins B1 and B2 as needed. Seems like the compiler still doesn't support doing it -- #pin_select doesn't seem to work, nor does changing the pins with #use_rs232 from the looks of it, but I can change APFCON0 bit 7 on the fly.

And if I'm going to resort to that, I may as well set the SPBRGH:SPBRGL registers myself, too.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Nov 01, 2013 10:49 am     Reply with quote

dbotkin wrote:
How about a device whose UART pins I can MOVE at will? Bingo. 16F1827/1847.
There are even more PICs that can do this than the two models you reference here.

I'm surprised you consider changing processor as the PIC16F1459 has USB and you are dropping that feature now. From what we know for your project even the dirt cheap 8-pin PIC12F1822 might do the job. It has a hardware UART with switch-able pin configuration on the UART.

Quote:
And if I'm going to resort to that, I may as well set the SPBRGH:SPBRGL registers myself, too.
Well, yes, you can hard code everything if you want to, but what's wrong in using the set_uart_speed() function? That's doing exactly that for the hardware UART.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

Re: Changing baud rate on software UART?
PostPosted: Fri Nov 01, 2013 12:17 pm     Reply with quote

ckielstra wrote:
I consider this a bug. Would you please be so kind as to report this to CCS? It will help others in the future.

I don't like the CCS software UART. Simple, but limited in too many ways. Whenever possible I try to use a processor with hardware UART on every stream as it saves me from so many hard to find problems.

It is worth pointing out that the manual for set_uart_speed, says:

"Changes the baud rate of the built-in hardware RS232 serial port at run-time. "

Couldn't really be much plainer.

Agree totally about the standard software UART.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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