|
|
View previous topic :: View next topic |
Author |
Message |
vietnh
Joined: 02 Jul 2015 Posts: 3 Location: Vietnam
|
Modbus RTU with pic |
Posted: Thu Jul 02, 2015 2:21 am |
|
|
I tried to send data from pic to computer using modbus RTU, I used modbus poll and I can't receive anything.
My code is simple
Code: |
#include <main.h>
#define MODBUS_PROTOCOL MODBUS_PROTOCOL_SERIAL
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#define MODBUS_SERIAL_TYPE MODBUS_RTU //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_SERIAL_TX_PIN PIN_C6 // Data transmit pin
#define MODBUS_SERIAL_RX_PIN PIN_C7 // Data receive pin
#define MODBUS_SERIAL_ENABLE_PIN PIN_C5 // Controls DE pin for RS485
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_RX_ENABLE PIN_C5 // Controls RE pin for RS485
#define MODBUS_SLAVE_ADDRESS 31
#include "modbus.c"
int16 data=0xF5;
int respond;
void main()
{
output_high(PIN_C3);
delay_ms(500);
output_low(PIN_C3);
delay_ms(500);
modbus_init();
while(TRUE)
{
output_high(PIN_C3);
if(modbus_kbhit())
{
if((modbus_rx.address == 31))
{
modbus_diagnostics_rsp(MODBUS_SLAVE_ADDRESS,modbus_rx.func,data);
}
delay_ms(400);
output_low(PIN_C3);
delay_ms(400);
}
}
}
|
I connected PIN C3 to Led to debug, my code stuck at "if(modbus_kbhit())", I replace it by code "while(!modbus_kbhit());" but it still did not run.
Modbus poll only had a status "Timeout error".
Thanks for your attention! _________________ Best Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19542
|
|
Posted: Thu Jul 02, 2015 3:16 am |
|
|
Have you actually verified with a scope that there is serial data arriving at the RX pin?. That the signal here is idling high, and going low?.
modbus_kbhit won't ever go true unless data is being received. Look at the hardware first.
Then what you are doing is basically the same as the example (ex_modbus_slave.c). Note that this doesn't set 'MODBUS_SLAVE_ADDRESS'. It sets 'MODBUS_ADDRESS'. The CCS modbus driver does not use MODBUS_SLAVE_ADDRESS.... |
|
|
vietnh
Joined: 02 Jul 2015 Posts: 3 Location: Vietnam
|
|
Posted: Thu Jul 02, 2015 3:29 am |
|
|
My hardware has no problem. I used it to send and receive data to computer by using Hercule.
I am using the version CCS 5.015 and I read the library, it had to define MODBUS_SLAVE_ADDRESS, didn't use MODBUS_ADDRESS as previous version.
I saw the ex_modbus_slave.c but I can't do.
Ttelmah wrote: | Have you actually verified with a scope that there is serial data arriving at the RX pin?. That the signal here is idling high, and going low?.
modbus_kbhit won't ever go true unless data is being received. Look at the hardware first.
Then what you are doing is basically the same as the example (ex_modbus_slave.c). Note that this doesn't set 'MODBUS_SLAVE_ADDRESS'. It sets 'MODBUS_ADDRESS'. The CCS modbus driver does not use MODBUS_SLAVE_ADDRESS.... |
_________________ Best Regards |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Thu Jul 02, 2015 4:27 am |
|
|
Code: | #define MODBUS_SERIAL_TX_PIN PIN_C6 // Data transmit pin
#define MODBUS_SERIAL_RX_PIN PIN_C7 // Data receive pin
#define MODBUS_SERIAL_ENABLE_PIN PIN_C5 // Controls DE pin for RS485
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_RX_ENABLE PIN_C5 // Controls RE pin for RS485 |
I am concerned about this. The serial pin definitions are only needed if you are NOT using a hardware UART. Your interrupt source definition forces the modbus driver to use hardware UART1. So, the pin definitions won't do anything and are be confusing: so delete them.
Unless you have two enable pins and are using full duplex (Modbus is half-duplex), don't define both. Defining both to be the same pin may cause a clash, possibly preventing receiving data. Even if your hardware has two pins on its interface IC, for Modbus, connect them together and drive them as a single pin.
These three are defined in the driver, modbus.c. You only need to define them if your configuration is different.
Normally you would only have one enable pin: MODBUS_SERIAL_ENABLE_PIN and define that as the pin you are using. Its best to let the driver define the buffer size.
What I expect your code to have is:
Code: | #define MODBUS_SERIAL_ENABLE_PIN PIN_C5 // Controls DE pin for RS485 |
No tx/rx pin definitions, no rx enable definition, no buffer size.
I cannot understand how your code could get "stuck" at modbus_kbhit(). The routine is simple, and never waits for anything - it is non-blocking - and will always return quickly.
Quote: | I read the library, it had to define MODBUS_SLAVE_ADDRESS, didn't use MODBUS_ADDRESS as previous version. |
The library doesn't use either: the example does. Seems odd to define it and then not use it however. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19542
|
|
Posted: Thu Jul 02, 2015 11:22 am |
|
|
and the _slave address_, is used in the _master_ example. The modbus address, is used in the slave example.
I'd be really suspicious of a combination of hardware and software. The settings for the buffer control are wrong, as RF_Developer has said, and I suspect there is no pull-up on the output line from the receive buffer. The UART will then probably be triggering framing errors, which might cause problems with the kbhit function. kbhit will then return true, but with an error, and the code as posted will then hang. |
|
|
vietnh
Joined: 02 Jul 2015 Posts: 3 Location: Vietnam
|
|
Posted: Thu Jul 02, 2015 5:08 pm |
|
|
I don't think it's important, the_slave_address or modbus_address is defined as constant. I checked the modbus library, as RF_Developer said, the slave address and modbus address are not used in the modbus library. I replaced the slave address by modbus address but nothing changed.
Ttelmah wrote: | and the _slave address_, is used in the _master_ example. The modbus address, is used in the slave example.
I'd be really suspicious of a combination of hardware and software. The settings for the buffer control are wrong, as RF_Developer has said, and I suspect there is no pull-up on the output line from the receive buffer. The UART will then probably be triggering framing errors, which might cause problems with the kbhit function. kbhit will then return true, but with an error, and the code as posted will then hang. |
_________________ Best Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19542
|
|
Posted: Fri Jul 03, 2015 12:48 am |
|
|
Yes.
You are ignoring the important errors though. The actual setup being used is fundamentally floored. Your 'oh the hardware works with something else' is _not_ the way to get things working. It has to be right for what the driver expects and uses.
The point is if you are going to make a setting, at least check it has some connection to what you are doing. The slave address setting is not used by the slave driver, so should not be set. If you want to have an address setting, it wants to be the modbus address setting, which won't make any difference for the code as posted, but would if later you start using an address (which you should - don't go coding addresses in the code like '31').
Random extra settings should be avoided like the plague. They just make the code bulkier, and more likely to have errors.
With Modbus you have the choice of operating with separate buffer and receive enables or a single 'shared' line. Rf_Developer has told you how to set it up for the single line (not how you have it), and you need to have a pull up resistor on the output from the receive buffer when it is used like this (so that when the buffer is set to transmit, the PIC does not receive anything), otherwise thie modbus driver will receive spurious data when transmitting.
With the hardware setup correctly, and the defines set to match the hardware, the Modbus driver _works_. That it is not working says that one or more of your settings is wrong, or there is a problem with the hardware.
You talk about kbhit hanging (it won't). However the code as posted _would_ hang (not at the kbhit), if the bus line is floating, and the buffer is not correctly enabled. In this circumstance, it'll give an error on the receive, and then since your code does not check for or handle errors, the next part would hang.
The delay in the reply loop, and the fact that the code does not reply to address 0 (required), is also a problem. The transmitter will timeout for most requests, since you don't have any handler code.
Your initialisation only needs something like:
Code: |
#include <main.h>
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
//This alone, tells the code to setup to use the hardware UART - nothing else needed
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_TYPE MODBUS_RTU //use MODBUS_ASCII for ASCII mode
#define MODBUS_SERIAL_BAUD 9600
#define MODBUS_SERIAL_ENABLE_PIN PIN_C5 //This is all that is needed to use the enable
#include <modbus.c>
#define MODBUS_ADDRESS 31
void main()
{
setup_adc_ports(NO_ANALOGS);
//move lines as needed here
//then the test for receive data should be:
if(modbus_kbhit())
{
if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
|
The slave is _required_ to handle address 0. You can't just ignore this.
Then get rid of the delay in the loop.
The master device is going to timeout, since it does not receive a reply from this device. If you are ignoring functions, you should trigger an exception_rsp. |
|
|
|
|
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
|