View previous topic :: View next topic |
Author |
Message |
pulurumbuluruciu
Joined: 06 Nov 2013 Posts: 27
|
Baud Rate "Conversion" |
Posted: Mon Dec 02, 2013 3:43 pm |
|
|
Hi. Using 18F25k22 ( 2 UART) I'm trying to get data from one UART With a 57600 bps, and send it over the other UART with 9600 bps. The problem is that the data comes too fast from the 57600, and the 9600 bps UART fails to output all the string. How is this done in a correct way? I tried
Code: |
fputc(UART9.6,fgetc(UART57.6));
|
I know that I must implement a buffer but I tried several ways and failed. Please help. Thank you. |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 02, 2013 5:01 pm |
|
|
Look in the CCS example files directory for Ex_sisr.c. It shows how to
make a serial receive buffer for the incoming bytes:
Quote: | c:\program files\picc\examples\ex_sisr.c |
|
|
![](templates/subSilver/images/spacer.gif) |
gpsmikey
Joined: 16 Nov 2010 Posts: 588 Location: Kirkland, WA
|
|
Posted: Mon Dec 02, 2013 7:12 pm |
|
|
If the average data rate from the 57k source is above 9600 baud, then you can't get there from here. If the source average rate is less than 9600 baud, then you can do it, but will need to look at the "burst" size to determine what size buffer you will need (hopefully less than the available RAM in the chip). The key here is the average rate from the source - if it is too high, you are going to have to look at alternatives.
mikey _________________ mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3 |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9170 Location: Greensville,Ontario
|
|
Posted: Mon Dec 02, 2013 8:53 pm |
|
|
With proper handshaking it should be possible using the Ex_SISR.C example lightly modified for the 2 serial ports.
Key is handshaking.
I've done similar with 115K200 > 9600 using a 46k22 PIC.been stable for 14-18 months in the lab.
hth
jay |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19360
|
|
Posted: Tue Dec 03, 2013 1:31 am |
|
|
Agree with Temtronics comments.
You may need to deal with buffer 'overshoot' when handshaking. So (for instance), if you are running a 256byte buffer, it is no good trying to stop when the buffer is full. You need to send the handshake, some characters _before_ the buffer is full. PC's typically have 16byte of hardware buffering, and using XON/XOFF etc., it takes a character time for this to be sent, and it may then send this many characters after you tell it to 'stop'. So something like 32 characters before the buffer is full, is the point to be telling it to stop....
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Tue Dec 03, 2013 5:06 am |
|
|
don't forget uni-directional DTR-RTS handshaking as another way to deal with
potential overflow issues - tho this will require a control pin on your PIC to 'wave off" the 57600 source when the receive buffer is within range of it's last character or two. simpler and more efficient than software handshake, which can wreck havoc with binary transfers |
|
![](templates/subSilver/images/spacer.gif) |
pulurumbuluruciu
Joined: 06 Nov 2013 Posts: 27
|
|
Posted: Tue Dec 03, 2013 6:48 am |
|
|
Thank you for all your inputs. The incoming burst is relativ small ( 100 chars) so it could be easy managed by a buffer. The problem is that when I output the characters with a 50 us delay( needed as a guardtime) between them from the buffer I dont get the correct ones anymore. If I output them whitout that delay it works fine. Used the SISR example modified file for that.
NOT WORKING CODE (NEEDED)
Code: |
do {
while(bkbhit)
delay_us(50);
fputc( bgetc(),UART9.6 );
} while (TRUE);
|
WORKING CODE
Code: |
do {
while(bkbhit)
fputc( bgetc(),UART9.6 );
} while (TRUE);
|
|
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19360
|
|
Posted: Tue Dec 03, 2013 8:00 am |
|
|
Understand that if using a hardware UART, you won't get any delay this way....
There is a couple of characters of hardware buffering on the output. Fputc, will return as soon as the characters transfer to the hardware buffer, since each character (at 9600bps), will take 1.04mSec to send, the delay will be lost in the period it takes the character to physically send.....
If you want a longer pause between characters, set the UART up to send 9 bit characters, and then make sure what you actually send has the ninth bit as a zero.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
pulurumbuluruciu
Joined: 06 Nov 2013 Posts: 27
|
|
Posted: Tue Dec 03, 2013 8:26 am |
|
|
How do I send 9 bits char? Using 2 stop bits? |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19360
|
|
Posted: Tue Dec 03, 2013 8:59 am |
|
|
The _hardware_ only supports 8 or 9bit transmission with one stop bit.
The point is that if you select 9bit, then make sure the MSB (9th bit) is one, this sends effectively an extra stop bit, giving an extra just over 100uSec between the bytes.
Just set bits=9, and the option 'LONG_DATA' in the #use RS232 for the 9600bps stream. Then make sure the value you get from the 8bit UART is put into (or cast into) an int16, and send this in the putc. Putc automatically accepts a 16bit value for the character when 'long_data' is selected. So:
Code: |
do {
while(bkbhit)
fputc( make16(1,(bgetc()),UART9.6 );
} while (TRUE);
|
Correction here (thinking about RS232 levels, not TTL async levels). You need to set the 9th bit as shown.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
pulurumbuluruciu
Joined: 06 Nov 2013 Posts: 27
|
|
Posted: Mon Dec 09, 2013 5:40 am |
|
|
Hi again. After 2 weeks of strugle..no..I did not solve it..:| How Is possible when I print from a buffer created by INT_RDA2 and put the character on Uart1 and then get it back(echo prevent), to get garbage in my UART1 data...!? if I do not get it back It will work ..but whyy? because is a buffer...is nothing "real time".
Code: |
#include <18F25K22.h>
#FUSES NOWDT, WDT128, INTRC_IO, NOFCMEN, NOIESO, NOHFOFST, NOMCLR, NOLVP, NOXINST
#use delay(clock=64000000)
#use rs232(uart1, BITS=8,baud=9600, PARITY=N, STOP=1, STREAM=U1,errors)
#use rs232(uart2, BITS=8,baud=19200, PARITY=N, STOP=1, STREAM=U2,errors)
#define BUFFER_SIZE 128
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
#int_rda
void RDA_isr(void) {
fputc(fgetc(U1),U2); // lower to higher baud-rate , no need to buffer.
}
#int_RDA2
void RDA2_isr(void)
{
int t;
buffer[next_in]=fgetc(U2);
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}
#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);
}
main(){
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
setup_adc_ports( NO_ANALOGS ); // disable analog inputs
enable_interrupts(INT_RDA2);
enable_interrupts(INT_RDA2);
enable_interrupts(GLOBAL);
while(true){
if(bkbhit==1){
DISABLE_interrupts(INT_RDA);
fputc(bgetc(),U1);
FGETC(U1);
ENABLE_interrupts(INT_RDA);
}
}
}
|
And I send maximum 50 char..not even the full 128 buffer... my hair starts to fall.. |
|
![](templates/subSilver/images/spacer.gif) |
|