|
|
View previous topic :: View next topic |
Author |
Message |
varadharaj
Joined: 09 Apr 2012 Posts: 19 Location: Salem
|
Reg: Pic communication with PLC |
Posted: Thu May 23, 2013 12:07 am |
|
|
Hi,
I am using pic 16f877a for communicating with PLC. The PLC is using Modbus RTU (RS485) protocol. I have connected it with PC and using Rs232 hexcom tool. I have checked the communication. It is successful.
I have tried with these given address and values, And PLC has replied like given below,
transmitted code:010300060001640b then enter
010302015979EE
Then i interfaced the PLC with microcontroller (RS485 to UART). I used the following code,
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
//use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=DOM,errors)
//#use rs232(baud=9600,parity=N,xmit=PIN_B0,rcv=PIN_B1,bits=8,stream=LED)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#include <lcd.c>
char ct[]={0x01,0x03,0x00,0x06,0x00,0x01,0x64,0x0B};
char st[]={0x01,0x03,0x00,0x0A,0x00,0x01,0xBD,0x47};
char cn[]={0x01,0x03,0x00,0x14,0x00,0x01,0xCA,0x41};
int counter = 0;
char a[7] = {0};
int1 flag = 0;
/*#int_RDA
void RDA_isr(void)
{
a[counter] = getc();
counter ++;
}*/
void main()
{
int i;
lcd_init();
delay_ms(5000);
lcd_init();
printf(lcd_putc,"WELCOME");
// enable_interrupts(INT_RDA);
// enable_interrupts(GLOBAL);
while(1)
{
for(i = 0; i < 8; i++)
{
putc(ct[i]);
delay_us(1000000/19200);
}
printf("\r");
for(i = 0; i < 7; i++)
lcd_putc(getc());
counter = 0;
flag = 0;
delay_ms(5000);
lcd_init();
delay_ms(5000);
}
// TODO: USER CODE!!
}
|
The LCD displayed only 0103 character and stopped there itself. Is there any suggestion to get the proper values ?
I don't want to use modbus.c because i need only 3 values from the PLC. _________________ Embedding Innovation |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Thu May 23, 2013 12:59 am |
|
|
What is your compiler version number?
ALWAYS add the 'errors' keyword to the #rs232 line, unless you have strong reasons to handle the errors situations yourself. The hardware UART will stop working when the receive buffer overflows, that is after receiving the 3rd byte without you reading from the FIFO. The effect is that you can only read 3 bytes and then on the next call to getc() the program waits forever.
When you add the 'errors' keyword the compiler will add code to clear the error bits and start the UART again (you can still loose data but at least new data will be received).
This looks very much like what is happening in your program, except that you receive 4 characters instead of the 3 that fit into the FIFO buffer. |
|
|
varadharaj
Joined: 09 Apr 2012 Posts: 19 Location: Salem
|
compiler version number |
Posted: Thu May 23, 2013 1:05 am |
|
|
4.074 is my version.
I used errors in the #use Rs232 line, but no change.
Thanks for your quick reply. _________________ Embedding Innovation |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19555
|
|
Posted: Thu May 23, 2013 2:38 am |
|
|
There is something fundamentally 'odd' about what you are doing/showing.
If the two lines shown with the PC comms, are hex displays of the data, then the the first byte reply will not be displayed as 01 on the LCD, but would be control code 01, which is the SOH character, and would not display as 01 on the LCD. However if they are ASCII displays of the data, then the sequence you are sending from the PIC, is not the same as the one from the PC.
0x1, is the character 1. the character '1' (ASCII), is 0x31.
Are you using RTU, or Modbus ASCII?.
If RTU, then your display code, needs to be:
printf(lcd_putc,"%02x",(getc());
since otherwise you are sending ASCII control codes to the LCD, not text.
Conversely, if it is Modbus ASCII, then your transmission is wrong, and needs to use:
printf("%02x",ct[i]);
One or the other is wrong.....
Best Wishes |
|
|
varadharaj
Joined: 09 Apr 2012 Posts: 19 Location: Salem
|
communication |
Posted: Thu May 23, 2013 3:21 am |
|
|
Sorry @telmah,
the origal line is,
printf(lcd_putc,"%x",getc());
I am using modbus RTU
Any delay should be given for sending and receiving. My baudrate is 19200..
thank you _________________ Embedding Innovation |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19555
|
|
Posted: Thu May 23, 2013 4:33 am |
|
|
Doesn't give great confidence, when you say "I used the following code", and then obviously didn't....
Done a modified version. See whether this works:
Code: |
#include <16F877A.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=20000000)
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,ERRORS)
#include <lcd.c>
const char ct[]={0x01,0x03,0x00,0x06,0x00,0x01,0x64,0x0B};
#define BUFFER_SIZE 16
char rx_buffer[BUFFER_SIZE];
int next_in = 0;
int next_out = 0;
#define bkbhit (next_in!=next_out)
int16 wait_for=0;
#int_RDA
void RDA_isr(void)
{
int t;
rx_buffer[next_in]=getc();
t=next_in++;
if (next_in == BUFFER_SIZE) next_in=0;
if(next_in==next_out)
next_in=t; //overflow - throw data
}
char bgetc(void)
{
char c;
while(!bkbhit) ;
c=rx_buffer[next_out];
if (++next_out == BUFFER_SIZE) next_out=0;
return(c);
}
#define BYTE_TIME (1000000/1920) //ten bits per byte time
#INT_TIMER2
void tick(void)
{
//Timer called 125*/sec
if (wait_for>0) --wait_for;
}
//This does nothing, except stop the compiler warning when ERRORS is enabled.
void dummy(void)
{
int r;
r=RS232_ERRORS;
}
void main()
{
int i;
lcd_init();
delay_ms(1000);
lcd_init();
printf(lcd_putc,"WELCOME");
setup_timer_2(T2_DIV_BY_16,249,10); //125Hz tick
enable_interrupts(INT_RDA);
enable_interrupts(GLOBAL);
enable_interrupts(INT_TIMER2);
delay_ms(1000);
while(TRUE)
{
//Must delay for 3.5 byte times before transmission
delay_us(BYTE_TIME*3.5);
for(i = 0; i < SIZEOF(ct); i++)
{
putc(ct[i]);
}
//Modbus RTU does _not_ have a CR at the end.
//Only modbus ASCII has this
//Now wait for reply.
wait_for=5;
while (wait_for);
lcd_putc('\f');
while (bkbhit)
{
//print any reply
printf(lcd_putc,"%02x",bgetc());
}
}
}
|
|
|
|
varadharaj
Joined: 09 Apr 2012 Posts: 19 Location: Salem
|
Thanks |
Posted: Thu May 23, 2013 7:27 am |
|
|
Thank you very much Ttelmah,
The code which you have posted is really helpful for me to understand about the delays at start and end.
I changed your code little bit for my application. And it is working perfectly.
Thanks to you and cliestra for helping ... _________________ Embedding Innovation |
|
|
|
|
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
|