|
|
View previous topic :: View next topic |
Author |
Message |
milkman41
Joined: 16 Jun 2008 Posts: 30
|
AT help |
Posted: Tue Jul 22, 2008 1:37 pm |
|
|
Hey all, I'm having trouble with my code, I'm trying to communicate with a modem and I'm not quite getting it to work. However, whenever I use the program in 'manual' mode, ie use HyperTerm to enter the messages I want to send from the modem, it works beautifully, it just doesn't work when I try sending messages through the modem (actually, modem simulator on the comp. Here is a simple version of my code:
Code: |
#include <protoalone.h>
#include <utility.c>
#define MESSAGE_LENGTH 48
int buffer_in_use=0;
char message[2][MESSAGE_LENGTH];
int1 message_available=0;
#int_rda
void serial_gets_isr(void) {
char temp_chr;
static int input_locn=0;
temp_chr = getc(); //receive the _one_ character
message[buffer_in_use][input_locn++]=temp_chr; //add it to the buffer
if (input_locn>(MESSAGE_LENGTH-1)) input_locn=MESSAGE_LENGTH-1;
//If more than 'buffer' characters arrive, the data will be clipped at the
//size of the buffer.
if (temp_chr=='\n' || temp_chr=='\r' || temp_chr=='\0') {
message_available=1;
message[buffer_in_use][input_locn]='\0'; //null terminate the string
buffer_in_use^=1;
input_locn=0;
}
}
void main() {
int8 buffer_not_in_use;
int i = 0;
enable_interrupts(int_rda);
enable_interrupts(global);
printf("AT+SBDI\r");
printf("AT+SBDRT\r");
while(TRUE) {
delay_ms(4000);
output_high(RED_LED);
if (message_available) {
output_low(RED_LED);
//Now, the whole message, is sitting in the buffer 'not' in use
message_available=false; //must clear this ASAP
buffer_not_in_use=buffer_in_use^1; //select the buffer
//printf("%s",&message[buffer_not_in_use][0]);
for(i = 0; message[buffer_not_in_use][i] != '\0'; i++) {
//printf("\r\n%c", message[buffer_not_in_use][i]);
if(message[buffer_not_in_use][i] == '*') {
output_low(GREEN_LED);
if(message[buffer_not_in_use][i+1] == '*')
flash_leds();
}
}
}
}
}
|
When I use it in HyperTerm, everything works as it should, but when I use it with the modem, only the red led (message available) lights up.
Last edited by milkman41 on Thu Jul 24, 2008 9:46 am; edited 2 times in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 22, 2008 5:55 pm |
|
|
My advice is to strip down your program and make a program that only
tests the input parsing. Get rid of all the X10 stuff.
Also there are many inefficient lines of code in your program. You read
from the same array location over and over. It's better to read it once
at the start of the loop and put it in a temp variable (int8). Then do your
comparsions on this short little variable. It makes the code a lot easier
to read and understand.
Also, you need to learn about the toupper() function. When you read
the byte from the array, run it through toupper() which will convert it
to upper case. Then you don't have to test both upper and lower case.
You can just do one test for the upper case value. Look in the CCS
manual for information on toupper().
I don't want to fix your code for you. I just want to give some tips on
how to make it easier to understand, so you can fix it.
If you have more questions then post them in this same thread.
Don't start a new thread on the same topic every few days. |
|
|
milkman41
Joined: 16 Jun 2008 Posts: 30
|
|
Posted: Wed Jul 23, 2008 9:33 am |
|
|
I edited the first post to show the simplified program I'm using, it just checks for a '*', and if this happens, the leds will flash.
Also, I realize the first code I posted was slightly inefficient, especially with the array thing (which I have changed, should have that of that earlier, haha), but I'm pretty much a newbie at this programming thing, so I frankly don't really know what I'm doing with this stuff, I just need to get it to work, haha. |
|
|
milkman41
Joined: 16 Jun 2008 Posts: 30
|
|
Posted: Thu Jul 24, 2008 9:44 am |
|
|
*bump*
The program is apparently recieving messages, since the red LED goes high, but its still not flashing the LEDs as it should, so theres still something wrong, anybody know what? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 24, 2008 10:48 am |
|
|
1. Post the #include, #fuses, #use delay() lines. If those are in the
protoalone.h file, then post that file.
If anything in utility.c is used, then post the portions that are used.
In other words, post enough additional code so that your program
can be dropped into MPLAB and compiled without errors.
2. Post your compiler version. |
|
|
milkman41
Joined: 16 Jun 2008 Posts: 30
|
|
Posted: Thu Jul 24, 2008 11:19 am |
|
|
oh yes, of course, sorry about that, here are the protoalone.h and utility.c files.
protoalone.h:
Code: |
#include <16f877A.h>
#fuses HS,NOLVP,NOWDT,PUT,NOPROTECT
#use delay(clock=20000000)
#use rs232 (baud = 9600, xmit=PIN_C6, rcv=PIN_C7)
#define GREEN_LED PIN_A5
#define YELLOW_LED PIN_B4
#define RED_LED PIN_B5
#define PUSH_BUTTON PIN_A4 |
utility.c (used parts):
Code: |
void flash_leds() {
light_one_led(GREEN);
delay_ms(50);
light_one_led(YELLOW);
delay_ms(50);
light_one_led(RED);
delay_ms(50);
light_one_led(GREEN);
delay_ms(50);
light_one_led(YELLOW);
delay_ms(50);
light_one_led(RED);
delay_ms(50);
output_high(RED_LED);
} |
It is possible that my fuses aren't condusive to what I'm trying to do, I do really know what they all do, but I've used them for everything else and they seem to work fine, so yeah. The compiler version is version 4.058s.
I don't know if its my code that's wrong, it could very well be the modem simulator I'm using, if that's the case, that would be wonderful, haha, cuz then my code would be working! :p
thanks,
-Nick |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 24, 2008 1:36 pm |
|
|
Quote: |
When I use it in HyperTerm, everything works as it should, but when I
use it with the modem, only the red led (message available) lights up. |
Try to determine the differences between the modem simulator and
HyperTerminal. Did you create the modem simulator ? Is it another PIC ?
Capture the messages (include control characters) from the modem
simulator and compare them to the characters that you send with Hyperterminal. Are they the same ?
What is the interval between characters and between messages for
the modem simulator ?
Basically, the reason it works with one method and doesn't work with
another will likely be:
1. Different characters (possibly control characters) in the messages.
2. Different interval between characters and/or messages. |
|
|
milkman41
Joined: 16 Jun 2008 Posts: 30
|
|
Posted: Fri Jul 25, 2008 8:02 am |
|
|
The simulator was created by someone else, someone who presumably knows what they're doing (unlike me :p), and it is on the computer. The company I work at uses it often for their products, so it seems to be reliable. Right now I'm workin on figuring out the differences between the characters from the simulator and from HyperTerm.
Other than that, does my code look good? |
|
|
milkman41
Joined: 16 Jun 2008 Posts: 30
|
|
Posted: Fri Jul 25, 2008 11:51 am |
|
|
I wrote the messages into an external EEPROM chip that came with the development kit I go, and then read them with another program, and apparently all the PIC received from the modem simulator was a new line character ('\n'), so Im guessing I'm not using the modem simulator correctly/it was not designed to do this. Unfortunately there is no help file for the simulator, so I'm kind of stuck . However, it seems as if this is all that is wrong (I don't know), so that's a positive.
Thanks,
-Nick |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sun Jul 27, 2008 4:05 pm |
|
|
A minor remark:
Add the ERRORS directive to the #use RS232 line so the compiler adds code to clear some common errors. Very unlikely, but if your program is slow in reading the UART the UART will stall when the receive buffer is full with three characters. Without the ERRORS directive the UART will never restart and your program stalls.
A major design flaw is in the code for switching the receiver buffers: Code: | if (temp_chr=='\n' || temp_chr=='\r' || temp_chr=='\0') { | Many PC based systems will terminate a line by sending two characters, CR +LF ('\n' and '\r'). If this happens than both your receive buffers are filled but there is only a single flag for marking a message being available. Result is you are loosing one message. This might explain why you are seeing a single '\n'.... |
|
|
milkman41
Joined: 16 Jun 2008 Posts: 30
|
|
Posted: Mon Jul 28, 2008 1:02 pm |
|
|
ckielstra wrote: | A minor remark:
Add the ERRORS directive to the #use RS232 line so the compiler adds code to clear some common errors. Very unlikely, but if your program is slow in reading the UART the UART will stall when the receive buffer is full with three characters. Without the ERRORS directive the UART will never restart and your program stalls.
A major design flaw is in the code for switching the receiver buffers: Code: | if (temp_chr=='\n' || temp_chr=='\r' || temp_chr=='\0') { | Many PC based systems will terminate a line by sending two characters, CR +LF ('\n' and '\r'). If this happens than both your receive buffers are filled but there is only a single flag for marking a message being available. Result is you are loosing one message. This might explain why you are seeing a single '\n'.... |
Thanks for the reply, that sounds like it could be why it wouldn't work, how should I get around that? I was thinking something along the lines of
Code: | if (temp_chr=='\n' || temp_chr=='\r' || temp_chr=='\0') {
message[buffer_in_use][input_locn] = toupper(getc()); //Get the next character
input_locn++;
if (temp_chr=='\n' || temp_chr=='\r' || temp_chr=='\0') {
//here execute the rest of the original buffer code
|
I haven't tested this yet because I've been busy with other things, do you think this work? If not, how could I take into account the fact that the PC will send '\n''\r'? Also, once I connect it to the modem itself, it will not be necessary to capture both, will it? I mean, will the modem will only send one character?
Thanks,
-Nick |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Mon Jul 28, 2008 4:04 pm |
|
|
Don't call getc twice in the interrupt routine as this will delay the interrupt till the second character is received. You shouldn't introduce such kind of delays.
What you want to do with received '\0' characters is a design issue. Normally in an AT-command interface you wouldn't see this character unless it is part of a binary stream and then it's not the end of a string and you have to keep it. I don't know your system specifications so can't tell you how to handle the zero.
Note that UNIX and UNIX-like systems use 0x0A (a single New Line character) to terminate a line while most other systems (Windows, etc) use a combination of 0x0D / 0x0A (Carriage Return + Line Feed).
You could try to make your program universal by throwing away the received 0x0D character.
I think I would change the start of the interrupt routine to something like: Code: | temp_chr = getc(); //receive the _one_ character
if (temp_chr=='\r') // Ignore line feed character and exit
return;
message[buffer_in_use][input_locn++]=temp_chr; //add it to the buffer
//If more than 'buffer' characters arrive, the data will be clipped at the
//size of the buffer.
if (input_locn>(MESSAGE_LENGTH-1))
input_locn=MESSAGE_LENGTH-1;
if (temp_chr=='\n') {
... your original code
|
|
|
|
milkman41
Joined: 16 Jun 2008 Posts: 30
|
|
Posted: Tue Jul 29, 2008 10:42 am |
|
|
Hey man thanks alot thats flippin genius, haha, the program works better now, I can now read what comes into the buffer, so thats better. Unfortunately, its still not working as I want it too, as all Im getting back is "SDBRING\n123,1,456,4,1", and I can't send the message :\. I think it might be the simulator or something though, I'll check it out, but once again, thanks alot man! |
|
|
|
|
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
|