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

CCS RS485.c Lib Doesn't work. Proteus + source.

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



Joined: 17 Mar 2009
Posts: 7

View user's profile Send private message

CCS RS485.c Lib Doesn't work. Proteus + source.
PostPosted: Fri Nov 20, 2009 1:16 pm     Reply with quote

Hello! I tried to use the library of ccs to make communication between two PICs, but did not work.

I need the message to go in both directions, to do a sensor network.

I am enclosing the file used in this test, including the proteus circuit.

appreciate any help!


http://www.mediafire.com/file/zdnozazmmnh/485.rar
ivrj



Joined: 17 Mar 2009
Posts: 7

View user's profile Send private message

PostPosted: Wed Nov 25, 2009 8:41 am     Reply with quote

Anybody know what I did wrong?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Nov 25, 2009 1:53 pm     Reply with quote

There are probably several reasons why no one is helping you.

1. You didn't give a direct download link for your file. It goes to an
HTML page. Who knows what is on that page ? It could be
something bad.

2. Most people don't want to look at a large amount of code.

3. Most people don't have Proteus. They can't view a Proteus schematic file.
ivrj



Joined: 17 Mar 2009
Posts: 7

View user's profile Send private message

PostPosted: Thu Nov 26, 2009 5:10 am     Reply with quote

PCM programmer wrote:
There are probably several reasons why no one is helping you.

1. You didn't give a direct download link for your file. It goes to an
HTML page. Who knows what is on that page ? It could be
something bad.

2. Most people don't want to look at a large amount of code.

3. Most people don't have Proteus. They can't view a Proteus schematic file.


Sorry, but my intention was to make it easy to debug my code!

There is the code, and the schematic:





[img=http://img20.imageshack.us/img20/2093/rs485.jpg]


Code:

/////////////////////////////////////////////////////////////////////////
////                             EX_RS485_CHAT.C                     ////
////                                                                 ////
////     Converts RS485 data and puts it onto RS232 data line.       ////
////                                                                 ////
////  Jumpers:                                                       ////
////     PCM,PCH    pin B2 to RS232 RX, pin B1 to RS232 TX           ////
////                                                                 ////
////                                                                 ////
////  The following conditional compilation lines are used to        ////
////  include a valid device for each compiler.  Change the device,  ////
////  clock and RS232 pins for your hardware if needed.              ////
/////////////////////////////////////////////////////////////////////////
////        (C) Copyright 1996,2005 Custom Computer Services         ////
//// This source code may only be used by licensed users of the CCS  ////
//// C compiler.  This source code may only be distributed to other  ////
//// licensed users of the CCS C compiler.  No other use,            ////
//// reproduction or distribution is permitted without written       ////
//// permission.  Derivative programs created using this software    ////
//// in object code form are not restricted in any way.              ////
/////////////////////////////////////////////////////////////////////////

#include <18f4550.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1, ENABLE=PIN_B0)

#define  RS485_RX_BUFFER_SIZE 64
#define  RS485_USE_EXT_INT    TRUE

int8 OUR_RS485_ID = 0;
#define RS485_ID OUR_RS485_ID

#include <rs485.c>
#include <stdlib.h>

   #define RS485_RX_PIN       PIN_C6   // Data receive pin
   #define RS485_TX_PIN       PIN_C7   // Data transmit pin
   #define RS485_ENABLE_PIN   PIN_B0   // Controls DE pin.  RX low, TX high.
   #define RS485_RX_ENABLE    PIN_B1   // Controls RE pin.  Should keep low.
   

int8 in_char = 0;
int8 next_in = 0;
int8 next_out = 0;
int8 msg[64];


#INT_TIMER1
void timer1_isr()
{
   int8 i;
   printf("timer");
   if(rs485_get_message(msg, FALSE))
   {
      printf("\n\r mensagem recebida %d: ", msg[0]);

      for(i=0; i < msg[1]; ++i)
         putc(msg[i+2]);

      printf("\n\r");
   }
}

void RS485send(char* s, int8 id)
{
   int8 size;

   for(size=0; s[size]!='\0'; ++size);
   printf("Wait for bus");
   rs485_wait_for_bus(FALSE);
   printf("bus released, sending message...");
   while(!rs485_send_message(id, size, s))
      delay_ms(OUR_RS485_ID);
   printf("msg sent!");
}

char PCgetc()
{
   in_char = 0;

   while(!kbhit());
   in_char = getc();
   return in_char;
}

int8 PCgetInt()
{
   int8 i, s[3];
   
   for(i=0; (s[i]=PCgetc()) != '\r' && i<3; ++i);

   return atoi(s);
}

char* PCgetMsg()
{
   int8 i;

   for(i=0; (msg[i] = PCgetc()) != '\r' && i<64; ++i);

   msg[i] = '\0';

   return &(msg[0]);
}

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

   --max;
   len=0;
   do {
     c=getc();
     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 int8 get_int() {
  char s[5];
  signed int8 i;

  get_string(s, 5);

  i=atoi(s);
  //printf("get int %d", i);
  return(i);
}
#INT_RDA
void serial_isr()

   //printf("INT RDA");
   if(kbhit())
      in_char = get_int;
   //in_char = fgetc(PC);
}

void main()
{
   int8 i, send_addr = 0;
   char command;
   int8 inteiro;
   char *teste;  //just a test variable
   
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1);

   enable_interrupts(INT_RDA);
   enable_interrupts(GLOBAL);
   //enable_interrupts(INT_TIMER1);

   rs485_init();

   while(OUR_RS485_ID == 0 || OUR_RS485_ID >= 255)
   {
      printf("Please choose a network ID (1-255): ");
     
      //inteiro = get_int();
      //printf("%s",inteiro);
      OUR_RS485_ID = PCgetInt();
      //OUR_RS485_ID = inteiro;
   }

   printf("\n\rYour ID is: %d\n\r\n\rIf you require assistance, press h.\n\r", OUR_RS485_ID);
   
   while(command != 'Q')
   {
         enable_interrupts(INT_TIMER1);

         command = toupper(PCgetc());

         //disable_interrupts(INT_TIMER1);

         switch(command)
         {
            case 'S':
               if(send_addr == 0 || send_addr > 255)
               {
                  printf("\n\r\n\rEnter send address (1-255): ");
                  send_addr =get_int();
               }

               printf("\n\r%d:>", send_addr);
               RS485send(PCgetint(), send_addr);
               
               printf("Msg sent \n\r");
               break;

            case 'C':
               send_addr = 0;

               while(send_addr == 0 || send_addr > 255)
               {
                  printf("\n\r\n\rEnter send address (1-255): ");
                  send_addr = PCgetint();
                  printf("\n\r");
               }
               break;

            case 'I':
               OUR_RS485_ID = 0;

               while(OUR_RS485_ID == 0 || OUR_RS485_ID >= 255)
               {
                  printf("\n\rPlease choose a network ID (1-255): ");
                  OUR_RS485_ID = PCgetint();
               }
               printf("\n\rYour ID is: %d\n\r\n\r", OUR_RS485_ID);
               break;

            case 'H':
               printf("\n\rCommands: (S)end message, (C)hange Send Address, ");
               printf("Change (I)D, (H)elp, (Q)uit.\n\r");
               break;

            default:
               if(command != 'Q')
                  printf("\n\rInvalid command!\n\r");
         }
   }
}

Just pointing out that the code used in master and slave is the same!

Watching the oscilloscope, I noticed that there is sign on the 485´wires
just before setting the destination ID and type a message.

Ater typing the target ID and type the message, the code stops on the
line
Code:
 rs485_wait_for_bus(FALSE)
of RS485send() function.

Thank you for your time!
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Nov 26, 2009 11:11 am     Reply with quote

You have changed the CCS example in many ways.
Quote:
c:\program files\picc\examples\ex_rs485.c

Try the CCS example with as few changes as possible. Make that code
work. Then try adding changes to it.
ckielstra



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

View user's profile Send private message

PostPosted: Thu Nov 26, 2009 4:54 pm     Reply with quote

I do agree with PCM Programmer. Start with a working program and then make small changes so you know the latest change is the one to break things.

Just a few remarks on your code:
Code:
 RS485send(PCgetint(), send_addr);
RS485send expects a string as input, you give it an integer.

Code:
int8 PCgetInt()
{
   int8 i, s[3];
   
   for(i=0; (s[i]=PCgetc()) != '\r' && i<3; ++i);

   return atoi(s);
}
It is a very ugly coding style to have an assignment in the compare statement of the for-loop.
Bug: there is no terminating zero in s[] before your call to atoi().
Bug: You do have the terminating zero in PCgetMsg, but here it is possible a large message will write to msg[64]. A buffer overflow.

Code:
      if(len<=max) {
This line in get_string() can cause a buffer overflow. Change '<=' to '<'.
Also see my post in http://www.ccsinfo.com/forum/viewtopic.php?t=40633

Code:
#INT_RDA
void serial_isr()
{
   //printf("INT RDA");
   if(kbhit())
      in_char = get_int;
   //in_char = fgetc(PC);
}
Your program will only enter the interrupt when a character has been received. Hence testing kbhit will always be true and can be removed.

Calling get_int() from within the interrupt handler is bad practice. Get_int() will wait for a complete integer to be received. This is taking a long time for the processor and you are wasting a lot of processor resources. The same code can be written without interrupt handler and will be easier to understand.
ivrj



Joined: 17 Mar 2009
Posts: 7

View user's profile Send private message

PostPosted: Sat Nov 28, 2009 2:57 pm     Reply with quote

ckielstra wrote:
I do agree with PCM Programmer. Start with a working program and then make small changes so you know the latest change is the one to break things.

Just a few remarks on your code:
Code:
 RS485send(PCgetint(), send_addr);
RS485send expects a string as input, you give it an integer.

Code:
int8 PCgetInt()
{
   int8 i, s[3];
   
   for(i=0; (s[i]=PCgetc()) != '\r' && i<3; ++i);

   return atoi(s);
}
It is a very ugly coding style to have an assignment in the compare statement of the for-loop.
Bug: there is no terminating zero in s[] before your call to atoi().
Bug: You do have the terminating zero in PCgetMsg, but here it is possible a large message will write to msg[64]. A buffer overflow.

this is the original rs485.c code! :(

ckielstra wrote:

Code:
      if(len<=max) {
This line in get_string() can cause a buffer overflow. Change '<=' to '<'.
Also see my post in http://www.ccsinfo.com/forum/viewtopic.php?t=40633



Code:
#INT_RDA
void serial_isr()
{
   //printf("INT RDA");
   if(kbhit())
      in_char = get_int;
   //in_char = fgetc(PC);
}
Your program will only enter the interrupt when a character has been received. Hence testing kbhit will always be true and can be removed.

Calling get_int() from within the interrupt handler is bad practice. Get_int() will wait for a complete integer to be received. This is taking a long time for the processor and you are wasting a lot of processor resources. The same code can be written without interrupt handler and will be easier to understand.


I really appreciate the time and attention of you, but after reading a lot about rs485 and ask some questions for a friend I finally understood a little more how an exchange of messages in 485. So , I will abandon the use of this library to do my own protocol.


I just wanted to take one more doubt: the rs485 is identical to RS232 for messaging, differing only in the use of "pin" activation mode for writing and reading? This is without considering the need to develop the communication protocol, treatment of collision, and everything else!

Again, thank you!
bkamen



Joined: 07 Jan 2004
Posts: 1611
Location: Central Illinois, USA

View user's profile Send private message

PostPosted: Fri Mar 26, 2010 10:30 am     Reply with quote

ckielstra wrote:

Code:
int8 PCgetInt()
{
   int8 i, s[3];
   
   for(i=0; (s[i]=PCgetc()) != '\r' && i<3; ++i);

   return atoi(s);
}
It is a very ugly coding style to have an assignment in the compare statement of the for-loop.


Heh! you know how much of that's in the older Microchip TCPIP stack? Hahah..

I looked at it the same way too. "eeehhhh!!"

-Ben
_________________
Dazed and confused? I don't think so. Just "plain lost" will do. :D
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