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

what way is best to read incoming rs232 data

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



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

what way is best to read incoming rs232 data
PostPosted: Wed Nov 15, 2006 1:35 am     Reply with quote

Hi all
Thanks for all your help so far i am still learning the tricks of C
i just want some advise on how to go about reading in rs232 data
i have a 16bit variable that i need to update via rs232 example if i receive FFFF i want to update my variable to have the value FFFF
but i am having problem geting the data from the EX_SISR.C example
could someone please point out to me were i am going wrong
here is my program below

#if defined(__PCM__)
#include <16F877.h>
#ORG 0x1F00,0x1FFF {} // use boot loader for the 8k 16F877
#fuses XT,NOWDT,NOPROTECT,BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // Jumpers: 8 to 11, 7 to 1


#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;


#int_rda
void serial_isr()
{
int t;

buffer[next_in]=getc();
t=next_in;
next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out)
next_in=t; // Buffer full !!
}

#define bkbhit (next_in!=next_out)

BYTE bgetc() {
BYTE c;

while(!bkbhit) ;
c=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(c);
}



void main() {

enable_interrupts(global);
enable_interrupts(int_rda);
int16 mydata;

printf("\r\n\Main Program Running...\r\n");

// The program will delay for 10 seconds and then display
// any data that came in during the 10 second delay

do {
delay_ms(10000);

while(bkbhit)
mydata=putc( bgetc() );


} while (TRUE);
}
_________________
BOB_Santana Smile
ckielstra



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

View user's profile Send private message

PostPosted: Wed Nov 15, 2006 3:15 am     Reply with quote

When posting souce code please use the 'code' button, this will help to preserve formatting and makes for easier reading.

There are two problems in the code below
Code:
while(bkbhit)
    mydata=putc( bgetc() );
1) You assign the return value of putc() to mydata instead of the return value of bgetc().
2) bgetc() returns an 8-bit value while you want a 16-bit value.

Problem 1 can be solved by changing the code to:
Code:
while(bkbhit)
{
  mydata = bgetc();
  putc( mydata );
}


Problem number 2 is a bit more difficult to tackle because you have to think about what to do in error situations where you only receive 1 byte? Or, what to do when 1 byte is lost and you get out of sync?
The best way to solve this is to not just send a value over the serial line but create a simple protocol. For example only accept the value when it is followed by a carriage-return character:
- byte 1, byte 2, CR
Guest








PostPosted: Wed Nov 15, 2006 3:58 am     Reply with quote

You can read the data in as a string and then convert string to hex[/quote]
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Wed Nov 15, 2006 3:27 pm     Reply with quote

ckielstra wrote:
When posting souce code please use the 'code' button, this will help to preserve formatting and makes for easier reading.

Sorry about that i have onlyjust found out about it as you mentioned it and i would use it in future newbie thats me:)


Problem number 2 is a bit more difficult to tackle because you have to think about what to do in error situations where you only receive 1 byte? Or, what to do when 1 byte is lost and you get out of sync?
The best way to solve this is to not just send a value over the serial line but create a simple protocol. For example only accept the value when it is followed by a carriage-return character:
- byte 1, byte 2, CR


I ws thinking of using reading the data in as a string then read it into an array.
Since i know what the length of my string should be i can do a check to make sure the lenght is the correct lenght .
my major problem with doing it that way as Guest suggested is that
i don't know how i would convert each character to correct hex value
bearing in mine that the values that i would receive would be something like this say FFED where FF i can map to mydata[0] & ED to mydata[1]
those i would then send to my 2 74hc595 shiftreg until the next set of data arrives.
Any pointers would be a great help
_________________
BOB_Santana Smile
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Mon Nov 20, 2006 5:02 pm     Reply with quote

Hi all
Could someone please help me with this program using serial interupts
i am trying to capture a string use the rs232 interupt but the problem
is that i want my main program to be running continously and the string captured only on interupt could you help

Code:
#if defined(__PCM__)
#include <16F877.h>
#ORG 0x1F00,0x1FFF {} // use boot loader for the 8k 16F877
#fuses XT,NOWDT,NOPROTECT,BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 1
#include <input.c>
#include <string.h>
#include <stdio.h>
/////////////////////////////////////

#define BUFFER_SIZE 10
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;


#int_rda
void serial_isr()
{
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}




////////////////////////////////////

void main()
{
  char string[BUFFER_SIZE];

   enable_interrupts(global);
   enable_interrupts(int_rda);
 
while(1)
  {
    printf("please type a string1 ");
    delay_ms(1000);
    printf("please type a string2  "); // JUST TO SEE PROGRAM RUNNING IN BACK GROUND
    // Wait for a key press
    while(!kbhit());                  // do this part only on interupt
    {
    get_string(string, BUFFER_SIZE);
    printf("\r\n%s\r\n",string);
    }
  }
}

_________________
BOB_Santana Smile
PCM programmer



Joined: 06 Sep 2003
Posts: 20604

View user's profile Send private message

PostPosted: Mon Nov 20, 2006 5:57 pm     Reply with quote

A problem with your code is that instead of trying to understand
what each function does, you've just sort of tossed in lines of code
and routines. This will never work. For example, you've taken
the #int_rda routine from the Ex_Sisr.c example file, but you didn't
look at how that example determines if characters are available in
the buffer, and how it then gets characters from the buffer.
Then you've stuck in the get_string() function from Input.c, but
Ex_Sisr.c and get_string() are two different ways of getting characters.
They're not related. They don't work together. You can't just
toss them into a program and expect it to work.
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Tue Nov 21, 2006 5:15 am     Reply with quote

Hi PCM

I did tried but was getting a bit lost in the program
from my understanding of the EX_SISR.C example
So let me start again an explain myself just give me a chance i want to understand this let take the EX_SISR.C again

Code:


#if defined(__PCM__)
#include <16F877.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)  // Jumpers: 8 to 11, 7 to 12


#define BUFFER_SIZE 10
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;


#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}

#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}



void main() {

   enable_interrupts(global);
   enable_interrupts(int_rda);

   printf("\r\n\Running...\r\n");

               // The program will delay for 10 seconds and then display
               // any data that came in during the 10 second delay

   do {
      delay_ms(10000);
      printf("\r\nBuffered data => ");
      while(bkbhit)
        putc( bgetc() );
   } while (TRUE);
}



From my understand of this program there are 2 functions

Code:


#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out)
     next_in=t;           // Buffer full !!
}


On there being a character of the program jumps to this interupt service rountine.
In the routine it uses buffer[next_in]=getc() to store the characters into
the array which can hold up BUFFER_SIZE , Is this right ?

The other function bgetc() is only use to read the characters out of
the array when this function is called it returns one character at a time through its return value which is c is this right ?

Code:

#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}



so bgetc() only gets called in the main program to display the contents of the array buffer[]
so i thought that those content could be called using the get_string()
if they were declared as string in the first place
I know i and wrong but i want learn how to fish
_________________
BOB_Santana Smile
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Tue Nov 21, 2006 9:06 am     Reply with quote

The goal of the buffer is to allow the code you have in your main section to
get a chance to run with some independence of the rs232 hardware constraint that a char must be read before the next is received.
Now this could be done by a polling loop in main without using an interrupt.
The disadvantage is that a character can be received at any time so unless the loop executes fast more than one char might be received before your code gets to the point of accepting the earlier one. An interrupt avoids this providing fast capture of any received character and placement of the char in a circular buffer. The buffer may appear linear but the modulo arithmetic on the buffer size means that the placement pointer rolls over to the begining
like a dog chasing its tail. A read pointer is maintained and it also rolls over.
As the buffer fills the placement pointer moves up. As data is read the read pointer chases the placement pointer. As long as on average the read pointer can keep pace with the placement pointer the placement pointer will not lap the read pointer. So the buffer allows RS232 chars to stream into the buffer to be picked up by the read logic in main. The buffer acts like a shock or surge supressor. The data in the buffer can be read rapidly at a point of your choosing in your main code.
Now a slightly modified getc function is needed to retreive chars one at a time from the buffer. Get string opens up another issue. You don't want to make the main code wait till the whole string is received it almost defeats the purpose of using the interrupt in the first place. An approach is to set a flag in the interrupt routine to indicate when a complete string is in the buffer. To do that you need a char that indicates the end of a string could be Cr or LF. The interrupt routine will set a flag when this char is received. A modified kbhit will then check this flag before letting you main code retreive the string and will also reset it. You'll need a modified version of gets to do this
it will call your modified getc until it hits your CR or LF char
BOB_SANTANA



Joined: 16 Oct 2006
Posts: 110
Location: HOVE, EAST SUSSEX

View user's profile Send private message

PostPosted: Wed Nov 22, 2006 6:23 am     Reply with quote

Douglas Kennedy

Thank you very much for taking the time to explain this for me.
you have improved my understanding of the whole program and i am in the process of making the suggested changes.
i would let you know how i get on should do it tonite when i get in

Best Regards
_________________
BOB_Santana Smile
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Wed Nov 22, 2006 7:01 am     Reply with quote

We are very fortunate on this board ... PCM programmer, Mark, Hans Wedemeyer and others have transferred much knowledge. All I knew when it came to PIC programming was that I needed to learn. PCM programmer's posts in particular have been invaluable to me and I will always be grateful.
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