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

Reading a Block of ascii characters from UART

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



Joined: 22 Apr 2006
Posts: 87

View user's profile Send private message

Reading a Block of ascii characters from UART
PostPosted: Wed Sep 09, 2009 11:01 pm     Reply with quote

I want to read a block of ascii numbers that is sent by the PC to my PIC.
Can any one please tell me what I am doing wrong. I have tried the following code but is is not working.

The size of the data block is fixed to 768 bytes always, as below:
Code:

01 0130 0131 1230 1231 1430 1400 0130 0131 1230 1231 1430 1400
02 0230 0231 0330 0331 1830 1831 0230 0231 0330 0331 1830 1831
03 0330 0331 0430 0431 1930 1931 0330 0331 0430 0431 1930 1931
04 0430 0431 0530 0531 2030 2031 0430 0431 0530 0531 2030 2031
05 0530 0531 0630 0631 2130 2131 0530 0531 0630 0631 2130 2131
06 0630 0631 0730 0731 2230 2231 0630 0631 0730 0731 2230 2231
07 0730 0731 0830 0831 2330 2331 0730 0731 0830 0831 2330 2331
08 0830 0831 1030 1031 0330 0331 0830 0831 1030 1031 0330 0331
09 0930 0931 1330 1331 1530 1531 0930 0931 1330 1331 1530 1531
10 1030 1031 0230 0231 0530 0531 1030 1031 0230 0231 0530 0531
11 1130 1131 1230 1231 0630 0631 1130 1131 1230 1231 0630 0631
12 1030 1031 1430 1431 2330 2331 1030 1031 1430 1431 2330 2331


#include <16F877.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#include <input.c>

//======================================
void main()
{
char temp[769]; size of the data block

printf("Enter string: ");

get_string(temp, sizeof(temp));

printf("\n\rReceived: %s \n\r", temp);

while(1);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 09, 2009 11:11 pm     Reply with quote

Quote:
#include <16F877.H>

char temp[769]; size of the data block

It's not working because it doesn't compile. You didn't even try to
compile it. The PCM compiler can't make a RAM array larger than the
bank size, and that's a maximum of of 96 bytes for the 16F877.
(Even if you use #device *=16).
deltatech



Joined: 22 Apr 2006
Posts: 87

View user's profile Send private message

PostPosted: Wed Sep 09, 2009 11:29 pm     Reply with quote

Thanks PCM Programmer

I Have tried it with pic18f6622 and still it wont work

Code:
#include <18F6622.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)

#include <input.c>

//======================================
void main()
{
char temp[768];

//printf("Enter string: ");

get_string(temp, sizeof(temp));

printf("\n\rReceived: %s \n\r", temp);

while(1);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Sep 09, 2009 11:41 pm     Reply with quote

Quote:

void get_string(char* s, unsigned int8 max) {
unsigned int8 len;


Look at the definition of the get_string() function in input.c.
CCS has declared the 'max' and 'len' variables as an int8.
To go larger than 255 bytes, you would have to change them
to int16. If you do that, it would be best to make a copy of
the get_string() function and put it in your program. Then
modify that copy. Don't include the input.c file.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Sep 10, 2009 9:30 am     Reply with quote

curiosity talking here:

do you have any time-out or other protection method in mind to prevent a total hang of the program should the full 768 bytes not be received?

as in what happens if you DON't get to fill the full string ?

or to get back in sync if you DO manage to survive a bad length string receive ?

just wondering if this was for fun or for real



Very Happy
deltatech



Joined: 22 Apr 2006
Posts: 87

View user's profile Send private message

PostPosted: Thu Sep 10, 2009 12:26 pm     Reply with quote

Hi Pcm Programmer

Is this the best to way read a block of 768 byte ascii characters from the uart? Do you have any example you can suggest? I have searched on the forum. There are many posts but I can't find one where someone read a block of text from the UART.

Hi asmboy. I am sorry I am newbee I don't have any timeout protection. This is for real not just fun. I want to read the table above. This is 768 bytes big and it is fixed. It doesn't change. It is to be read from a PC connected to the pic serial port. I would be grateful if you would help me by making any suggestions that would get me started. Many thanks.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Sep 10, 2009 1:48 pm     Reply with quote

In the middle of my work day now but will post you code later this evening (lcl time).

The way I do that is to set up a circular ring buffer, serial interrupt handler.

And then poll an INT_KBhit() function to see if there are characters ready - and remove them - checking and appending to the output_768 char string as you get them - even checking for "legality" ( not line-faulted ) as I go.

Then there is never the chance for a hang - and I can do other tasks while I wait for all the chars to arrive ( or not arrive as the case may be ).
ciao till later
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

ISR receiver that buffers chars as they arrive
PostPosted: Thu Sep 10, 2009 5:31 pm     Reply with quote

Code:

//  serial port ISR parts   96 byte buffer for 18F use
//  this example is for 38400 and at max throughput
//  you need not remove a char for up to 25 msec to avoid overflow,data loss
//  if you DO overflow - the pointers wrap , but don't  crash 
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 96
BYTE RISR_out;      // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
//   TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)

// NB: ONLY call if bkbhit is true
//     ignore this at your peril
char bgetc(void) {
   RISR_out=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(risr_out);
}
void DISR_INIT(void){  // prepare handler
    clear_interrupt( int_rda );
    enable_interrupts(int_rda);
    enable_interrupts(global);
}
#int_rda           // the handler
   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 protection !!
}


// in your Main ( just fragmentary here 
main (){
     // your init stuff
     disr_init();
    while (1){
       // other stuff you need to cycle through
       //

      // below will not execute unless  chars wating in the INT buffer

      while ( bkbhit ) {         //  LOOP as long as chars are in ISR buffer
         your_next_char=bgetc(); // unloads one char from buffer
         // check, append or whatever your new char  NOTE RISR_OUT global
      }  // your keyhandler ends NOTE: no wait for a char to come in 


      // other stuff you want to do AFTER some new chars are found and handled


    } // you main loop ends
}     //  main ends

asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

ISR receiver that buffers chars as they arrive
PostPosted: Thu Sep 10, 2009 5:33 pm     Reply with quote

Code:

//  serial port ISR parts   96 byte buffer for 18F use
//  this example is for 38400 and at max throughput
//  you need not remove a char for up to 25 msec to avoid overflow,data loss
//  if you DO overflow - the pointers wrap , but don't  crash 
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 96
BYTE RISR_out;      // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
//   TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)

// NB: ONLY call if bkbhit is true
//     ignore this at your peril
char bgetc(void) {
   RISR_out=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(risr_out);
}
void DISR_INIT(void){  // prepare handler
    clear_interrupt( int_rda );
    enable_interrupts(int_rda);
    enable_interrupts(global);
}
#int_rda           // the handler
   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 protection !!
}


// in your Main  just fragmentary here 
main (){
     // your init stuff
     disr_init();
    while (1){
       // other stuff you need to cycle through
       //

      // below will not execute unless  chars are waiting in the INT "buffer"

      while ( bkbhit ) {         //  LOOP as long as chars are in ISR buffer
         your_next_char=bgetc(); // unloads one char from buffer
         // check, append or whatever new char  NOTE RISR_OUT global
      }  // your keyhandler ends NOTE: no wait for a char to come in 


      // other stuff you want to do AFTER some new chars are found and handled


    } // you main loop ends
}     //  main ends

deltatech



Joined: 22 Apr 2006
Posts: 87

View user's profile Send private message

PostPosted: Thu Sep 10, 2009 8:14 pm     Reply with quote

Hi asmboy thanks for your help with this problem.

I have tried to adopt your code to my application to the best of my ability, but unfortunately I get an error message on compilation on the following line of code:

buffer+=next_char[i]; //build the 768 bytes received form the UART


What I am trying to do is rebuild the received table one byte at a time but I think I am doing something wrong.

Please point out my mistake. Many Thanks.
Code:

//  serial port ISR parts   96 byte buffer for 18F use
//  this example is for 38400 and at max throughput
//  you need not remove a char for up to 25 msec to avoid overflow,data loss
//  if you DO overflow - the pointers wrap , but don't  crash
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 769
BYTE RISR_out;      // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
//   TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)

// NB: ONLY call if bkbhit is true
//     ignore this at your peril
char bgetc(void) {
   RISR_out=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(risr_out);
}
void DISR_INIT(void){  // prepare handler
    clear_interrupt( int_rda );
    enable_interrupts(int_rda);
    enable_interrupts(global);
}
#int_rda           // the handler
   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 protection !!
}


// in your Main  just fragmentary here
main (){
unsigned int8 next_char[679];
BYTE buffer[679];
 
 setup_adc_ports(NO_ANALOGS|VSS_VDD);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   setup_timer_4(T4_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(VREF_LOW|-2);
   setup_oscillator(False);

   // your init stuff
     disr_init();
    while (1){
       // other stuff you need to cycle through
       //

      // below will not execute unless  chars are waiting in the INT "buffer"

      while ( bkbhit ) {

         char i;     //  LOOP as long as chars are in ISR buffer

         for (i=0;i<769;i++)
         {
         next_char[i]=bgetc(); // unloads one char from buffer
      buffer+=next_char[i]; //build the 768 byte received form the UART  one byte ata time
     
         }
         // check, append or whatever new char  NOTE RISR_OUT global



      }  // your keyhandler ends NOTE: no wait for a char to come in


      // other stuff you want to do AFTER some new chars are found and handled


    } // you main loop ends
}     //  main ends
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Sep 10, 2009 9:01 pm     Reply with quote

TYPOS and syntax
DON'T try to use the background and count it out
leave the SIZE of buffer code alone - as set originally
have a buffer for received and do this:

it's much simpler than U r trying to make it

Code:

// stay with BUFFER_SIZE =96 !! dont mess with the vars directly that the // INT handler touches - you will be glad you did it that way

char Yourbuffer [770]  // your assembly point for the fished out 768
yourbuffer[769]=0; // making sure of null \0 terminator char

int16 bufptr=0;  // fill point
// so starting  and assuming  read w/o checking chars


// and later
       while ( bkbhit  && bufptr<768) {
         
           yourbuffer[bufptr++]=bgetc(); // unloads 1 char
             
         }
        // test when bufptr shows 768 recvd && process YOURBUFFER
        // then reset bufptr=0; wyen ready to get another 
       // check, append or whatever new char  NOTE RISR_OUT global



      }  // your keyhandler ends

deltatech



Joined: 22 Apr 2006
Posts: 87

View user's profile Send private message

PostPosted: Thu Sep 10, 2009 10:26 pm     Reply with quote

Hi asmboy thanks for your help i think i have more understanding now where i am going you hav been great help thanks .

But when i compile the new code i get an erro at the following line

yourbuffer [769]=0; // making sure of null \0 terminator char

the error is
Quote:
expecting a (



Code:

//  if you DO overflow - the pointers wrap , but don't  crash
#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )
#define BUFFER_SIZE 96
BYTE RISR_out;      // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];

char yourbuffer [770] ; // your assembly point for the fished out 768

yourbuffer [769]=0; // making sure of null \0 terminator char

int16 bufptr=0;  // fill point
// so starting  and assuming  read w/o checking chars



BYTE next_in = 0;
BYTE next_out = 0;
//   TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)

// NB: ONLY call if bkbhit is true
//     ignore this at your peril
char bgetc(void) {
   RISR_out=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(risr_out);
}
void DISR_INIT(void){  // prepare handler
    clear_interrupt( int_rda );
    enable_interrupts(int_rda);
    enable_interrupts(global);
}
#int_rda           // the handler
   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 protection !!
}


// in your Main  just fragmentary here
main (){


     // your init stuff
     disr_init();
    while (1){
       // other stuff you need to cycle through
       //

      // below will not execute unless  chars are waiting in the INT "buffer"

      while ( bkbhit  && bufptr<768)
      {         //  LOOP as long as chars are in ISR buffer
         yourbuffer[bufptr++]=bgetc(); // unloads 1 char//your_next_char=bgetc(); // unloads one char from buffer
         // check, append or whatever new char  NOTE RISR_OUT global
      }  // your keyhandler ends NOTE: no wait for a char to come in

//-----------
/// and later
       
        // test when bufptr shows 768 recvd && process YOURBUFFER
        // then reset bufptr=0; wyen ready to get another
       // check, append or whatever new char  NOTE RISR_OUT global



      }  // your keyhandler ends
//-----------
      // other stuff you want to do AFTER some new chars are found and handled


    } // you main loop ends
//}     //  main ends
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Sep 10, 2009 10:30 pm     Reply with quote

The code is FRAGMENTARY - not a compilable program - incomplete
not all done and ready to fly by any means.

It illustrates the principle of serial INT Buffering ,
in your special case - and that was all.

But now you have to understand how to write a c- program
to finish the job and write the program you mentioned.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Sep 11, 2009 5:09 pm     Reply with quote

this is a MINIMAL !!! version that will compile and shows mistakes
starting with the #device line that does not belong

there is LOTS'A work to do to make this a complete program

but go forth and prosper and best wishes

Code:

//  serial port ISR parts   96 byte buffer for 18F use
//  this example is for 38400 and at max throughput
//  you need not remove a char for up to 25 msec to avoid overflow,data loss
//  if you DO overflow - the pointers wrap , but don't  crash
#include <18F6620.h>


//  ## FUSES statement needed HERE !!

#use delay( clock=8000000 ) // clock changed to 80000

char yourbuffer[780]; // your assembly point for the fished out 768


#use rs232(baud=38400, xmit=PIN_C6, rcv=PIN_C7, ERRORS )

#define BUFFER_SIZE 96
BYTE RISR_out;      // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
int16 bufptr=0;  // fill point
// so starting  and assuming  read w/o checking chars

BYTE next_in = 0;
BYTE next_out = 0;
//   TRUE if chars are waiting in buffer
#define bkbhit (next_in!=next_out)



// NB: ONLY call if bkbhit is true
//     ignore this at your peril
char bgetc(void) {
   RISR_out=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(risr_out);
}
void DISR_INIT(void){  // prepare handler
    clear_interrupt( int_rda );
    enable_interrupts(int_rda);
    enable_interrupts(global);
}
#int_rda           // the handler
   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 protection !!
}


// in your Main  just fragmentary here
main (){

       yourbuffer[778]=0;


     // your init stuff
     disr_init();
    while (1){
       // other stuff you need to cycle through
       //

      // below will not execute unless  chars are waiting in the INT "buffer"

      while ( bkbhit  && bufptr<768)
      {         //  LOOP as long as chars are in ISR buffer
         yourbuffer[bufptr++]=bgetc(); // unloads 1 char//your_next_char=bgetc(); // unloads one char from buffer
         // check, append or whatever new char  NOTE RISR_OUT global
      }  // your keyhandler ends NOTE: no wait for a char to come in

//-----------
/// and later

        // test when bufptr shows 768 recvd && process YOURBUFFER
        // then reset bufptr=0; wyen ready to get another
       // check, append or whatever new char  NOTE RISR_OUT global



      }  // your keyhandler ends
//-----------
      // other stuff you want to do AFTER some new chars are found and handled


    } // you main loop ends
//}     //  main ends 
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