View previous topic :: View next topic |
Author |
Message |
beaker404
Joined: 24 Jul 2012 Posts: 163
|
PIC to PIC serial. |
Posted: Tue Apr 11, 2017 3:21 pm |
|
|
Needing to send data from one PIC to another.
The sending 16F876 PIC uses the UART to send HEX data:
Code: | #use rs232(baud=4800,xmit=PIN_C6, rcv=PIN_C7,stream=USB_SERIAL,ERRORS)
int MSB,LSB;
long value_L;
MSB = (int)(value_L >> 8);
fprintf(USB_SERIAL,"%2x",MSB);
delay_ms(25);
LSB = (int)(value_L);
fprintf(USB_SERIAL,"%2x",LSB);
|
the receiving 16F877 PIC uses a software UART on INT0:
Code: |
#use rs232(baud=4800,xmit=pin_b1,rcv=pin_b0,stream=CTRL)
#int_rda
void serial_isr() {
char cChar;
cChar = fgetc(CTRL);
s
} // end serial_isr() |
Question is this, the most efficient way to do this? Time is critical on this one needing to process fast.
Also, sending the HEX will the cChar variable get the HEX value or a CHAR conversion?
Thanks for the thoughts and time on this one. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Apr 11, 2017 4:41 pm |
|
|
Why not use the hardware UART on both ends?
How your receiver handles the character depends on your code.
Mike |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Apr 11, 2017 4:59 pm |
|
|
If 'time is critical', crank up the baudrate! Even the lowly 877 can get over 300KB...
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Apr 11, 2017 6:56 pm |
|
|
Quote: |
int MSB,LSB;
long value_L;
MSB = (int)(value_L >> 8);
fprintf(USB_SERIAL,"%2x",MSB);
delay_ms(25);
LSB = (int)(value_L);
fprintf(USB_SERIAL,"%2x",LSB);
|
Quote: |
Also, sending the HEX will the cChar variable get the HEX value or a
CHAR conversion?
|
It's going to get an ASCII hex byte.
Quote: |
Question, is this the most efficient way to do this? Time is critical on this
one, needing to process fast. |
You're sending ASCII hex. Let's say you have 'value_L' set to 0x1234.
Your code shown above will send 4 bytes: 0x31 0x32 0x33 0x34
So you've taken two bytes and made it into a 4-byte transmission.
It's easier to debug when you do this, because the ASCII characters
will display as 1 2 3 4 on any terminal program, such as TeraTerm, etc.
In other words, you can see what you're sending.
If you just want to send the two original bytes in 'value_L', you can
use fputc() for each one. That would be faster. Also, the time
necessary for fprintf() to convert from binary to ASCII hex would be
eliminated. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Wed Apr 12, 2017 7:02 am |
|
|
Two good points, I am using the UART on the '877 side to interface to a PC so need a second one so am doing a software UART.
As for the baud rate, it would be nice to turn it up, but running nearly 200 feet with no twisted pair or shield in a field application, so want to keep speed low. |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Wed Apr 12, 2017 8:00 am |
|
|
A few points: You are listing the RDA interrupt under your software UART. Software UARTS cannot use the UART interrupts (hardware only). I am not sure how easy it is to use the external interrupt (might be possible, but my gut says the interrupt is too slow to work off an edge condition). When doing software UART receive, you are generally stuck with your code not being able to do anything but receive data. If you leave the receive loop at all you can miss data.
You really should rethink the software UART usage. I would generally only use hardware UARTS for those that need to receive data, so possibly a different chip if you only have 1 on that one (didn't check).
Side note, I seem to remember someone mentioning doing an ISR driven software UART receive...but I think using timers. Maybe Ttelmah? I don't know the details though. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Apr 12, 2017 8:22 am |
|
|
There is actually an option for the software UART 'SAMPLE_EARLY', which is designed for using it inside an edge detect interrupt. Means it samples straight away, instead of waiting for half a bit time after the getc is called. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Wed Apr 12, 2017 9:24 am |
|
|
what are the risks of using the 'SAMPLE_EARLY'? |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Wed Apr 12, 2017 9:45 am |
|
|
Quote: | You're sending ASCII hex. Let's say you have 'value_L' set to 0x1234.
Your code shown above will send 4 bytes: 0x31 0x32 0x33 0x34
So you've taken two bytes and made it into a 4-byte transmission.
It's easier to debug when you do this, because the ASCII characters
will display as 1 2 3 4 on any terminal program, such as TeraTerm, etc.
In other words, you can see what you're sending. |
I am using hyperterminal to watch my transmissions.
It displays the HEX values as you say, IE data like 265E.
Reading this in, It would read in a '2' a '6' a '5' a 'E' and then I would have to convert from CHAR to INT? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Wed Apr 12, 2017 10:24 am |
|
|
On SAMPLE_EARLY, ideally you need to work out how long it takes your processor to get into the interrupt, relative to the bit time. This depends on your processor clock versus the serial rate. If the time is less than 1/4 bit time then you don't want to use SAMPLE_EARLY. If it this large or bigger it needs to be used. It takes typically about 30 instruction times to get into an interrupt handler, and then another perhaps 10 instruction times to actually get into the getc and start reading. At higher data rates it is the only way to get even close to the correct sample point....
If you have a character in a variable 'chr', then assuming you have upper case hex:
val = (chr>='A')?(chr-55):(chr-'0');
will make 'val' be the actual numeric value of 'chr'.
What it does is test if char >= 'A' (so A B C etc..), and if so puts this-55 into val, otherwise puts chr minus the ASCII value of the character '0' into val. Now, 'why 55', is because the ASCII value of 'A' is 65, and we want this to return 10. 65 - 10 is 55.... |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Thu Apr 13, 2017 7:01 am |
|
|
I will be looking into that today, I will report back how the sending and receiving pans out. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Fri Apr 14, 2017 6:29 am |
|
|
After some project rethinking and soul searching, I think I will take earlier advice and move to a PIC with two UARTs. Did not go this way earlier due to field upgrade concerns. I can still upgrade if I do a plug in board that uses the '877 socket to bridge between the two boards allowing me to have a PIC with a much easier interface that being two UARTS. I am thinking 18F26K40 as I do not need all the IO of a 40 pic device and the daughter board will be smaller with the 28 pin package. I will take thoughts on which device then start a new thread for that topic as needed. thanks all and have a good Easter. |
|
|
beaker404
Joined: 24 Jul 2012 Posts: 163
|
|
Posted: Fri Apr 14, 2017 6:50 am |
|
|
One thing I am confused about is how to read the datasheet format for the pinouts of the '26K40.
specifically which pins are the UARTS on? seemed easier when the available functions were just spelled out graphically on the chip picture. Could be not enough coffee yet this morning too. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Fri Apr 14, 2017 6:55 am |
|
|
haha..won't run out of pins.....lol !
really, you ALWAYS need 2-3 more..
I settled on the PIC18F46K22 as my 'goto', Swiss Army Knife PIC years ago. Yes, 'overkill' for 99% of projects BUT I've never run out of pins,memory or peripherals. While it may cost a bit more you can build YOUR libraries and get to KNOW one PIC very, very well.
Having the 2 HW UARTs is a BIG bonus ......
If you design your own PCBs, you only need one type as the basis or 'template' for all your projects.
Jay |
|
|
jeremiah
Joined: 20 Jul 2010 Posts: 1354
|
|
Posted: Fri Apr 14, 2017 9:32 am |
|
|
beaker404 wrote: | One thing I am confused about is how to read the datasheet format for the pinouts of the '26K40.
specifically which pins are the UARTS on? seemed easier when the available functions were just spelled out graphically on the chip picture. Could be not enough coffee yet this morning too. |
I cannot view the datasheet from here, so it depends. Is the 26K40 a chip with Peripheral Pin Select (PPS) and is the UART located on that? If so, it is pretty easy:
Code: |
#PIN_SELECT U1TX = PIN_B7
#PIN_SELECT U1RX = PIN_B6
#use rs232(baud=4800,UART1,errors,stream=CTRL)
|
NOTE: those are made up pin assignments. I don't know that chip's pins well enough to guess at the real ones.
If it doesn't have the PPS, then it should list a specific set of pins for the UART. |
|
|
|