|
|
View previous topic :: View next topic |
Author |
Message |
koray_duran
Joined: 04 Feb 2010 Posts: 37
|
Increase Modbus Points |
Posted: Fri Dec 16, 2011 1:57 am |
|
|
Hi,
I work on modbus in these days, maybe it is very simple question but i couldn't figure out how to increase modbus points. It seems only 8 points per type. I wait your answers.
Here is my code:
Code: |
#include <18F67J60.h>
#fuses HS, NOWDT, NOPROTECT, NOFCMEN, PRIMARY, NOETHLED
#use delay(clock=25M)
#define MODBUS_TYPE MODBUS_TYPE_SLAVE
#define MODBUS_SERIAL_RX_BUFFER_SIZE 64
#define MODBUS_SERIAL_BAUD 9600
#define USE_WITH_PC 1
#define POT PIN_F3
#define BUT PIN_B0
#define LED PIN_B4
#ifndef USE_WITH_PC
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_EXT
#define MODBUS_SERIAL_TX_PIN PIN_C6 // Data transmit pin
#define MODBUS_SERIAL_RX_PIN PIN_C7 // Data receive pin
//The following should be defined for RS485 communication
//#define MODBUS_SERIAL_ENABLE_PIN PIN_B0 // Controls DE pin for RS485
//#define MODBUS_SERIAL_RX_ENABLE PIN_B0 // Controls RE pin for RS485
#else
#define MODBUS_SERIAL_INT_SOURCE MODBUS_INT_RDA
#endif
#include "modbus.c"
#define MODBUS_ADDRESS 0x01
/*This function may come in handy for you since MODBUS uses MSB first.*/
int8 swap_bits(int8 c)
{
return ((c&1)?128:0)|((c&2)?64:0)|((c&4)?32:0)|((c&8)?16:0)|((c&16)?8:0)
|((c&32)?4:0)|((c&64)?2:0)|((c&128)?1:0);
}
void main()
{
int8 coils = 0b00000101;
int8 inputs = 0b00001001;
int16 hold_regs[40] = {
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800,
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800,
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800,
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800,
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800
};
int16 input_regs[40] = {
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800,
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800,
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800,
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800,
0x1100,0x2200,0x3300,0x4400,0x5500,0x6600,0x7700,0x8800
};
int16 event_count = 0;
modbus_init();
while(TRUE)
{
while(!modbus_kbhit());
//check address against our address, 0 is broadcast
if((modbus_rx.address == MODBUS_ADDRESS) || modbus_rx.address == 0)
{
switch(modbus_rx.func)
{
case FUNC_READ_COILS: //read coils
case FUNC_READ_DISCRETE_INPUT: //read inputs
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int8 data;
if(modbus_rx.func == FUNC_READ_COILS)
data = coils>>(modbus_rx.data[1]); //move to the starting coil
else
data = inputs>>(modbus_rx.data[1]); //move to the starting input
data = data & (0xFF>>(8-modbus_rx.data[3])); //0 out values after quantity
if(modbus_rx.func == FUNC_READ_COILS)
modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
else
modbus_read_discrete_input_rsp(MODBUS_ADDRESS, 0x01, &data);
event_count++;
}
break;
case FUNC_READ_HOLDING_REGISTERS:
case FUNC_READ_INPUT_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
if(modbus_rx.func == FUNC_READ_HOLDING_REGISTERS)
modbus_read_holding_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),hold_regs+modbus_rx.data[1]);
else
modbus_read_input_registers_rsp(MODBUS_ADDRESS,(modbus_rx.data[3]*2),input_regs+modbus_rx.data[1]);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_COIL: //write coil
if(modbus_rx.data[0] || modbus_rx.data[3] || modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else if(modbus_rx.data[2] != 0xFF && modbus_rx.data[2] != 0x00)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_VALUE);
else
{
//coils are stored msb->lsb so we must use 7-address
if(modbus_rx.data[2] == 0xFF)
bit_set(coils,7-modbus_rx.data[1]);
else
bit_clear(coils,7-modbus_rx.data[1]);
modbus_write_single_coil_rsp(MODBUS_ADDRESS,modbus_rx.data[1],((int16)(modbus_rx.data[2]))<<8);
event_count++;
}
break;
case FUNC_WRITE_SINGLE_REGISTER:
if(modbus_rx.data[0] || modbus_rx.data[1] >= 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
//the registers are stored in little endian format
hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[3],modbus_rx.data[2]);
modbus_write_single_register_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
}
break;
case FUNC_WRITE_MULTIPLE_COILS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
modbus_rx.data[5] = swap_bits(modbus_rx.data[5]);
for(i=modbus_rx.data[1],j=0; i < modbus_rx.data[1]+modbus_rx.data[3]; ++i,++j)
{
if(bit_test(modbus_rx.data[5],j))
bit_set(coils,7-i);
else
bit_clear(coils,7-i);
}
modbus_write_multiple_coils_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
case FUNC_WRITE_MULTIPLE_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
hold_regs[i] = make16(modbus_rx.data[j+1],modbus_rx.data[j]);
modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
default: //We don't support the function, so return exception
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_FUNCTION);
}
}
}
}
|
|
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Fri Dec 16, 2011 3:25 am |
|
|
Read the code. All you need to know is there.
Try walking through it. Work out line by line what the code does, imagining what will happen with various different values. Try it with different MODBUS addresses.
Here's a hint: you are wondering why it only allows you 8 of each type of item. Try searching for the number 8 in the code, or perhaps 7. Where does it appear? Why does it appear where it does? What would happen if you changed it?
Walkthroughs are one of the the simplest and effective code reading and checking techniques. Use them to improve your understanding of C (and of other code). It will improve the code you write too.
RF Developer |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Dec 16, 2011 5:46 am |
|
|
As an additional suggestion, read the MODBUS application protocol specification from modbus.org to understand what the software does. |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Sat Jan 07, 2012 8:58 pm |
|
|
Hi everyone,
I was successful in implement modbus protocol using function 3 and function 4, i.e holding and input registers. However I'm finding it tricky to implement function 10, i.e write multiple register. Since the input here is 2 bytes I don't know how to work on it.
Code: |
case FUNC_WRITE_MULTIPLE_REGISTERS:
if(modbus_rx.data[0] || modbus_rx.data[2] ||
modbus_rx.data[1] >= 8 || modbus_rx.data[3]+modbus_rx.data[1] > 8)
modbus_exception_rsp(MODBUS_ADDRESS,modbus_rx.func,ILLEGAL_DATA_ADDRESS);
else
{
int i,j;
for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2)
hold_regs[i] = make16(modbus_rx.data[j+1],modbus_rx.data[j]);
modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
}
break;
|
How do I proceed ? I want to write data on over this function. Please help. |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
problem not yet sorted |
Posted: Tue Jan 10, 2012 2:16 am |
|
|
Hi,
I tried using multiple registers for writing, and the response showed ok.
However, I've only been able to write a single register from the multiple register case.
I did the following modification in the code.
Code: |
hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[j],modbus_rx.data[j+1]);
|
Please help. How should I proceed?
Eagerly awaiting for your response.
SId |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Jan 10, 2012 3:59 am |
|
|
In contrast to the reasonable code in your previous post, your writing all data to a single holding register. Why? |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Tue Jan 10, 2012 10:47 pm |
|
|
I'm bit confused while figuring out the logic. I don't understand the 'i' variable, it should get the data and and add to the holding register and increment. But that is not happening. Thats when I used
Code: |
hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[j],modbus_rx.data[j+1]);
|
which at least adds the data into an array of holding register. But since 'modbus_rx.data[1]' is one its suppose to add only one value.
Later I tried with
Code: |
for(i=0, j=5; i < modbus_rx.data[4]/2; ++i, j+=2) //changed i=0
/*hold_regs[i+8]*/hold_regs[modbus_rx.data[i+8]] = make16(modbus_rx.data[j], modbus_rx.data[j+1]); // j=j+1 and j+1 =j
//hold_regs[modbus_rx.data[1]] = make16(modbus_rx.data[2], modbus_rx.data[3]);
modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
ax[0]=hold_regs[8];
ay[0]=hold_regs[9];
ax[1]=hold_regs[10];
ay[1]=hold_regs[11];
ax[2]=hold_regs[12];
ay[2]=hold_regs[13];
ax[3]=hold_regs[14];
ay[3]=hold_regs[15];
ax[4]=hold_regs[16];
ay[4]=hold_regs[17];
ax[5]=hold_regs[18];
ay[5]=hold_regs[19];
ax[6]=hold_regs[20];
ay[6]=hold_regs[21];
ax[7]=hold_regs[22];
ay[7]=hold_regs[23];
|
But again its not working Please help. I'm trying really hard.
Sid |
|
|
Sid2286
Joined: 12 Aug 2010 Posts: 119
|
|
Posted: Wed Jan 11, 2012 1:52 am |
|
|
Sorry for the trouble. problem is sorted out of writing on multiple register on modbus.
But now i cant write on eeprom in that case.
Code: |
for(i=0,j=5; i < modbus_rx.data[4]/2; ++i,j+=2) //changed i=0
hold_regs[i] = make16(modbus_rx.data[j],modbus_rx.data[j+1]); // j=j+1 and j+1 =j
modbus_write_multiple_registers_rsp(MODBUS_ADDRESS,
make16(modbus_rx.data[0],modbus_rx.data[1]),
make16(modbus_rx.data[2],modbus_rx.data[3]));
event_count++;
ax[0]=hold_regs[8];
ay[0]=hold_regs[9];
ax[1]=hold_regs[10];
ay[1]=hold_regs[11];
ax[2]=hold_regs[12];
ay[2]=hold_regs[13];
ax[3]=hold_regs[14];
ay[3]=hold_regs[15];
ax[4]=hold_regs[16];
ay[4]=hold_regs[17];
ax[5]=hold_regs[18];
ay[5]=hold_regs[19];
ax[6]=hold_regs[20];
ay[6]=hold_regs[21];
ax[7]=hold_regs[22];
ay[7]=hold_regs[23];
skipFlag[0]=hold_regs[24];
skipFlag[1]=hold_regs[25];
skipFlag[2]=hold_regs[26];
skipFlag[3]=hold_regs[27];
skipFlag[4]=hold_regs[28];
skipFlag[5]=hold_regs[29];
skipFlag[6]=hold_regs[30];
skipFlag[7]=hold_regs[31];
rs_cpu=hold_regs[32];
delay_ms(5);
}
if(rs_cpu==0)
{
reset_cpu();
}
int l2=0;
for( l2=0;l2<8;l2++)
{
write_eeprom(7+offset,alarmflag[l2]);
//delay_ms(5);
temEE=ax[l2]/256;
write_eeprom(8+offset,temEE);
//delay_ms(5);
temEE=ax[l2]%256;
write_eeprom(9+offset,temEE);
//delay_ms(5);
temEE=ay[l2]/256;
write_eeprom(10+offset,temEE);
//delay_ms(5);
temEE=ay[l2]%256;
write_eeprom(11+offset,temEE);
//delay_ms(5);
write_eeprom(16+offset,skipFlag[l2]);
//delay_ms(5); */
} |
its not getting written on EEPROM.
but when i do the same outside the function it does get written on the EEPROM |
|
|
|
|
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
|