View previous topic :: View next topic |
Author |
Message |
magnus
Joined: 09 May 2013 Posts: 15
|
PIC MODBUS |
Posted: Thu May 09, 2013 11:13 am |
|
|
Hello guys.
I need to communicate a microcontroller PIC 16F877A with my PC via modbus RTU/485. My PC send a data to my PIC, pic make a calc and then return a value to my PIC. Can you help me???? ![Question](images/smiles/icon_question.gif) |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Fri May 10, 2013 1:27 am |
|
|
We can probably help you. I've got Modbus RTU over RS485 working on my PIC projects. We're not going to write the code for you. There is working "driver" code and examples of modbus master and slaves provided by CCS. Look at those first and get them working on your hardware, then develop your own code around them. If you get stuck, then come back to us and we can help.
Modbus is not a bus you send data or messages to and from things. Slaves have "registers" of various types that masters can read from and write to. Slaves cannot send anything, all data has to be read by the master. |
|
![](templates/subSilver/images/spacer.gif) |
magnus
Joined: 09 May 2013 Posts: 15
|
|
Posted: Fri May 10, 2013 5:40 am |
|
|
hmmm, thank you. To send a value to slave, do I need write registers? To read the result do I need read registers???
Do you can show me an example? |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9170 Location: Greensville,Ontario
|
|
Posted: Fri May 10, 2013 6:08 am |
|
|
Seriously ? As RFD said..CCS SUPPLIES drivers AND example code !!
They're in the examples folders.... |
|
![](templates/subSilver/images/spacer.gif) |
magnus
Joined: 09 May 2013 Posts: 15
|
|
Posted: Fri May 10, 2013 6:32 am |
|
|
Hey, sorry about my ignorance. I never did anything about modbus and I'm lost. Really really sorry. |
|
![](templates/subSilver/images/spacer.gif) |
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Fri May 10, 2013 6:54 am |
|
|
The only thing missing in the OP is:
"I'm using CCS compiler"
that would have made my day.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
![](templates/subSilver/images/spacer.gif) |
dyeatman
Joined: 06 Sep 2003 Posts: 1924 Location: Norman, OK
|
|
Posted: Fri May 10, 2013 2:37 pm |
|
|
Magnus,
There is a lot of code in this forum if you do a search for Modbus or for
RS485. Thats in addition to the examples CCS provides that were
mentioned above.
If you Google for "CCS Modbus RS485" you will find a bunch as well.
Once you put something together and come back, be sure to tell us
the version of CCS you are using. _________________ Google and Forum Search are some of your best tools!!!! |
|
![](templates/subSilver/images/spacer.gif) |
magnus
Joined: 09 May 2013 Posts: 15
|
|
Posted: Wed May 15, 2013 7:38 am |
|
|
Hello,
For RS-485 communication, do I need put the control pins here?
#define MODBUS_SERIAL_ENABLE_PIN X
#define MODBUS_SERIAL_RX_ENABLE X
Can be any pin or there is a specific pin?
sorry about my little knowledge!
CCS ver 4.140 |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed May 15, 2013 1:58 pm |
|
|
Yes, you can use any i/o pin that can be configured as an output pin.
(Most of them can). |
|
![](templates/subSilver/images/spacer.gif) |
magnus
Joined: 09 May 2013 Posts: 15
|
|
Posted: Thu May 16, 2013 12:08 pm |
|
|
Hello again
My pic isn't enabling MAX 485. How do I should put in program?
This way:
#define MODBUS_SERIAL_ENABLE_PIN PIN_B2
#define MODBUS_SERIAL_RX_ENABLE 0
or this:
#define MODBUS_SERIAL_ENABLE_PIN PIN_B2
#define MODBUS_SERIAL_RX_ENABLE PIN_B2
or another way...? |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu May 16, 2013 12:25 pm |
|
|
Post a link to your board schematic(s). |
|
![](templates/subSilver/images/spacer.gif) |
magnus
Joined: 09 May 2013 Posts: 15
|
|
Posted: Mon May 20, 2013 6:58 am |
|
|
Like this:
But i didn't put the pull-up resistor in RE/DE.
And I am using RB0 and RB1 pins to RX and TX like example code.
Am I right? How do I put in the program?
Thanks in advance! |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon May 20, 2013 9:37 am |
|
|
For that type of circuit you need something like:
Code: |
// Must set slave or master.
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
// Must set protocol type
#define MODBUS_SERIAL_TYPE MODBUS_RTU
// This is the enable. Only define MODBUS_SERIAL_RX_ENABLE if you
// have two separate enable connections.
#define MODBUS_SERIAL_ENABLE_PIN PIN_B2
// Must set serial bit rate. DON'T GO much faster as the timing becomes
// critical and unreliable on PICs.
#define MODBUS_SERIAL_BAUD 38400
// Tell the driver which serial port to use. It will set it up for us.
// _INT_RDA for first hardware serial port, _INT_RDA2 for second etc, up to _INT_RDA4. _INT_EXT for software serial (I think - I haven't tried it)
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
// Include the driver. It will define the serial port for us.
#include "modbus.c"
...
// In initialisation code near the start of main()
// Modbus_init turns on global interrupts for us, so we must not.
modbus_init();
if (modbus_kbhit())
{
// We have received something on the modbus. Do something!
// This is covered in the examples. Note the examples implement
// eight of everything; no more , no less.
}
|
Tips:
1) The CCS modbus drivers use interrupts, and enable them when initialised. Don't try to mess about with global interrupts in your code.
2) The driver uses timer2 in RTU mode, but not in ASCII mode. Do not try to use timer2 in your own code with RTU mode enabled.
3) The driver sets up the serial port, and its related interrupts. Don't try to set these up or use them yourself.
4) Don't try to go too fast. Modbus RTU relies on timed delays directly related to character transmission times. I found 38400 baud was about as fast as could make the PIC modbus stuff work reliably.
5) Use the CCS example code as the starting point for a modbus slave but remember, it does just eight of the basic endpoint types. Most practical applications will need more. Read the code very carefully to understand what its doing and modify carefully.
6) The driver is written to implement one physcial modbus port only. It will need modification to implement more.
For the PC end I use an FTDI USB-RS485-WE-1800-BT wired to a connector suitable for my project. Like most FTDI stuff, it just works.
I use NModbus 3.5 to provide a C# API in Visual Studio 2012 Express or Professional. That works too, provided you can get your head around the interface model of .net code.
RF Developer |
|
![](templates/subSilver/images/spacer.gif) |
magnus
Joined: 09 May 2013 Posts: 15
|
|
Posted: Tue May 21, 2013 7:49 am |
|
|
Thank you RFD.
But I have more one problem...
when I put MODBUS_INT_RDA like MODBUS_SERIAL_INT_SOURCE appears the following error:
***Error 100"C:\Program Files\PICC\drivers\modbus.c" Line 215(8,85):USE parameter value is out of range "ERROR"
***Error 12"C:\Program Files\PICC\drivers\modbus.c" Line 362(13,18):Undefined identifier kbhit
***Error 12"C:\Program Files\PICC\drivers\modbus.c" Line 362(40,41):Undefined identifier getch
***Error 12"C:\Program Files\PICC\drivers\modbus.c" Line 454(9,10):Undefined identifier putchar
***Error 12"C:\Program Files\PICC\drivers\modbus.c" Line 474(11,12):Undefined identifier getch
5 Errors,0 Warnings.
And directs me for this part of code:
Code: |
[#if( MODBUS_SERIAL_INT_SOURCE == MODBUS_INT_RDA )
[b]#use rs232(baud=MODBUS_SERIAL_BAUD, UART1, parity=N, stream=MODBUS_SERIAL, error)[/b]
#define RCV_OFF() {disable_interrupts(INT_RDA);}
#elif( MODBUS_SERIAL_INT_SOURCE == MODBUS_INT_RDA2 )
#use rs232(baud=MODBUS_SERIAL_BAUD, UART2, parity=N, stream=MODBUS_SERIAL, error)
#define RCV_OFF() {disable_interrupts(INT_RDA2);}
#elif( MODBUS_SERIAL_INT_SOURCE == MODBUS_INT_EXT )
#use rs232(baud=MODBUS_SERIAL_BAUD, xmit=MODBUS_SERIAL_TX_PIN, rcv=MODBUS_SERIAL_RX_PIN, parity=N, stream=MODBUS_SERIAL, disable_ints)
#define RCV_OFF() {disable_interrupts(INT_EXT);}
#else
#error Please define a correct interrupt source
#endif
] |
on <modbus.c>
please help me! I don't know what is these error! |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue May 21, 2013 8:47 am |
|
|
Hmm, I'm not totally sure... but modbus.c sort of assumes you have more than one hardware serial port. What I mean is that it uses "UART1", "UART2" etc. to select which port to use in its #use rs232() line. In your code, its that line that's causing the error. The other "errors" are the result of the #use rs232 not working: fix the #use rs232 and all should be well... probably.
What I suspect is that you are using a processor with only one hardware serial port, and the "UART1" is causing the problem. Yes, the 16F877A has only one serial port.
So, what can you do? In this case I suggest you copy modbus.c to somewhere in your project directory, renaming it to something like "single_uart_modbus.c". Include this is your code instead of the original "mobus.c". Then in the copy, remove "UART1," from the line that's causing the first error, causing it to dfault to the one and only hardware serial port. Make sure you have not got any #use rs232 lines before the modbus.c include (see below).
Yes, you are modifying (a copy of) the modbus driver, but in this case I think you have to. Remember to put a comment in to show *exactly* what you have changed.
Having one hardware serial port also means you can't use any printfs or anything like that *unless* you define another, software, serial interface after the modbus include, and give it a different stream name, and then use the stream name consistently for your I/O. If you don't the compiler may well try to send/receive from the modbus serial port, causing all sorts of horrible things to happen and confuse you.
As you can see from that error line, modbus.c calls refers to its serial port by a stream called MODBUS_SERIAL. Do not try to send or receive anything from MODBUS_SERIAL, modbus.c wants it all for itself.
Another problem I've just found, which is related, is that older compiler versions (I currently use 4.132 but developed my modbus project on a earlier 4.1xx version) seem to have changed the name by which the compiler refers to the uart transmit status and control register for(possibly) some PICs. In the older version on which I first developed my modbus project, it called the first UARTs TXSTA "TXSTA", just as it would be on a single UART PIC like your 16F877A. UART2 on my 18F6722 was called "TXSTA2". V4.132 doesn't recognise "TXSTA" for the 18F6722, it calls it "TXSTA1" instead., which makes sense, but messes up modbus.c :-( So when I came, just now, to recompile my working code on V4.132, it failed :-(( Don't worry: it shouldn't matter for your single UART PIC.
Oh, and another tip I forgot: Modbus.c assumes a baud rate of 9600 baud if you don't specify the rate using #define MODBUS_SERIAL_BAUD.
RF Developer
Last edited by RF_Developer on Tue May 21, 2013 8:53 am; edited 2 times in total |
|
![](templates/subSilver/images/spacer.gif) |
|