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 CCS Technical Support

RS232

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



Joined: 23 Aug 2005
Posts: 93

View user's profile Send private message Visit poster's website

RS232
PostPosted: Mon Jan 02, 2006 7:07 am     Reply with quote

Hi, I'm trying to get a interrupt driven (UART in 16F876A) to trigg an external function.
But I want to save the chars in the buffer, and use them in the function.
The incomming chars are, /?! CR LF, I tryed to read them into a global buffer, end then compare against a string, but it wont work.
If I only read them into that buffer in ISR() and then compare against a couple of chars (?!) it works fine. But I need to have the possibility to compare against a whole string later.
Do anyone has an idea why it wont work?
Code:
in main file:
#use rs232(baud=300, xmit=PIN_C6, rcv=PIN_C7, bits=7, parity=E, ERRORS)
#int_rda
void serial_isr() {
rs232_flag=ON;
}
Then I poll for that flag in main and jump to:
void func(){
char i, sign, string[], string1[];

strcpy(string1, "/?!");
get_str(string,BUF_SIZE);
if(!strcmp(string, string1))
// 1. All must respond with ID
printf(USER_ID"\n\r");
//2. If ACK
sign=getc();
if(sign==0x06){ //if it wants to speak, ASCII for ACK
}
The code has been cut down for easy reading
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Mon Jan 02, 2006 9:26 am     Reply with quote

First of all: when posting source code use the 'code' button, this ensures your code will be easier to read.

Setting a flag in your interrupt routine and then polling this flag in the main routine is not a good way of handling serial communications, among several other problems your main function might be too slow in responding and you miss data.

A better way for handling the serial port is to have your interrupt routine fill a buffer and then handle the contents of this buffer from your main function. For the buffer you can use either a linear or circular buffer type, see this thread for a description of when to use which buffer type.

An example of a circular buffer implementation is ex_sisr.c in the CCS example directory. An explanation of the internal workings of this example is given at http://www.ccsinfo.com/forum/viewtopic.php?t=19083

An example of a linear buffer can be found in the post of Humberto in http://www.ccsinfo.com/forum/viewtopic.php?t=19117

Searching this forum you can find many more circular buffer implementations.
Tagge



Joined: 23 Aug 2005
Posts: 93

View user's profile Send private message Visit poster's website

PostPosted: Tue Jan 03, 2006 4:25 am     Reply with quote

Thanks, god hints. But I still think I have to have a flag in the isr(), because I cant do all things in isr, it would take to long time?
And I must know when a string has arrived. Or the right sequence of chars. The incoming string can be from 4 to 32 bytes(chars), starts with a '/' and ends with a CR and then a LF.
Can I decode this string in the isr(), by get_string(), it doesnt seem to work with this strings, and inside a isr()??
beside the strings arrive in between 10-20sec, good time to poll for the flag?
The string is by the format of: 1 start bit, 7-data, 1 par, 1 stop.
Code:

#use rs232(baud=300, xmit=PIN_C6, rcv=PIN_C7, bits=7, parity=E, ERRORS)
#int_rda
void serial_isr() {
   
  buffer[next_in]= getc(); 
 
  if(buffer[next_in]=='!' && buffer[next_in-1]=='?')  //look for this chars
      rs232_flag=ON;           
  if(buffer[next_in]=='\n')
   next_in=0;   
   
   if(next_in==BUFFER_SIZE)
     next_in=0;           // Buffer full !!
   
   next_in++; 
}
main(){
 if(rs232_flag=ON)
   func();
//.......
}
 void func(){
//checking for a special string
//would like to use the bufferd chars or
// by get_string()....
//      if(strcmp(!str1, str2)).....

 rs232_flag=OFF;  //reset flag
 for(i=0;i<=BUFFER_SIZE;i++)  //clear buffer
   buffer[i]=0;
}
Ttelmah
Guest







PostPosted: Tue Jan 03, 2006 5:13 am     Reply with quote

The normal approach, assuming the incoming data follows some known 'format', is to use a 'state machine' in the ISR. What happens is that the first time the routine is called, the 'state' is 0, and in this state, it checks the single character, against 'acceptable' first characters. If the character is recognised, the state is advanced, and the routine exits. For each character as it arrives, there is a similar behaviour. So (for instance), you could have a string, that if it begins with 'n', then has a 3 digit number. The state machine when it finds 'n' in the incoming data, moved the state, to one which saves the next three digits as a number, and then starts looking for the next 'key' value.
Done properly, each state, needs only check one character, and the state value. Though it still makes the ISR slower than may be 'ideal', this can easily handle complex input tasks. As an example, I have one, looking for 'keywords' in an input stream, which uses an alphabetically organised table of words, and a row/column counter. It 'walks' the table with subsequent characters, to either find a match, or fail.

Best Wishes
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