CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

AT help

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
milkman41



Joined: 16 Jun 2008
Posts: 30

View user's profile Send private message

AT help
PostPosted: Tue Jul 22, 2008 1:37 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 22, 2008 5:55 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Jul 23, 2008 9:33 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jul 24, 2008 9:44 am     Reply with quote

*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

View user's profile Send private message

PostPosted: Thu Jul 24, 2008 10:48 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jul 24, 2008 11:19 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Jul 24, 2008 1:36 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jul 25, 2008 8:02 am     Reply with quote

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

View user's profile Send private message

PostPosted: Fri Jul 25, 2008 11:51 am     Reply with quote

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 Confused . 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

View user's profile Send private message

PostPosted: Sun Jul 27, 2008 4:05 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Jul 28, 2008 1:02 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Mon Jul 28, 2008 4:04 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Jul 29, 2008 10:42 am     Reply with quote

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! Very Happy
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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