|
|
View previous topic :: View next topic |
Author |
Message |
OldGuy
Joined: 03 Feb 2013 Posts: 27 Location: Seattle Area
|
2 RS232, how to handle I/O |
Posted: Fri Aug 21, 2020 5:24 pm |
|
|
Hi - On my project, I have two RS232 streams going on at once. Well, at the moment none of them are going on at once. This is a PIC18F25K80, with both streams connected to hardware EUSART pins. At the moment, I'm not getting an interrupt on incoming characters (waiting for that LED to blink!). So, since the XBEE channel doesn't work, evidently there is something wrong in my software.
A bigger question is how do I set it up for both channels to be receiving at once? Seems like INT.RDA only accommodates one interrupt and buffer. I've tried INT_RDA2, it doesn't work either. The compiler doesn't seem to like INT_RDA1 or INT_RDA0. How do you tell the compiler which RDA to use if there are two channels?
I can see the input line going to RB7 wiggle on my scope when I send it a character, but no interrupt occurs. I've successfully transmitted from this same circuit, so I think the hardware is ok.
Any thoughts would be appreciated.
My code is shown in my next post, it currently won't find input characters:
Last edited by OldGuy on Fri Aug 21, 2020 6:19 pm; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9228 Location: Greensville,Ontario
|
|
Posted: Fri Aug 21, 2020 5:33 pm |
|
|
from my foggy memory...so are 14 hr days..
you need two ISRs....
int_rda is the first serial port
int_rda1 is the 2nd serial port.
if you press F11, when using MPLAB, the CCs C manual magically opens up. find the 'preprocessor' tab (?), find INT_RDA... it's there 'somewhere'.
I know it does work.... I had a 46k22 tied in a double loopback test ( PC>uart1>uart2>uart1>pc and with double buffers got 115k200 serial without a problem....
other will reply, maybe with a small test program for you... I need some zz's
Jay |
|
|
OldGuy
Joined: 03 Feb 2013 Posts: 27 Location: Seattle Area
|
|
Posted: Fri Aug 21, 2020 6:15 pm |
|
|
Thanks for your tired thoughts Jay.
So RDA is EUSART 1 and RDA2 is EUSART 2? Defined by the pin numbers in the Use RS232?
That would make sense, and be easy to accommodate if I can figure out why it isn't capturing RDA.
Any further thoughts appreciated.
I think I posted my code wrong initially, I'll try it again:
Code: |
#include <18F25K80.h> // this also does the #device PIC18F25K0
// the fuses specify use of external 16 MHz oscillator
#use delay (clock=16MHZ)
#fuses NOWDT, HSH, NOPUT, NOPROTECT, NOWDT, NOPLLEN
// set up the RS-232 channels
#use rs232 (stream=SOUNDER, baud=4800, xmit=PIN_C6, rcv=PIN_C7, PARITY=N, BITS=8, ERRORS) // Sounder in 0813 RS-232 mode
#use rs232 (stream=XBEE, baud=9600, xmit=PIN_B6, rcv=PIN_B7, PARITY=N, BITS=8, ERRORS) // XBee to shore
#include <stdlib.h>
#define LED PIN_A1 // pin 2, signal RA1/AN1 - low to turn on LED
#define OFF 0 // for reel and LED control
#define ON 1 // for LED
#define IN 2 // reel
#define OUT 3 // reel
#define BUFFER_SIZE 32
char buffer[BUFFER_SIZE];
char next_in = 0;
char next_out = 0;
char char_received = ' ';
// LED on or off
Void LED1 (what) {
if (what == OFF) output_high (LED);
if (what == ON) output_low (LED);
}
// blink the LED for the specified number of mS (500mS if zero)
Void LED1_Blink (int16 how_long) {
LED1(ON);
if (how_long == 0)
Delay_MS (500);
else
DELAY_MS(how_long);
LED1(OFF);
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
BYTE c;
while(!bkbhit);
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
#int_rda
void serial_isr() {
LED1_blink(0);
int t;
buffer[next_in]=bgetc();
if (buffer[next_in] == 'O') LED1_blink(0);
if (buffer[next_in] == 'I') LED1_blink(0);
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
void main (void) {
char_received = ' ';
LED1_Blink (0); // LED on for a little bit to know we're running
// XBEE input interrupt
enable_interrupts (INT_RDA);
enable_interrupts (global);
// now we just sit here and loop, gathering data
while (TRUE) {
delay_ms(500); // don't loop too fast
// see if anything arrives via xBee
if (bkbhit) char_received = bgetc();
if (char_received == 'I') led1_blink(0);
if (char_received == 'O') led1_blink(0);
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 21, 2020 6:49 pm |
|
|
Your code is badly wrong. Look at the .LST file.
Quote: |
....... // set up the RS-232 channels
....... #use rs232 (stream=SOUNDER, baud=4800, xmit=PIN_C6, rcv=PIN_C7, PARITY=N, BITS=8, ERRORS) // Sounder in 0813 RS-232 mode
........ #use rs232 (stream=XBEE, baud=9600, xmit=PIN_B6, rcv=PIN_B7, PARITY=N, BITS=8, ERRORS) // XBee to shore
........
|
The compiler is not generating any code for either UART.
You don't have any calls to fgetc() in your rda isrs. Without that, you won't
receive and characters. Study Ex_Sisr.c. Notice the isr doesn't call bgetc().
It calls getc(). For streams you need to use fgetc() and specify the stream
as the parameter. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 21, 2020 6:53 pm |
|
|
temtronic wrote: |
int_rda is the first serial port
int_rda1 is the 2nd serial port.
|
temtronic,
Why don't you just pull up the .h file before answering ? What good is a
bum answer ? If you look at the .h file, you see it's RDA and RDA2
Here is the list of ints from the .h file:
Quote: | #define INT_EXT2 0x00F010
#define INT_RB 0x01FFF208
#define INT_AD 0x009D40
#define INT_RDA 0x009D20
#define INT_TBE 0x009D10
#define INT_SSP 0x009D08
#define INT_BUSCOL 0x00A008
#define INT_RDA2 0x00A320
#define INT_TBE2 0x00A310
#define INT_OSCF 0x00A080
|
|
|
|
OldGuy
Joined: 03 Feb 2013 Posts: 27 Location: Seattle Area
|
|
Posted: Fri Aug 21, 2020 7:07 pm |
|
|
I fixed that erroneous call bgetc, still no luck after changing it to getc(XBEE) or fgetc(XBEE). On another device I've done with a different PIC it works fine with getc(). |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 21, 2020 7:09 pm |
|
|
Post your revised program. |
|
|
OldGuy
Joined: 03 Feb 2013 Posts: 27 Location: Seattle Area
|
|
Posted: Fri Aug 21, 2020 7:13 pm |
|
|
Here's the current program...
Code: |
#include <18F25K80.h> // this also does the #device PIC18F25K0
// the fuses specify use of external 16 MHz oscillator
#use delay (clock=16MHZ)
#fuses NOWDT, HSH, NOPUT, NOPROTECT, NOWDT, NOPLLEN
// set up the RS-232 channels
#use rs232 (stream=SOUNDER, baud=4800, xmit=PIN_C6, rcv=PIN_C7, PARITY=N, BITS=8, ERRORS) // Sounder in 0813 RS-232 mode
#use rs232 (stream=XBEE, baud=9600, xmit=PIN_B6, rcv=PIN_B7, PARITY=N, BITS=8, ERRORS) // XBee to shore
#include <stdlib.h>
#define LED PIN_A1 // pin 2, signal RA1/AN1 - low to turn on LED
#define OFF 0 // for reel and LED control
#define ON 1 // for LED
// RS232 Buffer
#define BUFFER_SIZE 32
char buffer[BUFFER_SIZE];
char next_in = 0;
char next_out = 0;
char char_received = ' ';
// LED on or off
Void LED1 (what) {
if (what == OFF) output_high (LED);
if (what == ON) output_low (LED);
}
// blink the LED for the specified number of mS (500mS if zero)
Void LED1_Blink (int16 how_long) {
LED1(ON);
if (how_long == 0)
Delay_MS (500);
else
DELAY_MS(how_long);
LED1(OFF);
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
BYTE c;
while(!bkbhit);
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
#int_rda
void serial_isr() {
LED1(ON);
int t;
buffer[next_in]=fgetc(XBEE); // also tried getc() and fgetc()
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
void main (void) {
LED1_Blink (0); // LED on for a little bit to know we're running
// XBEE input interrupt
enable_interrupts (INT_RDA);
enable_interrupts (global);
// now we just sit here and loop, gathering data
while (TRUE) {
delay_ms(500); // don't loop too fast
// see if anything arrives via xBee
if (bkbhit) char_received = bgetc();
if (char_received == 'I') led1_blink(0);
if (char_received == 'O') led1_blink(0);
}
} | [/quote] |
|
|
OldGuy
Joined: 03 Feb 2013 Posts: 27 Location: Seattle Area
|
Got it! |
Posted: Fri Aug 21, 2020 7:57 pm |
|
|
I found that by switching to INT_RDA2 it works with the following code. I may have missed this working earlier, if I forgot to unplug the ICD-U64. It also wants to use the same line as incoming RS232, and screws up the signal unless I unplug it each time. Once in a while I forget.
I'm going to presume that I'll use INT_RDA for the other RS232 I/O. Sound correct?
Thank you for your time to give me tips to come to a solution!
Brian
Code: |
#include <18F25K80.h> // this also does the #device PIC18F25K0
#include <stdlib.h>
// the fuses specify use of external 16 MHz oscillator
#use delay (clock=16MHZ)
#fuses NOWDT, HSH, NOPUT, NOPROTECT, NOWDT, NOPLLEN
// set up the RS-232 channels
#use rs232 (stream=SOUNDER, baud=4800, xmit=PIN_C6, rcv=PIN_C7, PARITY=N, BITS=8, ERRORS) // Sounder in 0813 RS-232 mode
#use rs232 (stream=XBEE, baud=9600, xmit=PIN_B6, rcv=PIN_B7, PARITY=N, BITS=8, ERRORS) // XBee to shore
#define LED PIN_A1 // pin 2, signal RA1/AN1 - low to turn on LED
#define OFF 0 // for reel and LED control
#define ON 1 // for LED
// RS232 Buffer
#define BUFFER_SIZE 32
char buffer[BUFFER_SIZE];
char next_in = 0;
char next_out = 0;
char char_received = ' ';
// LED on or off
Void LED1 (what) {
if (what == OFF) output_high (LED);
if (what == ON) output_low (LED);
}
// blink the LED for the specified number of mS (500mS if zero)
Void LED1_Blink (int16 how_long) {
LED1(ON);
if (how_long == 0)
Delay_ms (500);
else
Delay_ms (how_long);
LED1(OFF);
}
#define bkbhit (next_in!=next_out)
BYTE bgetc() {
BYTE c;
while(!bkbhit);
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}
#int_rda2
void serial_isr() {
//LED1(ON);
int t;
buffer[next_in]=fgetc(XBEE); // also tried getc() and fgetc()
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
void main (void) {
LED1_Blink (0); // LED on for a little bit to know we're running
// XBEE input interrupt
enable_interrupts (INT_RDA2);
enable_interrupts (global);
// now we just sit here and loop, gathering data
while (TRUE) {
delay_ms(500); // don't loop too fast
// see if anything arrives via xBee
if (bkbhit) char_received = bgetc();
if (char_received == 'I') led1_blink(0); char_received = ' ';
if (char_received == 'O') led1_blink(250); char_received = ' ';
char_received = ' ';
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: Got it! |
Posted: Fri Aug 21, 2020 9:01 pm |
|
|
[quote="OldGuy"
I'm going to presume that I'll use INT_RDA for the other RS232 I/O. Sound correct?
[/quote]
Yes, INT_RDA is associated with UART1 on pins C6 and C7. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19516
|
|
Posted: Sat Aug 22, 2020 1:32 am |
|
|
As a 'comment', I'd suggest not using the pin numbers.
Issues are:
1) Easy to get them wrong.
2) The numbers do nothing to tell you which stream is which UART,
3) On chips where the UART uses PPS, the pin numbers will result in
a software UART being setup, so no interrupt.
If instead, you use the UART name, the code tells you at once which UART
is being used by which stream:
Code: |
//uses pin C6 for TX and C7 for RX, INT_RDA
#use rs232 (stream=SOUNDER, baud=4800, UART1, PARITY=N, BITS=8, ERRORS) // Sounder in 0813 RS-232 mode
//Uses B6 for TX and B7 for RX, INT_RDA2
#use rs232 (stream=XBEE, baud=9600, UART2, PARITY=N, BITS=8, ERRORS) // XBee to shore
|
Adding the remark, reminds you which pins are involved.
Then if you switch to a chip that uses PPS, the compiler will nicely tell you
that the pins need to be setup before you can use the UART.
This way you have a nice reminder of which stream uses which physical
UART. |
|
|
OldGuy
Joined: 03 Feb 2013 Posts: 27 Location: Seattle Area
|
|
Posted: Sat Aug 22, 2020 7:31 am |
|
|
Thanks for the tips Ttelmah. Makes sense. |
|
|
|
|
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
|