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

int16 over rs232
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Allan



Joined: 20 Dec 2009
Posts: 23

View user's profile Send private message

int16 over rs232
PostPosted: Thu Mar 18, 2010 4:44 am     Reply with quote

Hi everybody,

I've got a beginners RS232 question. I'm using a 18f2321 with V4.104 software. I need a method to send more than a single character over RS232. I know my hardware (National 97176 rs485 drivers) is working because I can send single / receive single characters.

With "errors" removed from the #USE statement the program locks, with "errors" in place I get a bunch of 0's. I get the same type of errors when I use fprintf() instead of fputs

If I understand the manual the compiler is taking care of null terminating the strings at the atol and ltoa statements, so I didn't add a "\r"


Code:

#use rs232(uart1, baud = 9600, Enable = EPIN, stream = Remote, errors, DISABLE_INTS)

============

#INT_RDA
void InputRS232()
   {
   extern int16 Display;  // Send - receive an int16
   char data[10];
   fgets(data, Remote);
   Display = atol(data);
   }

============

    char data[10];
   
    itoa(Display, 10, Data);
    fputs(Data, Remote);


 


Also, is there a simpler way to send an int16 over rs232? Those string functions are using a lot of resources.

Thanks
Ttelmah



Joined: 11 Mar 2010
Posts: 19506

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 6:54 am     Reply with quote

First problem. Do a search here about RS485 termination, and more importantly _bias_. It sounds as if your bus is not biased 'off', so garbage characters are being received, when it is not driven. 'ERRORS' prevents the UART from locking up, when unhandled characters are received.

Then understand the difference between '\r', and '\0'. '\r', means 'carriage return' a transmittable ASCII charcater. '\0', is the string terminator character inside the memory. The PIC will automatically add the latter to the data, when the _former_ is received. At some point though, you need to be sending a carriage return...

Then understand what the interrupt implies. It is saying there is _one_ charcater received. You are calling 'gets', inside the interrupt, which means the code will sit inside the interrupt, effectively 'hung', _until_ a carriage return is received. If more than 9 characters do arrive (the garbage for instance), then the buffer _will_ overflow, destroying the contents of memory...
So:
Code:

#include "ex_sisr.c" //CCS's example interrupt driven receive

//Then something like

signed int16 wait_for_number(int16 loopfor) {
   int16 temp=0;
   int8 chr;
   do {
       if (bkbhit()) {
          chr=bgetc();
          if (chr>='0' && chr<='9') {
              //Have received a number
              temp=temp*10;
              temp=temp+(chr-'0'); //Add in the digit
          }
          if (chr=='\r') {
              //Have carriage return
              return temp;
          }
        }
        delay_us(90);
     } while (loopfor--);
     return -1L; //flag for 'timeout'
}     
   
//Then in the main
signed int16 val;

//Ten inside your loop waiting for values
val=wait_for_number(1000); //Wait for about one second

if (val==-1) {
    //Display/handle number not received
}
else {
    fprintf(data,"%02LD\n\r",val);
}


You obviously need to put the main etc. around this.

Now, it is only a demo, but the 'wait_for_number' routine, loops for 'loopfor' times, and if text numbers are received, builds a running sum, by converting them to numeric (-'0'), and adding them to the running total *10. When the carriage return is seen (just like gets, it _needs_ this), it returns the number generated. If the loop count, gets to zero, it instead returns '-1', to say that the string didn't arrive in time.
It gives a basic idea of how to receive text nmbers, without getting involved in the string functions at all.

Best Wishes
Allan



Joined: 20 Dec 2009
Posts: 23

View user's profile Send private message

PostPosted: Thu Mar 18, 2010 6:05 pm     Reply with quote

Quote:

understand the difference between '\r', and '\0'.


Thanks Ttelmah!

I'll also put a scope on the data lines tomorrow - the design is proven but an IC might have been damaged by static or handling

Allan
wgalaugher



Joined: 10 Jan 2011
Posts: 18

View user's profile Send private message

PostPosted: Thu Sep 08, 2011 9:19 pm     Reply with quote

I added the code to the Ex_SISR code

I get a consistent errr that I cannot find.

Executing: "C:\Program Files\PICC\Ccsc.exe" +FH "..\serial\Serial.c" +EXPORT +DF +LN +T +A +M +Z +Y=9 +EA
*** Error 58 "Serial.c" Line 16(19,20): Expecting a close paren
1 Errors, 0 Warnings.
Halting build on first failure as requested.
BUILD FAILED: Thu Sep 08 20:11:25 2011

Code:

#include <EX_SISR.c>

#fuses  HS,NOWDT,NOPROTECT

#use delay(clock=20000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7,STREAM=seriale)



signed int16 wait_for_number(int16 loopfor)
 {
   int16 temp=0;
   int8 chr;
   do {
       if (!bkbhit())
      {
          chr=bgetc();
          if (chr>='0' && chr<='9');
         {
              //Have received a number
              temp=temp*10;
              temp=temp+(chr-'0'); //Add in the digit
             }
          if (chr=='\r');
         {
              //Have carriage return
              return temp;
             }
        }
 
        delay_us(90);         
       
   }   while (loopfor--);
  return -1L; //flag for 'timeout'

}

main()
{
signed int16 val ;

   enable_interrupts(global);
   enable_interrupts(int_rda);
 
val=wait_for_number(1000); //Wait for about one second

if (val==-1) {
    //Display/handle number not received
}
else {
    fprintf(seriale,"%02LD\n\r",val);

while (TRUE);

}





I neeed a better pair of eyes.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 08, 2011 9:34 pm     Reply with quote

Quote:
if (chr>='0' && chr<='9');

if (chr=='\r');

Your if() statements all have semi-colons at the end. Remove them.
wgalaugher



Joined: 10 Jan 2011
Posts: 18

View user's profile Send private message

PostPosted: Thu Sep 08, 2011 9:40 pm     Reply with quote

Semicolons removed but no joy. I get the same error!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 08, 2011 9:42 pm     Reply with quote

Post the current code and mark the line that the error is on,
so I can easily see it. Your post said "line 19", but which one
is that ? Mark it with a comment.
wgalaugher



Joined: 10 Jan 2011
Posts: 18

View user's profile Send private message

PostPosted: Thu Sep 08, 2011 10:11 pm     Reply with quote

Code:

#include <EX_SISR.c>

#fuses  HS,NOWDT,NOPROTECT

#use delay(clock=20000000)
#use rs232(baud=4800, xmit=PIN_C6, rcv=PIN_C7,STREAM=seriale)



signed int16 wait_for_number(int16 loopfor)
 {
   int16 temp=0;
   int8 chr;
   do {
       [b]if (!bkbhit())[/b]      { "This is line 16"
          chr=bgetc();
          if (chr>='0' && chr<='9')
         {
              //Have received a number
              temp=temp*10;
              temp=temp+(chr-'0'); //Add in the digit
             }
          if (chr=='\r')
         {
              //Have carriage return
              return temp;
             }
        }
 
        delay_us(90);         
       
   }   while (loopfor--);
  return -1L; //flag for 'timeout'

}

main()
{
signed int16 val ;

   enable_interrupts(global);
   enable_interrupts(int_rda);
 
val=wait_for_number(1000); //Wait for about one second

if (val==-1) {
    //Display/handle number not received
}
else {
    fprintf(seriale,"%02LD\n\r",val);

while (TRUE);

}

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Sep 08, 2011 10:36 pm     Reply with quote

This code can't compile. You can't take the Ex_sisr.c example file, which
has it's own #fuses, and main(), and tack another test program with
it's own main(), etc., onto the end of it.

Just delete the #include for Ex_sisr.c, and put in the #include line for
your PIC. Then copy and paste everything from Ex_sisr.c except for
the initial part of that file, which has the lines for the PIC, #fuses, etc.,
and put it just after the #use rs232() line in your program. You just
want the "guts" of the Ex_sisr.c file (variable declarations and functions).


Quote:
while(!bkbhit());

In the line above in your posted code, you have two parentheses after
the bkbhit. Get rid of those.

Also get rid of the stream parameter in your own #use rs232() line.
The Ex_sisr.c routines are not setup to use a stream.

If you do all that, it should compile.
wgalaugher



Joined: 10 Jan 2011
Posts: 18

View user's profile Send private message

PostPosted: Thu Sep 08, 2011 11:52 pm     Reply with quote

Got it to compile. Not getting the correct result. It should show the value of the numbers typed. It only shows the last 2 digits once, then hangs


Code:

#include<18F2620.h>

#fuses  HS,NOWDT,NOPROTECT

#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,STREAM=seriale)

#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);
}

signed int16 wait_for_number(int16 loopfor)
 {
   int16 temp=0;
   int8 chr;
   do {
       if (!bkbhit)
      {
          chr=bgetc();
          if (chr>='0' && chr<='9') {
              //Have received a number
              temp=temp*10;
              temp=temp+(chr-'0'); //Add in the digit
          }
          if (chr=='\r') {
              //Have carriage return
              return temp;
          }
        }
       
        delay_us(90);         
       
   }   while (loopfor--);
  return -1L; //flag for 'timeout'

}

main()
{
signed int16 val ;

   enable_interrupts(int_rda);
   #if defined(__PCD__)
   enable_interrupts(intr_global);
   #else
   enable_interrupts(global);
   #endif

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


 
val=wait_for_number(1000); //Wait for about one second

if (val==-1) {
    //Display/handle number not received
fprintf(seriale,"%02LD\n\r",val);
}
else {
    fprintf(seriale,"%02LD\n\r",val);

while (TRUE);

}
temtronic



Joined: 01 Jul 2010
Posts: 9225
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Sep 09, 2011 8:25 am     Reply with quote

Add 'errors' to the use rs232(...) option list, that'll take care of the UART buffer being full and clobbered by more incoming.
wgalaugher



Joined: 10 Jan 2011
Posts: 18

View user's profile Send private message

PostPosted: Fri Sep 09, 2011 8:40 am     Reply with quote

Added "errors" to the RS232 but still the same result. If I type in 4 numbers only the last two digits show and it hangs. It seems so simple.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 09, 2011 12:45 pm     Reply with quote

You came into this thread, but I don't think you ever told us what you
want to do. Do you want to get an unsigned decimal integer consisting
of up to 4 digits, with the digits in ASCII format, which will arrive at the
PIC over the RS-232 interface ?

And, how will the number be terminated ? Will it have a Carriage Return
(0x0D) character at the end ?

If you want anything different than that, such as signed instead of
unsigned, or if you want more (or less) digits, or if it's not in decimal,
or if there is no termination byte, or anything else, please tell us.
wgalaugher



Joined: 10 Jan 2011
Posts: 18

View user's profile Send private message

PostPosted: Fri Sep 09, 2011 1:11 pm     Reply with quote

Good lesson for me. Never make any assumptions about what people think you mean.

What I trying to do with this code is to type in 4 digit via RS232 with a carriage return so the PIC will assemble these digits into an int16 numeric variable that I can use as a control value in the program.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Sep 09, 2011 3:13 pm     Reply with quote

Look at the get_long() function in this CCS driver file:
Quote:

c:\program files\picc\drivers\input.c


If you want an interrupt-driven buffered version of it, look at:
Quote:

c:\program files\picc\examples\ex_zmd.c

It's for get_int(), but it could be modified for get_long().
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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