|
|
View previous topic :: View next topic |
Author |
Message |
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
Using timed_getc with several software USARTs |
Posted: Thu Sep 01, 2005 7:08 am |
|
|
Hi,
Compiler: PCM 3.1619
My project consists of a PIC 16F877 which is the master PIC and three slaves ( one is a 16F877, the others are 16F628). I am using software USARTs to communicate with these PICs.
To receive data I am using the timed_getc() given in CCS help. Based on this I have written the following code for three software USARTs
Code: |
//The USART configuration is as follows. and is declared in the start of the code
#use rs232(baud=300,xmit=pin_c6, rcv=pin_c7,parity=n,stream=PC,errors)
#use rs232(baud=300,xmit=pin_c5, rcv=pin_c2,parity=n,brgh1ok,stream=LASER,INVERT)
#use rs232(baud=9600,xmit=pin_d0, rcv=pin_d4,parity=n,brgh1ok,stream=RHSROTATION,errors)
#use rs232(baud=9600,xmit=pin_d5, rcv=pin_d6,parity=n,brgh1ok,stream=LHSROTATION,errors)
char timed_getc(char cSelDevice)
{
long timeout;
timeout_error=FALSE;
timeout=0;
switch(cSelDevice)
{
case 'R': //Right Sensor
while(!kbhit(RHSROTATION)&&(++timeout<50000)) // 1/2 second
delay_us(10);
if(kbhit(RHSROTATION))
return(fgetc(RHSROTATION));
else
{
timeout_error=TRUE;
return(0);
}
break;
case 'L': //Left Sensor
while(!kbhit(LHSROTATION)&&(++timeout<50000)) // 1/2 second
delay_us(10);
if(kbhit(LHSROTATION))
return(fgetc(LHSROTATION));
else
{
timeout_error=TRUE;
return(0);
}
break;
case 'B': //Laser Controller
while(!kbhit(LASER)&&(++timeout<50000)) // 1/2 second
delay_us(10);
if(kbhit(LASER))
return(fgetc(LASER));
else
{
timeout_error=TRUE;
return(0);
}
break;
}
}
|
Is the above code OK ,if any modifications are required kindly post them...
thanks
arunb |
|
|
Ttelmah Guest
|
|
Posted: Thu Sep 01, 2005 8:48 am |
|
|
Within it's limitiations, it'll pretty nearly work as expected. The timeout will be somewhat more than 0.5 seconds in each loop, because the extra test in the loop will take time. It depends on your clock frequency, but at 4MHz for example, the timout will probably be nearly 1 second, rather than 0.5 seconds.
The main limitation, is that data _will_ be lost, unless you are sitting waiting in this loop for each device when it sends. Note also that the 'errors' directive, basically does nothing on the software UARTs. There are some wasted areas of code (for instance, there is no point in using the 'else' statement after each kbhit test, since you have already left the routine with 'return', in the case that data has been fetched. The optimiser may almost remove the extra code this generates, but it might save a byte or two to do this yourself.
Best Wishes |
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE; |
Posted: Fri Sep 02, 2005 2:08 am |
|
|
hi,
The trouble with the above piece of code is that I tend to get invalid characters, so I modified the use rs232 command by adding a force_sw and sample_early commands.
This improved matters and I received data correctly, but I noticed that data came out quite slowly.
My question is ..
a. Is the KBHIT function being used correctly, KBHIT(Stream)... ??
b. Do I have to put the #Use RS 232 diretive before each case statement in the timed_getc() function ??
Note: Crystal is 4 Mhz
Thanks
arnb |
|
|
Ttelmah Guest
|
|
Posted: Fri Sep 02, 2005 5:24 am |
|
|
If you are getting corrupted chaacters, and 'sample early' helps, then the characters have almost certainly started _before_ you call the routine.
Force_sw has no effect on pins that don't have hardware UART's.
It will be slow. At 300bps, a character will take approximately 33000 instruction times to arrive.
Yes, kbhit(stream) is correct (provided your compiler is reasonably recent), and the stream ability removes the need for seperate USE_RS232 statements inside the code.
Best Wishes |
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE; |
Posted: Sat Sep 03, 2005 1:33 am |
|
|
Hi,
Thank you for the help.
I noticed that force_sw delayed the transmission (even at 9600 bauds), also sometimes commands where entirely ignored.
The slave PICs send an acknowledge character immediately after receiving a command from the master, there could be a slight delay in the reciving part and the processing, say a few instructions.
Please note the slave PICs use INT_RDA to receive commands.
Do you think a slight delay of a few milliseconds just after receiving should improve matters ??
thanks
arunb |
|
|
Eugeneo
Joined: 30 Aug 2005 Posts: 155 Location: Calgary, AB
|
|
Posted: Mon Sep 05, 2005 1:49 am |
|
|
I don't know if this is really necessary but at those baud rates and that processor, you may should be able to go to 20 mhz, use 2 of your timers and with the INT_CCP for input 1, IN_EXT for input 2. Use hardware usart for input 3. And bit bang input 1&2. This way you won't miss any data. |
|
|
Ttelmah Guest
|
|
Posted: Mon Sep 05, 2005 4:48 am |
|
|
I'd try with something like this:
Code: |
//The USART configuration is as follows. and is declared in the start of the code
#use rs232(baud=300,xmit=pin_c6, rcv=pin_c7,parity=n,stream=PC,errors)
#use rs232(baud=300,xmit=pin_c5, rcv=pin_c2,parity=n,stream=LASER,INVERT)
#use rs232(baud=9600,xmit=pin_d0, rcv=pin_d4,parity=n,stream=RHSROTATION)
#use rs232(baud=9600,xmit=pin_d5, rcv=pin_d6,parity=n,stream=LHSROTATION)
//brg10Kh only applies when you are using a baud rate generator.
//Similarly 'errors' only applies with a hardware UART.
char timed_getc(char cSelDevice)
{
long timeout;
timeout_error=FALSE;
timeout=0;
switch(cSelDevice)
{
case 'R': //Right Sensor
while(input(PIN_D4)&&(++timeout<50000)) // 1/2 second
delay_us(2);
if(input(PIN_D4)) {
timeout_error=TRUE;
return(0);
}
else
return(fgetc(RHSROTATION));
break;
case 'L': //Left Sensor
while(input(PIN_D6)&&(++timeout<50000)) // 1/2 second
delay_us(2);
if(input(PIN_D6)) {
timeout_error=TRUE;
return(0);
}
else
return(fgetc(LHSROTATION));
break;
case 'B': //Laser Controller
while(!input(PIN_C2)&&(++timeout<50000)) // 1/2 second
delay_us(2);
if(input(PIN_C2))
return(fgetc(LASER));
else
{
timeout_error=TRUE;
return(0);
}
break;
}
}
|
This uses direct input, rather than 'kbhit' to check for the line changing. Though the compiler ought to optimise this fairly well, it'd be interesting to see if this improves things. Also the delay count is reduced to allow for the time taken in the test. My 'guess' would be that the test for the 'edge', would take about two to four instructions, while the increment, and test, could easily take another six or more instructions. With the delay in the loop, and the jump time itself, this means that the loop, is probably taking something more in terms of 20 to 30uSec. As such, on the existing code, if the edge goes 'active', immediately after the last test, it'll not actually start reading the character, for perhaps 40 to 50uSec (once round the loop, jump to exit, test again, then start the actual sample), which may be why 'sample early' is helping. Reducing the delay, should improve this.
Best Wishes |
|
|
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE: |
Posted: Mon Sep 05, 2005 8:44 am |
|
|
Hi,
I solved the problem, here is what I did..
I retained the original code, as posted, but I delayed the transmission in the slave PICs by 100 micro seconds. This solved the problem, firstly there was no delay in receiving
the characters, and also I received no un wanted characters..
Thanks a lot for the help and suggestions...
arunb |
|
|
|
|
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
|