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

yet another RS232 post

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



Joined: 08 May 2010
Posts: 6

View user's profile Send private message

yet another RS232 post
PostPosted: Sat May 08, 2010 2:57 pm     Reply with quote

Hello all,

I am trying to write a simple program that receives a string from the RS232 and stores it for later use.
I have seen numerous examples in this forum, yet I did not succeed making any of them work for me.
I try to keep it as simple and as fast as possible...
here is the code as it is now:

Code:

#include <input.c>
#include <stdio.h>
#include <stdlib.h>

char input [ 30 ];
int index = 0;
int1 input_ready = FALSE;

// serial interupt
#int_rda
void serial_interrupt ( )
{
   if (index<29) {
      input [index] = getc();
      putc(input[index]);
      if (input [index] == '\r') {
         input_ready = TRUE;
         index = 0;
         break;
      }
      index++;
   }
   else index = 0;
}
 

void main()
{
   
   printf("starting\n");
   enable_interrupts(int_rda);
   enable_interrupts(global);

   while (1) {
      input_ready = false;
      if (input_ready) {
         disable_interrupts(int_rda);
         printf("plot-->%s",input);
         enable_interrupts(int_rda);
      }
   }
   
}



I get the "starting" message in the terminal, but then nothing.
i don't even get the PUTC that I added to echo the input even before \r is detected.

any help will be most appreciated.

Moshe.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat May 08, 2010 4:26 pm     Reply with quote

Quote:

while (1) {
input_ready = false;

if (input_ready) {
disable_interrupts(int_rda);
printf("plot-->%s",input);
enable_interrupts(int_rda);
}
}

Look at what your while() loop is doing. You turn off the flag, and
then you test it. It will probably fail the test. There is a small chance
that the interrupt will occur just before the if() test, and set the flag.
But normally it will fail. You need to move the top line inside the if()
block.
mk77



Joined: 08 May 2010
Posts: 6

View user's profile Send private message

PostPosted: Sun May 09, 2010 11:37 am     Reply with quote

Thanks for the correction PCM, I modified the code as you suggested.
However, if you will notice the code I posted, I put inside the serial interrupt a putc to echo every getc, and that does not work either.
I've edited the serial interrupt a bit in order to debug it:

Code:

#int_rda
void serial_interrupt ( )
{
   if (index<29) {
      input [index] = getc();
      printf("%d\n",index);
      //putc(input[index]);
      if (input [index] == '\r') {
         input_ready = TRUE;
         index = 0;
         break;
      }
      index++;
   }
   else index = 0;
}


I am printing the index variable each time an interrupt is fired.
once I start a run - i get the following result:

starting
0
1

and then nothing happens, regardless of what i send through the port and regardless of the terminal i use (the 2 index counts are of the letters "n" and "w", don't know where they are coming from...).

can this be a hardware fault?

thanks for the help,

Moshe.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sun May 09, 2010 12:59 pm     Reply with quote

CCS has an example of how to use INT_RDA interrupts to get a string.
Look at the bget_string() function (buffered get_string) in this file:
Quote:

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



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

View user's profile Send private message

PostPosted: Mon May 10, 2010 12:30 am     Reply with quote

Just a general comment: The program you posted is not complete.
The #fuses and processor include lines are missing, and even more importantly the '#use rs232' line is not there.

If you don't post a complete program we can not know if you left out something on purpose or if this is the root of your problem. It is amazing how many problems we detect in these first three program lines.

Also post your compiler version number always.
mk77



Joined: 08 May 2010
Posts: 6

View user's profile Send private message

PostPosted: Mon May 10, 2010 12:52 pm     Reply with quote

Thanks for all the comments so far.

I use ver. 4.088 and XBEE as a serial interface.

I looked at ex_zmd and found it useful since i need many of the functions in there.
I copied them and twisted it a bit in order to suite my needs.

here is the code:
Code:

#include "D:\programming\code\robot.h"
#include <input.c>
#include <stdio.h>
#include <stdlib.h>

#use i2c(Master,sda=PIN_C4,scl=PIN_C5)
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,errors)

#define RS232_BUFFER_SIZE  127
char rs232_buffer[RS232_BUFFER_SIZE];
int8 rs232_nextin=0, rs232_nextout=0;

#int_rda
void isr_rda(void) {
   char c;
   c=getc();
   rs232_buffer[rs232_nextin++]=c;
   if (rs232_nextin >= RS232_BUFFER_SIZE) {rs232_nextin=0;}
   printf("in RDA");
   break;
}

char bgetc(void) {
   char c;
   while (rs232_nextout==rs232_nextin) {restart_wdt();}
   c=rs232_buffer[rs232_nextout++];
   if (rs232_nextout >= RS232_BUFFER_SIZE) {rs232_nextout=0;}
   return(c);
   
}


void bget_string(char* s, int max) {
   int len;
   char c;

   --max;
   len=0;
   do {
     c=bgetc();
     if(c==8) {  // Backspace
        if(len>0) {
          len--;
          putc(c);
          putc(' ');
          putc(c);
        }
     } else if ((c>=' ')&&(c<='~'))
       if(len<max) {
         s[len++]=c;
         putc(c);
       }
   } while(c!=13);
   s[len]=0;
}

signed int bget_int()
{
  char s[3];
  signed int i;

  bget_string(s, sizeof(s)-1);
  i=atoi(s);
  return(i);
}

signed long bget_long() {
  char s[7];
  signed long l;

  bget_string(s, sizeof(s)-1);
  l=atol(s);
  return(l);
}

#define bkbhit() (rs232_nextin!=rs232_nextout)

void main()
{
   char s[10];
 
   printf("starting\n");
   enable_interrupts(int_rda);
   enable_interrupts(global);
   
    while (1) {
      if (bkbhit()) {
         
         bget_string(s,sizeof(s)-1);
         printf("%s\n",s);
         
         }

}


I added a printf("in RDA") while inside the RDA, and the result is that the terminal is being filled with "in RDA" messages - which means it keeps coming to the RDA and never stops, even when no information is being sent.

The Xbee definitions work out fine when i check them with the AT commands.

No idea on what can go wrong...

Thanks again for the help.
Moshe.

UPDATE:
----------

the plot thickens - I changed the printf("in RDA") to printf("%s",c) so it will show me the characters he gets to the buffer ant this is what the terminal spits out:
<STX>nwA @xxx???xxx???xx<SO><STX>nwA @xxx???xxx???xx<SI><STX>nwxxx???xxx???xx<DLE><STX>nwA @xxx???xxx???xx<DC1><STX>nwA @xxx???xxx???xx<DC2><STX>nwA @xxx???xxx???<STX>nwA @xxx???xxx???xx<DC4><STX>nwA @xxx???xxx???xx<NAK><STX>nwA @xxx???x @xxx???xxx???xx<EM><STX>

and so on...

anyone has a clue?

Best regards,

Moshe
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon May 10, 2010 2:48 pm     Reply with quote

Quote:
#int_rda
void isr_rda(void) {
char c;
c=getc();
rs232_buffer[rs232_nextin++]=c;
if (rs232_nextin >= RS232_BUFFER_SIZE) {rs232_nextin=0;}
printf("in RDA");

break;
}

The printf inside the #int_rda will cause you to lose incoming characters.
The UART transmitter only has a "1-deep" input buffer. Therefore, it
can accept 2 characters immediately ("in"), without having to wait for the
transmitter to be ready. But the remaining 4 characters " RDA" will
require waiting for 1 ms each, for a total of 4 ms. The incoming
characters will quickly fill up the 2-deep receive buffer and overrun it,
and you will lose characters. Remove the printf from the #int_rda routine.

Also, the 'break' is unnecessary. It does nothing. Remove it.
ckielstra



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

View user's profile Send private message

PostPosted: Mon May 10, 2010 3:22 pm     Reply with quote

Code:
signed int bget_int()
{
  char s[3];
I reported this error in v4.099 but never got confirmed it being solved.
The 's[3]' is too small and causes the maximum range you can read to be -9 to 99 (or +9 if you use the sign). Change to 's[5]' for the full -127 to +128 range.
mk77



Joined: 08 May 2010
Posts: 6

View user's profile Send private message

PostPosted: Wed May 12, 2010 2:18 pm     Reply with quote

Thanks for all the suggestions...

I'm afraid nothing helped - I focus my search on the hardware and xbee settings, maybe that's the source of the problem, though everything seems to be in order.

If anyone who knows xbee recognizes something from the output I've posted and has a suggestion, I will be more than happy to hear.

Moshe.
ckielstra



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

View user's profile Send private message

PostPosted: Wed May 12, 2010 4:19 pm     Reply with quote

The program you posted is incomplete (robot.h is missing) and looks like to have a syntax error (missing '}'). So is this the real program you are testing with?

You can remove the not used i2c line, include files, bget_int and bget_long functions. Then post the complete and small as possible program.

Describe the hardware you have connected. Brand and model number of the Zigbee modules.
Is there a MAX232 or similar driver between the Zigbee modules and the PIC?

What is the data you are sending to the PIC?
How are you sending this?
What is the data you receive?
Gabriel



Joined: 03 Aug 2009
Posts: 1067
Location: Panama

View user's profile Send private message

PostPosted: Thu May 13, 2010 4:50 am     Reply with quote

Check out my post on "Receiving txt messages" on the working code part of the forum...

it depends on reading and sending strings over RS232 for sms control

it might help

also i have this little code to test my USART

Code:
#if defined(__PCB__)
#include <16f877a.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000) //must be 20 MHz

#elif defined(__PCM__)
#include <16f877a.h>
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=20000000) //must be 20 MHz

#use rs 232(baud=9600, xmit=PIN_C6, rcv=PIN_C7) // serial

void serialint();

char key;                  // caracter recibido
int presente;              // flag personal

void main()
{
   enable_interrupts(INT_RDA);  // habilitar interrupt de recieved data
   enable_interrupts(GLOBAL);   // habilitar interrupts globales
   presente=0;                  // clear flag personal


   while(1)
   {
      if(presente==1)
      {
         printf("%c\r\n",key);              // imprimir return y new line
         presente=0;
      }
   }

}

#INT_RDA
void serialint()
{
   key=getchar();
   presente = 1;
}



keep your isr As short as possible...i just get the char and set a flag.
all echoes and proscesing you can do outside...

like pcm programer said..if you take to long inside your isr you will loss characters

try putting the incoming data in a circular buffer ....
(i use one in my previously mentioned code "recieving txt messages")

hope this helps

sorry for the spanglish on my code comments Smile

gabriel
_________________
CCS PCM 5.078 & CCS PCH 5.093
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Thu May 13, 2010 8:24 am     Reply with quote

I would suggest taking the XBEE out of the circuit for now and work on getting your code working with a hard wired cable first. Once you have your code working like you want THEN migrate to the wireless and start trouble-shooting it.

Printf(), puts() or delays are not good inside an ISR. ISR's should be as short as possible. If I need to monitor the progress of an ISR, I'll have an output toggled or set/cleared and then monitor that output. Much faster for the ISR.

Ronald
rjrodrig



Joined: 09 Sep 2009
Posts: 7

View user's profile Send private message

Re: yet another RS232 post
PostPosted: Thu May 13, 2010 12:27 pm     Reply with quote

if you put this code in the interrupt and create a buffer before main()
called RX_BUFFER


Code:

#define RX_BUFFER_SIZE  20                      //Store Command Chars
#define ArrayLength (RX_BUFFER_SIZE + 1)        //+1 Stores Chars + '\0'

main()
{

}

/*
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
          I S R  R X  I N T E R R U P T  S E R V I C E  R O U T I N E
PIC24HJ256GP210.
*/
#INT_RDA
void RX_SerialData_ISR(void)
{
   disable_interrupts(INT_RDA);                    // RS232 OFF
   RX_BUFFER[RX_Wr_Index] = fgetc(RS232_USB);      //Get the character in the HW buffer
       
   if(RX_BUFFER[RX_Wr_Index] == 13)                //Is the current char a Carriage Return?
   {                                               //then set the flag, and reset the Buffer pointer
      RX_DONE = 1;                                 //Set the Reception is DONE...
      /*### INSERT THE NULL TERMINATOR ###*/
      RX_BUFFER[RX_Wr_Index] = '\0';               //Add Null Terminator to the Buffer
      RX_Wr_Index = 0;                             //Reset the Index back to the beginning
     
      if(RX_BUFFER[0] == 0x21)                     //HALT ANY MEASUREMENT PROCESSES with "! + CR"
      {
         STOP_MEASURING = 1;
      }
   }
   else if(++RX_Wr_Index == RX_BUFFER_SIZE)        //Increment the index and check if we reach the Buffer limit
   {
      RX_DONE = 1;                                 //Set the Reception is DONE...
      /*### INSERT THE NULL TERMINATOR ###*/
      RX_BUFFER[RX_Wr_Index] = '\0';               //Terminate the buffer
      RX_Wr_Index = 0;                             //Reset the Index back to the beginning
      //Parsed_RXData();                           //Parse the data automatically
   }
   else if((RX_Wr_Index % 4) == 3)
   {
      U1STA &= 0xFFFD;                             //Clear OverRun Error OERR Errata 18
      IFS0  &= 0xF7FF;                             //Clear Clear Interrupt Flag Errata 18
   }
   //clear_interrupt(INT_RDA);                     //Clear the interrupt Flag
   enable_interrupts(INT_RDA);                     //Re-enable the interrupt
   
}





mk77 wrote:
Hello all,

I am trying to write a simple program that receives a string from the RS232 and stores it for later use.
I have seen numerous examples in this forum, yet I did not succeed making any of them work for me.
I try to keep it as simple and as fast as possible...
here is the code as it is now:

Code:

#include <input.c>
#include <stdio.h>
#include <stdlib.h>

char input [ 30 ];
int index = 0;
int1 input_ready = FALSE;

// serial interupt
#int_rda
void serial_interrupt ( )
{
   if (index<29) {
      input [index] = getc();
      putc(input[index]);
      if (input [index] == '\r') {
         input_ready = TRUE;
         index = 0;
         break;
      }
      index++;
   }
   else index = 0;
}
 

void main()
{
   
   printf("starting\n");
   enable_interrupts(int_rda);
   enable_interrupts(global);

   while (1) {
      input_ready = false;
      if (input_ready) {
         disable_interrupts(int_rda);
         printf("plot-->%s",input);
         enable_interrupts(int_rda);
      }
   }
   
}



I get the "starting" message in the terminal, but then nothing.
i don't even get the PUTC that I added to echo the input even before \r is detected.

any help will be most appreciated.

Moshe.
mk77



Joined: 08 May 2010
Posts: 6

View user's profile Send private message

PostPosted: Thu May 13, 2010 12:44 pm     Reply with quote

thanks for all the help and suggestions.

I know using printf and putc inside the ISR is a bad practice, the thing is that I see that the RX and TX LEDs on my robot are blinking constantly and only the RX LED on my PC's XBEE is blinking, which makes me suspect there is a hardware fault at hand.
I will try to connect with a serial cable, but it will require a bit of fiddling, since I made the entire robot architecture suitable for the XBEE (I'll probably solder a small circuit with max232 on the side).

I will keep you updated on the results, and if the problem occurs with a cable i will post the entire code, what i am sending, receiving, etc.

Pictures of the application will be posted once problem is solved Smile

Again, thanks for helping out,
Moshe.
mk77



Joined: 08 May 2010
Posts: 6

View user's profile Send private message

Hello, again....
PostPosted: Sat Jun 05, 2010 7:33 am     Reply with quote

Well, I switched from wireless Xbee communication to regular serial cable and unfortunately, the problem remains.
It seems that the controller keeps jumping into INT_RDA, even when nothing is being sent to it.
In order to rule out hardware fault (both in the controller and the board), I am looking for a proved to be working, most simple "echo" program, that listens on the RS232 port and "echoes" everything back to the terminal.
If that won't work I will change board, controller , etc. until the fault will be found.

I will be more than thankful to anyone who can refer me to such a program.

Thanks in advance,

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