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

Help with RS485 communication between two pics

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



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

Help with RS485 communication between two pics
PostPosted: Wed Jun 03, 2009 8:33 am     Reply with quote

Hello,

I am trying to get two pic18f2525 two talk over a rs485 interface. Each pic is on a separate pcb and each board has a MAX487 RS485 transceiver. Right now I am just trying to establish some sort of one way communication and it is not working. I have created a test program so that pic1 simply sends a character every second based on which one of two RB switches are activated. The code for PIC 1 looks like this:

Code:


#include <18F2525.h>
#device ADC=10  //set for 10 bit A/D
#fuses INTRC_IO,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define NORMAL_OP          1
#define CAL                2
#define FAIL             3
#define OFFLINE          4
#define OFFLINE_RST_SW_ACT      1
#define ZERO_SPAN_SW_ACT         2
#define EXMO_NO_SW         7
#define EXMO_CAL_SW         8
#define EXMO_RST_SW         9

#define SENSOR_ZERO_HIGH_BYTE_ADDX 10
#define SENSOR_ZERO_LOW_BYTE_ADDX 11
#define SENSOR_SPAN_HIGH_BYTE_ADDX 20
#define SENSOR_SPAN_LOW_BYTE_ADDX 21
#define NUM_MSG_NORMAL_OP 3
#define ZERO_SPAN_SW       PIN_B5
#define OFFLINE_RESET_SW    PIN_B4
#define SENSPOT_CS PIN_B3
#define DE_RE   PIN_B0
#define DEBUG1
#define SPI_MODE_0_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1  (SPI_L_TO_H)
#define SPI_MODE_1_0  (SPI_H_TO_L)
#define SPI_MODE_1_1  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

unsigned char exmo_sw=4;

#include <sce5774.c>

#INT_RB
void rb_isr(void)
{
 

 if (input(OFFLINE_RESET_SW) == 0)
 {
   exmo_sw = EXMO_RST_SW;
      
 }// if (input(OFFLINE_RESET_SW) == 0)

else if ( input(ZERO_SPAN_SW) == 0)//else zero_span switch activated

         exmo_sw = EXMO_CAL_SW;
      
 
} //end void rb_isr(void)

void main(void)
{
output_low(DE_RE);
reset_display();

setup_spi(SPI_MASTER | SPI_MODE_0_0 |SPI_CLK_DIV_4);
SETUP_ADC_PORTS(AN0_TO_AN2 | VSS_VREF);
setup_adc(ADC_CLOCK_DIV_4 |ADC_TAD_MUL_4 );
setup_ccp1(CCP_PWM);   
setup_timer_2(T2_DIV_BY_4, 255, 1);

clear_interrupt(INT_RB);   
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);

while (1)
{

                output_high(DE_RE);
   printf("\n%u\r," exmo_sw);
   output_low(DE_re);
                delay_ms(1000);
}


And this appears to be doing what it is suppose to do. I took a peek using hyperterminal and see that it is printing 4 to start and when I activate one of the switches, the RB interrupt causes it to print 8 or 9 as it should.

The receiving PIC code looks like:

Code:

#include <18F2525.h>
#device ADC=10  //set for 10 bit A/D
#fuses INTRC_IO,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define NORMAL_OP          1
#define CAL                2
#define FAIL             3
#define OFFLINE          4
#define OFFLINE_RST_SW_ACT      1
#define ZERO_SPAN_SW_ACT         2
#define EXMO_NO_SW         7
#define EXMO_CAL_SW         8
#define EXMO_RST_SW         9

#define SENSOR_ZERO_HIGH_BYTE_ADDX 10
#define SENSOR_ZERO_LOW_BYTE_ADDX 11
#define SENSOR_SPAN_HIGH_BYTE_ADDX 20
#define SENSOR_SPAN_LOW_BYTE_ADDX 21
#define NUM_MSG_NORMAL_OP 3
#define ZERO_SPAN_SW       PIN_B5
#define OFFLINE_RESET_SW    PIN_B4
#define SENSPOT_CS PIN_B3
#define DE_RE   PIN_B0
#define DEBUG1
#define SPI_MODE_0_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1  (SPI_L_TO_H)
#define SPI_MODE_1_0  (SPI_H_TO_L)
#define SPI_MODE_1_1  (SPI_H_TO_L | SPI_XMIT_L_TO_H)

unsigned char ch;

#include <sce5774.c>

void main(void)
{
output_low(DE_RE);
reset_display();

setup_spi(SPI_MASTER | SPI_MODE_0_0 |SPI_CLK_DIV_4);
SETUP_ADC_PORTS(AN0_TO_AN2 | VSS_VREF);
setup_adc(ADC_CLOCK_DIV_4 |ADC_TAD_MUL_4 );
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
setup_ccp1(CCP_PWM);    // Configure CCP2 as a PWMDAC
setup_timer_2(T2_DIV_BY_4, 255, 1);


while (1)
{

if (kbhit())
{

   ch = getch();
     
    // format_adc_to_display(ch);
      
}//if (kbhit())
else
{
ch = 49;
}
format_adc_to_display(ch);
delay_ms(500);
clear_display();
delay_ms(500);




}//while

}//main


The problem is that the receiving pic only grabs the first tranmission on power up and after that it always prints 49 as the value for ch meaning that kbhit() is false.

Anyone has any ideas what the problem might be?

Thanks.

MK
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 03, 2009 11:13 am     Reply with quote

See this thread:
http://www.ccsinfo.com/forum/viewtopic.php?t=38128
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Wed Jun 03, 2009 12:12 pm     Reply with quote

Following the link you gave I added 1.2k pullup and pulldown on the A and B lines of the RS485 and a 120Ohm between the A and B. I got the same result. That is: I power up both boards and the receiving pic gets the correct character, once, but then doesn't get any subsequent transmissions. Furthermore if I add the line

Code:
format_adc_to_display(kbhit())


instead of

Code:

format_adc_to_display(ch);


I see that kbhit is always zero on my display. I put a scope probe right on the the Rx pin (RC7) of the receiving pic and I do see 0/5V signals that idle high. So for some reason the pic doesn't think there are bytes coming in.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 03, 2009 12:32 pm     Reply with quote

Quote:
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

Why don't you edit the #use rs232() statement, and add the ENABLE
parameter, and specify your DE pin there. And then, remove the
manual DE control statements in your code. Let the CCS library code
handle the RS-485 enable pin. Do this in your transmitter PIC program.
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Wed Jun 03, 2009 12:44 pm     Reply with quote

PCM programmer wrote:
Quote:
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

Why don't you edit the #use rs232() statement, and add the ENABLE
parameter, and specify your DE pin there. And then, remove the
manual DE control statements in your code. Let the CCS library code
handle the RS-485 enable pin. Do this in your transmitter PIC program.

I did that and same thing. I stripped away all the unnecessary stuff in the code and now the TX PIC code is:
Code:

#include <18F2525.h>
#device ADC=10 
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ENABLE = PIN_B0)

#define ZERO_SPAN_SW       PIN_B5
#define OFFLINE_RESET_SW    PIN_B4
#define DE_RE   PIN_B0
#define EXMO_CAL_SW         8
#define EXMO_RST_SW         9


unsigned char exmo_sw=3; //assign ch dummy value to start



#INT_RB
void rb_isr(void)
{
 

 if (input(OFFLINE_RESET_SW) == 0)
 {
   exmo_sw = EXMO_RST_SW;
      
 }// if (input(OFFLINE_RESET_SW) == 0)

else if ( input(ZERO_SPAN_SW) == 0)//else zero_span switch activated

         exmo_sw = EXMO_CAL_SW;
      
 
} //end void rb_isr(void)


void main(void)
{




clear_interrupt(INT_RB);   
enable_interrupts(INT_RB);
enable_interrupts(GLOBAL);

while (1)
{

   
   printf("\n%u\r," exmo_sw); //only talk when receive a '$' from main bd.

   delay_ms(1000);   
}//while

}//main




And the receiving PIC code is:
Code:

#include <18F2525.h>
#device ADC=10  //set for 10 bit A/D
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)

#define EXMO_CAL_SW         8
#define EXMO_RST_SW         9
#define ZERO_SPAN_SW       PIN_B5
#define OFFLINE_RESET_SW    PIN_B4
#define DE_RE   PIN_B0
#define SPI_MODE_0_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_0_1  (SPI_L_TO_H)
#define SPI_MODE_1_0  (SPI_H_TO_L)
#define SPI_MODE_1_1  (SPI_H_TO_L | SPI_XMIT_L_TO_H)


unsigned char j;
unsigned char ch = 99;
unsigned char messages[3][22] = {
      ">>>PPM>=>>>>>>>>>>>>>",
      ">>DEGC>=>>>>>>>>>>>>>",
      ">STATE>=>>>>>>>>>>>>>"};

#include <string.h>
#include <sce5774.c>

void main(void)
{

output_low(DE_RE);
reset_display();
setup_spi(SPI_MASTER | SPI_MODE_0_0 |SPI_CLK_DIV_4);

set_brightness(0b11110110);

while (1)
{

if (kbhit())
{

   ch = getch();
     
   
      
}//if (kbhit())
else
{
ch = 49;
}
format_adc_to_display(ch);
delay_ms(500);




}//while

}//main
Humberto



Joined: 08 Sep 2003
Posts: 1215
Location: Buenos Aires, La Reina del Plata

View user's profile Send private message

PostPosted: Wed Jun 03, 2009 12:48 pm     Reply with quote

Being a two point communication it is not necesary any pull up/down resistors. The most obvious problem you have is the DE_RE pins handling as pointed by PCM Programmer.
Let the compiler to do its job, use the ENABLE option (see #use RS232 option in the CCS Compiler Manual )

http://www.ccsinfo.com/forum/viewtopic.php?t=33914&highlight=rs485
http://www.ccsinfo.com/forum/viewtopic.php?t=30630&highlight=rs485

Humberto


Last edited by Humberto on Wed Jun 03, 2009 12:50 pm; edited 1 time in total
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 03, 2009 12:50 pm     Reply with quote

You haven't stripped it down enough. Get rid of all the #int_rb stuff
and all the SPI stuff.

You have this huge delay of 500ms in your receiver loop. This prevents
incoming characters from being read from the UART. If you get more
than 2 chars in the UART, it will lock up the receiver. Get rid of that
delay, and also add the ERRORS parameter to the #use rs232()
statement in the receiver PIC code (and transmitter, too). This will
automatically clear an overrun errors that occur.
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Wed Jun 03, 2009 1:26 pm     Reply with quote

Okay, I think this is as bare as it can be. For the TX:
Code:

#include <18F2525.h>
#device ADC=10 
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ENABLE = PIN_B0, ERRORS)

#define DE_RE   PIN_B0


unsigned char exmo_sw=3;


void main(void)
{



while (1)
{

   
   printf("\n%u\r," exmo_sw);
   delay_ms(1000);   
}//while

}//main


And for the RX:
Code:

#include <18F2525.h>
#device ADC=10  //set for 10 bit A/D
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,ERRORS)

#define EXMO_CAL_SW         8
#define EXMO_RST_SW         9
#define TEST_PIN         PIN_B2
#define ZERO_SPAN_SW       PIN_B5
#define OFFLINE_RESET_SW    PIN_B4
#define DE_RE   PIN_B0



unsigned char ch = 99;


void main(void)
{

output_low(DE_RE);


while (1)
{

if (kbhit())
{

   ch = getch();
     
      output_low(TEST_PIN);
      
}//if (kbhit())
else
{
ch = 49;
output_high(TEST_PIN);
}

}//while

}//main



So now if kbhit is true then my TEST_PIN is low and if kbhit is false then TEST_PIN is high. And I always see TEST_PIN high.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 03, 2009 1:45 pm     Reply with quote

With that loop, it will only go low for a few usec, before it goes high again.
You might not see it.

A better test would be to toggle the pin every time you get a character:
Code:
void main()
{     
int8 ch;

output_low(TEST_PIN);

while(1)
  {
   ch = getch();
     
   output_toggle(TEST_PIN);
  }       

}
 


Or, more simple than that, simply wait until you get a character.
Then set the pin high.
Code:
void main()
{     
int8 ch;

output_low(TEST_PIN);

ch = getch();  // Wait for a char
     
output_high(TEST_PIN);

while(1);
}
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Wed Jun 03, 2009 3:03 pm     Reply with quote

Looks like one of the MAX487 chips has gone bonkers on me. I used another bd as the RX and it appears to work with the test programs, I see the testpin toggle using the first code you suggested.

Thanks.
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Wed Jun 03, 2009 3:36 pm     Reply with quote

PCM Programmer, with regards to this test program:

Code:

void main()
{     
int8 ch;

output_low(TEST_PIN);

while(1)
  {
   ch = getch();
     
   output_toggle(TEST_PIN);
  }       

}


How long does the PIC wait to get a character with the getch() function before timing out? Can I assume that if it reaches the output_toggle() then it has received a character? On the scope the testpin is low most of time and goes high for about 1.25 ms at a time.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jun 03, 2009 3:41 pm     Reply with quote

It never times out. It waits forever, if necessary.
mkuang



Joined: 14 Dec 2007
Posts: 257

View user's profile Send private message Send e-mail

PostPosted: Thu Jun 04, 2009 9:58 am     Reply with quote

Thanks PCM Programmer. I modified the test programs slightly so that PIC1 talks, PIC2 waits using kbhit, then look for the character 'E' in the message, and then grab the character after the E and send that out via the printf. So essentially the two pics take turns talking on the RS485 line so there is no bus conflict. So for the the TX pic:
Code:


#include <18F2525.h>
#device ADC=10 
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ENABLE = PIN_B0, ERRORS)

#define ZERO_SPAN_SW       PIN_B5
#define OFFLINE_RESET_SW    PIN_B4
#define DE_RE   PIN_B0
#define EXMO_CAL_SW         8
#define EXMO_RST_SW         9


unsigned char exmo_sw=4; //assign ch dummy value to start


void main(void)
{



while (1)
{

   
   printf("\nE%u", exmo_sw);

   delay_ms(1000);   
}//while

}//main



And for the RX pic (which answers)
Code:

#include <18F2525.h>
#device ADC=10  //set for 10 bit A/D
#fuses XT,NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ENABLE = PIN_B0, ERRORS)

#define EXMO_CAL_SW         8
#define EXMO_RST_SW         9
#define TEST_PIN         PIN_B2
#define ZERO_SPAN_SW       PIN_B5
#define OFFLINE_RESET_SW    PIN_B4
#define DE_RE   PIN_B0




void main()
{     
int8 ch;

output_low(TEST_PIN);

while(1)
  {
if (kbhit())
{
   ch = getch();
   if (ch == 'E')
      {
   ch = getchar();
      output_toggle(TEST_PIN);
   printf("\nI received %c", ch);
   }
  }       
}


}


And I see in hyperterminal:

Code:

4
I received 4
4
I received 4
.
.
.


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