View previous topic :: View next topic |
Author |
Message |
Arclite
Joined: 02 Jul 2004 Posts: 16 Location: UK
|
RS232 reception problem |
Posted: Tue Dec 07, 2004 8:14 pm |
|
|
Hi guys,
I have an RS232 port defined as:
Code: |
#USE rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7, bit=8, stream=rsMOD)
|
and i want to send an AT msg to it like:
Code: |
#define AT "AT"
fprintf(rsMOD,AT);
fprintf(rsMOD,"\r"); // the <CR>
// This works!
|
then i am waiting for the "OK\r" on the receive pin using:
Code: |
fgets(InString,rsMOD);
// Then use 'strstr' to compare the returned msg with the expected "OK"
// or use an error handler
|
I am able to group these instructions several times to set up the modem, when the PIC is connected to a PC (hyper terminal), but i can't get past the first group when connected directly to the modem.
When connected to hyper terminal, if i punch the required responses on the keyboard, the PIC runs through the code with no problem. Do i need to check some flag or set some delay cycles?
I'm thinking of using the kbhit() func, but i'm sure there is a more orthodox method.
I'm not using the interrupt RDA yet as i want to set that up for a different function, so how can i do it?
Regards. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Tue Dec 07, 2004 8:58 pm |
|
|
Are you changing cables when you go from the PC to the modem?
The PC appears as a DTE device, the modem appears as a DCE device. So when the PIC is talking to the PC it must emulate a DCE and when talking to the modem the PIC must emulate a DTE. If you are not using any hardware handshaking and the modem is configured for software only then this means the only signals that need to be transposed are the transmit and receive.
Have you tried communicating between the PC and the modem at 9600 baud? Some modems will autobaud at higher baud rates such as 56K and 115K but will not operate at 9600 unless specifically configured. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Arclite
Joined: 02 Jul 2004 Posts: 16 Location: UK
|
All of the wiring is correct |
Posted: Wed Dec 08, 2004 9:12 am |
|
|
Hi asmallri,
The wires are in the right places, and the comm ports are all the same setting.
The main feature of the problem is that when i type in the "OK" to the PIC-PC link via hyper terminal, everything works. I get the same problem when i type the responses very quickly in the PIC-PC link as the PIC -Modem link would.
So i think i need some sort of delay, what's your opinion?
Regards. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1635 Location: Perth, Australia
|
|
Posted: Wed Dec 08, 2004 9:28 am |
|
|
I wouldn't try to solve this with delays. If the PIC you are using has a hardware USART then you should look at using receive interrupts and adding received characters to the a buffer until you get around to processing them. If the PIC does not have a hardware USART then you the use #use rs232 implementation can be transmitting or receiving but not both simultaneously. With a software USART imp[lementation you need to call kbhit() at better than tem times the bit rate to ensure you do not miss characters. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Dec 08, 2004 10:00 am |
|
|
So are you saying that the code gets stuck at the fgets() call?
Also, you should add the ERRORS parameter to your #use RS232 statement. |
|
|
Arclite
Joined: 02 Jul 2004 Posts: 16 Location: UK
|
|
Posted: Wed Dec 08, 2004 10:57 am |
|
|
Hiya,
Mark : yes the program stops at the fgets(.... I put an LED on before and after the second fgets(.. and the progam halts, illuminating the 1st LED but not the second.
Asmallri: i really need the interrupt for a different job using a larger message string structure. So if i can find different method to get around it, i would be happy with that.
Regards. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Dec 08, 2004 11:40 am |
|
|
Did the ERRORS make any difference? If you get an overflow, the receive is going to stop unless you add ERRORS to the #use. |
|
|
Arclite
Joined: 02 Jul 2004 Posts: 16 Location: UK
|
|
Posted: Wed Dec 08, 2004 4:55 pm |
|
|
Hi Mark,
Checked and done what you had said. It doesn't make a difference.
I think it has something to do with the 'fgets()' function. It uses getc() until it reads a 'return' <13> value and puts what it has read into a string.
According to the manual.
The modem returns using <CR><LF> at the start and end of each response.
If that is the case, i'll have to write my own function to process the string modelled on gets(), to avoid the first <13> and read all of the return string.
I am surprised that the prog even got thro' the 1st gets().
I'll inform of the results i get.
Regards. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Wed Dec 08, 2004 6:19 pm |
|
|
Quote: | I am surprised that the prog even got thro' the 1st gets().
|
I'm not. It read up to the <CR> and then stopped. The receive buf of the UART still had the <LF> in there. Then you sent another command and some more data was sent to the PIC probably overwriting the the <LF> causing a buffer overflow. At that point the receive is going to stop. Now if you put the ERRORS parameter in the #use RS232 it should take care of the overflow. However, if you missed the <13> because of the overflow, then you'll be stuck sitting there waiting for it.
Quote: | I wouldn't try to solve this with delays. If the PIC you are using has a hardware USART then you should look at using receive interrupts and adding received characters to the a buffer until you get around to processing them. |
Follow his advice. He knows what he is talking about and I agree with him.
Quote: | Asmallri: i really need the interrupt for a different job using a larger message string structure. So if i can find different method to get around it, i would be happy with that.
|
This doesn't matter. The INT is for that UART. Receiving data is receiving data. Its up to you to handle it. You only get about 2 bytes of buffing with the hardware. Using the INT, you can create a buffer much larger and avoid missing the data due to the overruns. |
|
|
Arclite
Joined: 02 Jul 2004 Posts: 16 Location: UK
|
Used interrupt RDA, and problem persists. |
Posted: Sun Dec 12, 2004 3:31 pm |
|
|
Hiya,
I have designed my code to use the interrupt RDA for my modem activities as you recommended.
Code: |
char InMSG[60];
BYTE next_in=0;
BYTE next_out=0;
#int_RDA
RDA_isr()
{
int t;
InMSG[next_in]=getc();
t=next_in;
next_in=(next_in+1) % sizeof(InMSG);
if(next_in==next_out)
{
next_in=t;
}
}
|
When i had altered the rest of the code to accept it, the results were the same. It would hang after sending the 1st command to the modem, ie "AT\r\n"
I had used "ERRORS" in the "#use RS232" line with no improvement. Now i believe that it clears any frame or overrun error in the comms h/w.
Given that there was no change in the performance, i removed the "ERRORS" flag, and used my own function that lights up an LED when either error bit OERR or FERR are thrown, toggling CREN if required to reset the operation. The LED did not light=> no error.
So i think the problem is with the "string" part of the code. I use the comm port to read a response into the InMSG string.
When i first use the InMSG string there will be the response in the first 5 elements, and garbage in the other 55, one might be a Null character.
When i used the "strstr" command to compare to "\r\nOK\r\nNULL", i am supposed to use Null terminated strings, am i correct?
Then i clear the string InMSG (set all elements to Null ie 0), then send my next command, and wait for the next response. I know a response is obtained via a comm port "tap", but still i can't get past the second "strstr" command.
If i don't clear the InMSG string and let it filter through, the device appears to have setup correctly.
In short, my questions are:
How do i clear the InMSG for later reuse in similar strstr checks?
Do i have to reset next_in and next_out when i clear the InMSG string?
Regards |
|
|
Arclite
Joined: 02 Jul 2004 Posts: 16 Location: UK
|
One other thing... |
Posted: Sun Dec 12, 2004 4:03 pm |
|
|
I send "AT\r\n" to the modem, and i get an "\r\nOKr\n" AND an "..AT.." sent back, whats going on here? |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Sun Dec 12, 2004 6:04 pm |
|
|
You probably have echo on. There is a command to turn it off. |
|
|
Arclite
Joined: 02 Jul 2004 Posts: 16 Location: UK
|
I think i've cracked this one! |
Posted: Mon Dec 13, 2004 9:22 am |
|
|
Hi Mark,
I have solved most of this stupid problem, and you were correct about the OERR overrun bit. When i had tested the OERR bit earlier, the bit definition was wrong by one byte, so OERR went undetected. Wasn't ERRORS supposed to handle that?
Anyway the code runs through all the modem start-up code with no fault and sends an SMS txt out on completion.
I have code setting up looking like:
Code: |
#int_RDA
RDA_isr()
{
InMSG[next_in]=getc();
if(OERR)
{
CREN=0;
CREN=1;
}
else
{
if(FERR)
{
}
else
{
next_in=(next_in+1) % sizeof(InMSG);
}
}
if(next_in==Next_out)
{
next_in=0; // Circular buffer
}
}
...
// Send 1st msg
OKd=FALSE;
do{
fprintf(rsMOD,"AT\r\n");
// interrupt RDA reads at this point
if(strstr(InMSG,AuxStr))
{
fputs("AT Ok'd",rsCOM);
OKd=TRUE;
}
else
{
fputs("AT Failed",rsCOM);
}
}while(!OKd);
...
|
Is there a faster/better way to code this to avoid the OERR error?
It took 2 days to do all of this in assembler and ages in CCS. I thought the purpose of having a high level complier was to take out the nitty-gritty, and let you code the app. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Dec 13, 2004 10:00 am |
|
|
Quote: | ...so OERR went undetected. Wasn't ERRORS supposed to handle that? | The ERRORS directive does reset the OERR-flag, so if this didn't work in your code you probably made a mistake. In all the above posted code samples you never showed a line using the ERRORS directive so we can't check this.
Code: | if(next_in==Next_out)
{
next_in=0; // Circular buffer
} | I'm not sure what you want to achieve here, but this certainly is not a circular buffer...
Code: | // interrupt RDA reads at this point
| Yes, the RDA interrupt will start reading data, but this takes some time. Between sending the command and receiving the response you should implement some kind of flow control. Your current code will never work the way you expect it to.
Quote: | Is there a faster/better way to code this to avoid the OERR error? | Create a working circular buffer implementation and make sure to calculate the required buffer size. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Mon Dec 13, 2004 11:22 am |
|
|
Quote: | It took 2 days to do all of this in assembler and ages in CCS. I thought the purpose of having a high level complier was to take out the nitty-gritty, and let you code the app. |
My answer to this, it would have taken me less than an hour to code and debug a routine for setting up a modem. Why, because I understand the chip and the compiler. C does make it much nicer and easier to maintain the code but a new commer can't expect to be up and running on day one. You can't run until you learn how to walk. |
|
|
|