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

switching between two #USE RS232 streams

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



Joined: 26 Sep 2003
Posts: 218
Location: Northern Indiana

View user's profile Send private message

switching between two #USE RS232 streams
PostPosted: Wed Sep 13, 2017 5:44 am     Reply with quote

I am using two UARTS on a PIC

Code:

#define BT_UART      UART2STRM
#define TERM_UART    UART1STRM
#use RS232(UART2,Stream=BT_UART,Baud=115200,PARITY=N,BITS=8,ERRORS)  // use internal UART2
#use RS232(UART1,Stream=TERM_UART,Baud=19200,PARITY=N,BITS=8,ERRORS)  // use internal UART1

Is there a way to make the stream a variable?
I have a terminal interface that works fine on the USB uart, but I would like to be able to switch all of that to the BT uart if the user connects thru BT without having to clone (and maintain) a BT version of the function.

Another option, but I can't find much info to support it, is to use the USB with no stream so it is STDIN/OUT. Then use fprintf(BT_UART,...) to change the STDOUT to the BT and fprintf(STDOUT) to change it back. Then I can just use printf()'s for everything. I tried it and it seemed to almost work, but I think I forgot to change STDIN so it appeared to not quite work as soon as I was looking for an input and I started pursuing the above technique. I may just go back to that and fix the STDIN switching just to see what happens.

I'm sure with all the UARTs available on some of the PICs that this has been done to death and I'm just overlooking something obvious. Just looking for a 'normal' and safe way of doing this rather than coming up with something a bit irregular that just happens to work... for now.

Oh, the #defines are just so MplabX doesn't flag the stream names as unknowns and mark every line with a warning flag which camouflages my legitimate screw-ups.
jeremiah



Joined: 20 Jul 2010
Posts: 1358

View user's profile Send private message

PostPosted: Wed Sep 13, 2017 7:05 am     Reply with quote

You can make a small driver file that does something like:

Code:

typedef enum {SELECT_BT, SELECT_TERM} uart_select_t;

void uart_putc(char c, uart_select_t s){
   switch(s){
      case SELECT_BT:
         fputc(c,BT_UART);
      case SELECT_TERM:
      default:
         fputc(c,TERM_UART);   
   }
}

// Do similar for other functions


If you want to use printf, you'll need to change from passing in the select variable to using a global:

Code:

typedef enum {SELECT_BT, SELECT_TERM} uart_select_t;

uart_select_t g_uart_selector = SELECT_TERM;

void uart_putc(char c){
   switch(g_uart_selector){
      case SELECT_BT:
         fputc(c,BT_UART);
      case SELECT_TERM:
      default:
         fputc(c,TERM_UART);   
   }
}

// Do similar for other functions


Then you can define printf like this:

Code:

#define uart_printf(fmt, ...) printf(uart_putc, fmt, __VA_ARGS__)


Assuming a version 5.x compiler. Then all you have to do is change the global whenever you want to swap UARTs.
pmuldoon



Joined: 26 Sep 2003
Posts: 218
Location: Northern Indiana

View user's profile Send private message

PostPosted: Wed Sep 13, 2017 9:08 am     Reply with quote

That's helpful, thanks. And yes, I have the latest CCS v5.074.

What I've found so far that seems to work is
Code:

#define BT_UART      UART2STRM
#use RS232(UART2,Stream=BT_UART,Baud=115200,PARITY=N,BITS=8,ERRORS)  // use internal UART2
#use RS232(UART1,Baud=19200,PARITY=N,BITS=8,ERRORS)  // use internal UART1


Apparently UART1 is ALWAYS STDIN and STDOUT, but the default stream is whatever was used last. (That is the point I was confused on.)

So, to switch all my printf()'s to use BT_UART I just have to execute one fprintf(BT_UART) and all printf()'s will output to BT_UART. To switch back, I have to fprintf(STDOUT). The same seems to be true for changing the default input between STDIN and BT_UART.

This seems to be working okay for now, I'm just not sure how solid an approach it is.
jeremiah



Joined: 20 Jul 2010
Posts: 1358

View user's profile Send private message

PostPosted: Wed Sep 13, 2017 10:45 am     Reply with quote

the downside to that method is that it is implementation defined. If they update the compiler and change how it selects they stream internally (this isn't documented behavior), then you can run into some very hard to identify bugs. If you don't ever plan on updating your compiler, then it shouldn't be a problem.
pmuldoon



Joined: 26 Sep 2003
Posts: 218
Location: Northern Indiana

View user's profile Send private message

PostPosted: Wed Sep 13, 2017 10:56 am     Reply with quote

I'm liking your method better all the time.
Now that I re-read it, it's making more sense to me. You're using that optional fname parameter in printf().
Code:

printf (fname, cstring, values...)

I had to look it up. Now I see how it works. Very cool.
jeremiah



Joined: 20 Jul 2010
Posts: 1358

View user's profile Send private message

PostPosted: Wed Sep 13, 2017 1:35 pm     Reply with quote

pmuldoon wrote:
I'm liking your method better all the time.
Now that I re-read it, it's making more sense to me. You're using that optional fname parameter in printf().
Code:

printf (fname, cstring, values...)

I had to look it up. Now I see how it works. Very cool.


It's a really handy version of printf. I use it a lot for LCD displays. I make an lcd_putc function and do a #define lcd_printf(fmt, ...) printf(lcd_putc,fmt,__VA_ARGS__)

Works with any output advice that you can make a putc like function for.

I even use it for debug utiliities:
Code:

#ifdef DEBUG
#define dbg_printf(fmt,...) printf(some_output_putc,fmt,__VA_ARGS__)
#else
#define dbg_printf(fmt,...) /*Nothing here*/
#endif


Then I can have the compiler automatically remove all my debug printfs with a single define so they don't take code space or runtime resources.

Variadic macros can be really useful.
pmuldoon



Joined: 26 Sep 2003
Posts: 218
Location: Northern Indiana

View user's profile Send private message

PostPosted: Thu Sep 14, 2017 5:23 am     Reply with quote

okay J, first I had to google variadic.
Quote:
a variadic function is a function of indefinite arity

Still not sure if I could use it in a sentence without embarrassing myself.

But I see your point and understand what you're doing. Thanks for sharing that technique. I will put it to good use.

(off topic) We just got a job writing code for a customers ARM processor design (my first). It's going to be a much more complex environment, but I can handle that. What I will miss as I get into that project is the quality of user forums available. I've never seen a forum that is as easy to use and as helpful as this one.
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