|
|
View previous topic :: View next topic |
Author |
Message |
pmuldoon
Joined: 26 Sep 2003 Posts: 218 Location: Northern Indiana
|
switching between two #USE RS232 streams |
Posted: Wed Sep 13, 2017 5:44 am |
|
|
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
|
|
Posted: Wed Sep 13, 2017 7:05 am |
|
|
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
|
|
Posted: Wed Sep 13, 2017 9:08 am |
|
|
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
|
|
Posted: Wed Sep 13, 2017 10:45 am |
|
|
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
|
|
Posted: Wed Sep 13, 2017 10:56 am |
|
|
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
|
|
Posted: Wed Sep 13, 2017 1:35 pm |
|
|
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
|
|
Posted: Thu Sep 14, 2017 5:23 am |
|
|
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. |
|
|
|
|
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
|