Commit 1660f89490e1eed3f25fe0163d132a9380250dcd
1 parent
07ae7c91
Various changes
- declare some functions static - use uint8_t and uint16_t in various places to reduce memory use, the transition is not complete and will break compilation of some applications - add some new functions to get/set bits from one or many bytes: o set_bits_from_byte o set_bits_from_bytes o get_byte_from_bits - the server (slave) detects a connection closing
Showing
2 changed files
with
181 additions
and
111 deletions
modbus/modbus.c
| ... | ... | @@ -32,6 +32,7 @@ |
| 32 | 32 | #include <stdio.h> |
| 33 | 33 | #include <string.h> |
| 34 | 34 | #include <stdlib.h> |
| 35 | +#include <stdint.h> | |
| 35 | 36 | #include <termios.h> |
| 36 | 37 | #include <sys/time.h> |
| 37 | 38 | #include <unistd.h> |
| ... | ... | @@ -57,7 +58,7 @@ |
| 57 | 58 | |
| 58 | 59 | #define UNKNOWN_ERROR_MSG "Not defined in modbus specification" |
| 59 | 60 | |
| 60 | -static const int SIZE_TAB_ERROR_MSG = 12; | |
| 61 | +static const uint8_t NB_TAB_ERROR_MSG = 12; | |
| 61 | 62 | static const char *TAB_ERROR_MSG[] = { |
| 62 | 63 | /* 0x00 */ UNKNOWN_ERROR_MSG, |
| 63 | 64 | /* 0x01 */ "Illegal function code", |
| ... | ... | @@ -74,7 +75,7 @@ static const char *TAB_ERROR_MSG[] = { |
| 74 | 75 | }; |
| 75 | 76 | |
| 76 | 77 | /* Table of CRC values for high-order byte */ |
| 77 | -static unsigned char table_crc_hi[] = { | |
| 78 | +static uint8_t table_crc_hi[] = { | |
| 78 | 79 | 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, |
| 79 | 80 | 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, |
| 80 | 81 | 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, |
| ... | ... | @@ -104,7 +105,7 @@ static unsigned char table_crc_hi[] = { |
| 104 | 105 | }; |
| 105 | 106 | |
| 106 | 107 | /* Table of CRC values for low-order byte */ |
| 107 | -static unsigned char table_crc_lo[] = { | |
| 108 | +static uint8_t table_crc_lo[] = { | |
| 108 | 109 | 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, |
| 109 | 110 | 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, |
| 110 | 111 | 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, |
| ... | ... | @@ -135,8 +136,7 @@ static unsigned char table_crc_lo[] = { |
| 135 | 136 | |
| 136 | 137 | /* Local declaration */ |
| 137 | 138 | static int read_reg_response(modbus_param_t *mb_param, |
| 138 | - int *data_dest, | |
| 139 | - unsigned char *query); | |
| 139 | + uint16_t *data_dest, uint8_t *query); | |
| 140 | 140 | |
| 141 | 141 | /* Treats errors and flush or close connection if necessary */ |
| 142 | 142 | static void error_treat(int ret, const char *string, modbus_param_t *mb_param) |
| ... | ... | @@ -157,7 +157,7 @@ static void error_treat(int ret, const char *string, modbus_param_t *mb_param) |
| 157 | 157 | |
| 158 | 158 | /* Computes the size of the expected response */ |
| 159 | 159 | static unsigned int compute_response_size(modbus_param_t *mb_param, |
| 160 | - unsigned char *query) | |
| 160 | + uint8_t *query) | |
| 161 | 161 | { |
| 162 | 162 | int response_size_computed; |
| 163 | 163 | int offset; |
| ... | ... | @@ -171,7 +171,7 @@ static unsigned int compute_response_size(modbus_param_t *mb_param, |
| 171 | 171 | int coil_count = (query[offset + 4] << 8) | query[offset + 5]; |
| 172 | 172 | response_size_computed = 3 + |
| 173 | 173 | (coil_count / 8) + ((coil_count % 8) ? 1 : 0); |
| 174 | - } | |
| 174 | + } | |
| 175 | 175 | break; |
| 176 | 176 | case FC_READ_HOLDING_REGISTERS: |
| 177 | 177 | case FC_READ_INPUT_REGISTERS: |
| ... | ... | @@ -192,8 +192,9 @@ static unsigned int compute_response_size(modbus_param_t *mb_param, |
| 192 | 192 | } |
| 193 | 193 | |
| 194 | 194 | /* Buils a RTU header */ |
| 195 | -int build_query_packet_rtu(int slave, int function, int start_addr, | |
| 196 | - int count, unsigned char *packet) | |
| 195 | +static int build_query_packet_rtu(uint8_t slave, uint8_t function, | |
| 196 | + uint16_t start_addr, uint16_t count, | |
| 197 | + uint8_t *packet) | |
| 197 | 198 | { |
| 198 | 199 | packet[0] = slave; |
| 199 | 200 | packet[1] = function; |
| ... | ... | @@ -206,13 +207,14 @@ int build_query_packet_rtu(int slave, int function, int start_addr, |
| 206 | 207 | } |
| 207 | 208 | |
| 208 | 209 | /* Builds a TCP header */ |
| 209 | -int build_query_packet_tcp(int slave, int function, int start_addr, | |
| 210 | - int count, unsigned char *packet) | |
| 210 | +static int build_query_packet_tcp(uint8_t slave, uint8_t function, | |
| 211 | + uint16_t start_addr, uint16_t count, | |
| 212 | + uint8_t *packet) | |
| 211 | 213 | { |
| 212 | - static unsigned short t_id = 0; | |
| 214 | + static uint16_t t_id = 0; | |
| 213 | 215 | |
| 214 | 216 | /* Transaction ID */ |
| 215 | - if (t_id < USHRT_MAX) | |
| 217 | + if (t_id < UINT16_MAX) | |
| 216 | 218 | t_id++; |
| 217 | 219 | else |
| 218 | 220 | t_id = 0; |
| ... | ... | @@ -235,9 +237,9 @@ int build_query_packet_tcp(int slave, int function, int start_addr, |
| 235 | 237 | return PRESET_QUERY_SIZE_TCP; |
| 236 | 238 | } |
| 237 | 239 | |
| 238 | -int build_query_packet(modbus_param_t *mb_param, int slave, | |
| 239 | - int function, int start_addr, | |
| 240 | - int count, unsigned char *packet) | |
| 240 | +static int build_query_packet(modbus_param_t *mb_param, uint8_t slave, | |
| 241 | + uint8_t function, uint16_t start_addr, | |
| 242 | + uint16_t count, uint8_t *packet) | |
| 241 | 243 | { |
| 242 | 244 | if (mb_param->type_com == RTU) |
| 243 | 245 | return build_query_packet_rtu(slave, function, start_addr, |
| ... | ... | @@ -248,7 +250,8 @@ int build_query_packet(modbus_param_t *mb_param, int slave, |
| 248 | 250 | } |
| 249 | 251 | |
| 250 | 252 | |
| 251 | -int build_response_packet_rtu(int slave, int function, int byte_count, unsigned char *packet) | |
| 253 | +static int build_response_packet_rtu(uint8_t slave, uint8_t function, | |
| 254 | + uint8_t byte_count, uint8_t *packet) | |
| 252 | 255 | { |
| 253 | 256 | packet[0] = slave; |
| 254 | 257 | packet[1] = function; |
| ... | ... | @@ -258,9 +261,10 @@ int build_response_packet_rtu(int slave, int function, int byte_count, unsigned |
| 258 | 261 | return PRESET_RESPONSE_SIZE_RTU+1; |
| 259 | 262 | } |
| 260 | 263 | |
| 261 | -int build_response_packet_tcp(int slave, int function, int byte_count, unsigned char *packet) | |
| 264 | +static int build_response_packet_tcp(uint8_t slave, uint8_t function, | |
| 265 | + uint8_t byte_count, uint8_t *packet) | |
| 262 | 266 | { |
| 263 | - static unsigned short t_id = 0; | |
| 267 | + static uint16_t t_id = 0; | |
| 264 | 268 | |
| 265 | 269 | /* Transaction ID */ |
| 266 | 270 | if (t_id < USHRT_MAX) |
| ... | ... | @@ -285,8 +289,8 @@ int build_response_packet_tcp(int slave, int function, int byte_count, unsigned |
| 285 | 289 | return PRESET_RESPONSE_SIZE_TCP+1; |
| 286 | 290 | } |
| 287 | 291 | |
| 288 | -int build_response_packet(modbus_param_t *mb_param, int slave, | |
| 289 | - int function, int byte_count, unsigned char *packet) | |
| 292 | +static int build_response_packet(modbus_param_t *mb_param, uint8_t slave, | |
| 293 | + uint8_t function, uint8_t byte_count, uint8_t *packet) | |
| 290 | 294 | { |
| 291 | 295 | if (mb_param->type_com == RTU) |
| 292 | 296 | return build_response_packet_rtu(slave, function, byte_count, packet); |
| ... | ... | @@ -295,9 +299,9 @@ int build_response_packet(modbus_param_t *mb_param, int slave, |
| 295 | 299 | } |
| 296 | 300 | |
| 297 | 301 | /* Sets the length of TCP message in the message */ |
| 298 | -void set_packet_length_tcp(unsigned char *packet, size_t packet_size) | |
| 302 | +void set_packet_length_tcp(uint8_t *packet, size_t packet_size) | |
| 299 | 303 | { |
| 300 | - unsigned short mbap_length; | |
| 304 | + uint16_t mbap_length; | |
| 301 | 305 | |
| 302 | 306 | /* Substract MBAP header length */ |
| 303 | 307 | mbap_length = packet_size - 6; |
| ... | ... | @@ -307,11 +311,11 @@ void set_packet_length_tcp(unsigned char *packet, size_t packet_size) |
| 307 | 311 | } |
| 308 | 312 | |
| 309 | 313 | /* Fast CRC */ |
| 310 | -static unsigned short crc16(unsigned char *buffer, | |
| 311 | - unsigned short buffer_length) | |
| 314 | +static uint16_t crc16(uint8_t *buffer, | |
| 315 | + uint16_t buffer_length) | |
| 312 | 316 | { |
| 313 | - unsigned char crc_hi = 0xFF; /* high CRC byte initialized */ | |
| 314 | - unsigned char crc_lo = 0xFF; /* low CRC byte initialized */ | |
| 317 | + uint8_t crc_hi = 0xFF; /* high CRC byte initialized */ | |
| 318 | + uint8_t crc_lo = 0xFF; /* low CRC byte initialized */ | |
| 315 | 319 | unsigned int i; /* will index into CRC lookup */ |
| 316 | 320 | |
| 317 | 321 | /* pass through message buffer */ |
| ... | ... | @@ -326,14 +330,14 @@ static unsigned short crc16(unsigned char *buffer, |
| 326 | 330 | |
| 327 | 331 | /* If CRC is correct returns 0 else returns INVALID_CRC */ |
| 328 | 332 | int check_crc16(modbus_param_t *mb_param, |
| 329 | - unsigned char *msg, | |
| 333 | + uint8_t *msg, | |
| 330 | 334 | int msg_size) |
| 331 | 335 | { |
| 332 | 336 | int ret; |
| 333 | 337 | |
| 334 | 338 | if (mb_param->type_com == RTU) { |
| 335 | - unsigned short crc_calc; | |
| 336 | - unsigned short crc_received; | |
| 339 | + uint16_t crc_calc; | |
| 340 | + uint16_t crc_received; | |
| 337 | 341 | |
| 338 | 342 | crc_calc = crc16(msg, msg_size - 2); |
| 339 | 343 | crc_received = (msg[msg_size - 2] << 8) | msg[msg_size - 1]; |
| ... | ... | @@ -357,11 +361,11 @@ int check_crc16(modbus_param_t *mb_param, |
| 357 | 361 | } |
| 358 | 362 | |
| 359 | 363 | /* Sends a query/response over a serial or a TCP communication */ |
| 360 | -static int modbus_send(modbus_param_t *mb_param, unsigned char *query, | |
| 364 | +static int modbus_send(modbus_param_t *mb_param, uint8_t *query, | |
| 361 | 365 | size_t query_size) |
| 362 | 366 | { |
| 363 | 367 | int write_ret; |
| 364 | - unsigned short s_crc; | |
| 368 | + uint16_t s_crc; | |
| 365 | 369 | int i; |
| 366 | 370 | |
| 367 | 371 | if (mb_param->type_com == RTU) { |
| ... | ... | @@ -396,9 +400,9 @@ static int modbus_send(modbus_param_t *mb_param, unsigned char *query, |
| 396 | 400 | } |
| 397 | 401 | |
| 398 | 402 | /* Computes the size of the header following the function code */ |
| 399 | -int compute_query_size_header(int function) | |
| 403 | +static uint8_t compute_query_size_header(uint8_t function) | |
| 400 | 404 | { |
| 401 | - int byte; | |
| 405 | + uint8_t byte; | |
| 402 | 406 | |
| 403 | 407 | if (function <= FC_FORCE_SINGLE_COIL) |
| 404 | 408 | /* Read and single write */ |
| ... | ... | @@ -416,10 +420,10 @@ int compute_query_size_header(int function) |
| 416 | 420 | } |
| 417 | 421 | |
| 418 | 422 | /* Computes the size of the data to write in the query */ |
| 419 | -int compute_query_size_data(modbus_param_t *mb_param, unsigned char *msg) | |
| 423 | +static uint8_t compute_query_size_data(modbus_param_t *mb_param, uint8_t *msg) | |
| 420 | 424 | { |
| 421 | - int function = msg[mb_param->header_length + 1]; | |
| 422 | - int byte; | |
| 425 | + uint8_t function = msg[mb_param->header_length + 1]; | |
| 426 | + uint8_t byte; | |
| 423 | 427 | |
| 424 | 428 | if (function == FC_FORCE_MULTIPLE_COILS || |
| 425 | 429 | function == FC_PRESET_MULTIPLE_REGISTERS) |
| ... | ... | @@ -464,7 +468,7 @@ int compute_query_size_data(modbus_param_t *mb_param, unsigned char *msg) |
| 464 | 468 | - msg_size: number of characters received. */ |
| 465 | 469 | int receive_msg(modbus_param_t *mb_param, |
| 466 | 470 | int msg_size_computed, |
| 467 | - unsigned char *msg, | |
| 471 | + uint8_t *msg, | |
| 468 | 472 | int *msg_size) |
| 469 | 473 | { |
| 470 | 474 | int select_ret; |
| ... | ... | @@ -472,7 +476,7 @@ int receive_msg(modbus_param_t *mb_param, |
| 472 | 476 | fd_set rfds; |
| 473 | 477 | struct timeval tv; |
| 474 | 478 | int size_to_read; |
| 475 | - unsigned char *p_msg; | |
| 479 | + uint8_t *p_msg; | |
| 476 | 480 | enum { FUNCTION, BYTE, COMPLETE }; |
| 477 | 481 | int state; |
| 478 | 482 | |
| ... | ... | @@ -504,6 +508,8 @@ int receive_msg(modbus_param_t *mb_param, |
| 504 | 508 | } |
| 505 | 509 | |
| 506 | 510 | size_to_read = msg_size_computed; |
| 511 | + | |
| 512 | + select_ret = 0; | |
| 507 | 513 | WAIT_DATA(); |
| 508 | 514 | |
| 509 | 515 | /* Read the msg */ |
| ... | ... | @@ -519,6 +525,9 @@ int receive_msg(modbus_param_t *mb_param, |
| 519 | 525 | if (read_ret == -1) { |
| 520 | 526 | error_treat(read_ret, "Read port/socket failure", mb_param); |
| 521 | 527 | return PORT_SOCKET_FAILURE; |
| 528 | + } else if (read_ret == 0) { | |
| 529 | + printf("Connection closed\n"); | |
| 530 | + return CONNECTION_CLOSED; | |
| 522 | 531 | } |
| 523 | 532 | |
| 524 | 533 | /* Sums bytes received */ |
| ... | ... | @@ -593,8 +602,8 @@ int receive_msg(modbus_param_t *mb_param, |
| 593 | 602 | Note: All functions used to send or receive data with modbus return |
| 594 | 603 | these values. */ |
| 595 | 604 | static int modbus_check_response(modbus_param_t *mb_param, |
| 596 | - unsigned char *query, | |
| 597 | - unsigned char *response) | |
| 605 | + uint8_t *query, | |
| 606 | + uint8_t *response) | |
| 598 | 607 | { |
| 599 | 608 | int response_size; |
| 600 | 609 | int response_size_computed; int offset = mb_param->header_length; |
| ... | ... | @@ -648,7 +657,7 @@ static int modbus_check_response(modbus_param_t *mb_param, |
| 648 | 657 | 0x80 + function */ |
| 649 | 658 | if (0x80 + query[offset + 1] == response[offset + 1]) { |
| 650 | 659 | |
| 651 | - if (response[offset + 2] < SIZE_TAB_ERROR_MSG) { | |
| 660 | + if (response[offset + 2] < NB_TAB_ERROR_MSG) { | |
| 652 | 661 | error_treat(0, |
| 653 | 662 | TAB_ERROR_MSG[response[offset + 2]], |
| 654 | 663 | mb_param); |
| ... | ... | @@ -675,12 +684,12 @@ static int modbus_check_response(modbus_param_t *mb_param, |
| 675 | 684 | return response_size; |
| 676 | 685 | } |
| 677 | 686 | |
| 678 | -int response_io_status(int address, int count, | |
| 679 | - int nb_io_status, unsigned char *tab_io_status, | |
| 680 | - unsigned char *response, int offset) | |
| 687 | +static int response_io_status(uint8_t address, uint16_t count, | |
| 688 | + uint8_t *tab_io_status, | |
| 689 | + uint8_t *response, int offset) | |
| 681 | 690 | { |
| 682 | - unsigned char shift = 0; | |
| 683 | - unsigned char byte = 0; | |
| 691 | + uint8_t shift = 0; | |
| 692 | + uint8_t byte = 0; | |
| 684 | 693 | int i; |
| 685 | 694 | |
| 686 | 695 | for (i = address; i < address+count; i++) { |
| ... | ... | @@ -702,7 +711,7 @@ int response_io_status(int address, int count, |
| 702 | 711 | |
| 703 | 712 | /* Manages the received query. |
| 704 | 713 | Analyses the query and constructs a response */ |
| 705 | -void manage_query(modbus_param_t *mb_param, unsigned char *query, | |
| 714 | +void manage_query(modbus_param_t *mb_param, uint8_t *query, | |
| 706 | 715 | int query_size, modbus_mapping_t *mb_mapping) |
| 707 | 716 | { |
| 708 | 717 | int offset = mb_param->header_length; |
| ... | ... | @@ -712,7 +721,7 @@ void manage_query(modbus_param_t *mb_param, unsigned char *query, |
| 712 | 721 | /* FIXME count/data */ |
| 713 | 722 | int count; |
| 714 | 723 | int data; |
| 715 | - unsigned char response[MAX_PACKET_SIZE]; | |
| 724 | + uint8_t response[MAX_PACKET_SIZE]; | |
| 716 | 725 | int byte_count; |
| 717 | 726 | int i; |
| 718 | 727 | |
| ... | ... | @@ -723,16 +732,14 @@ void manage_query(modbus_param_t *mb_param, unsigned char *query, |
| 723 | 732 | count = (query[offset+4] << 8) + query[offset+5]; |
| 724 | 733 | byte_count = (count / 8.0) + ((count % 8) ? 1 : 0); |
| 725 | 734 | offset = build_response_packet(mb_param, slave, function, byte_count, response); |
| 726 | - offset = response_io_status(address, count, | |
| 727 | - mb_mapping->nb_coil_status, mb_mapping->tab_coil_status, | |
| 735 | + offset = response_io_status(address, count, mb_mapping->tab_coil_status, | |
| 728 | 736 | response, offset); |
| 729 | 737 | break; |
| 730 | 738 | case FC_READ_INPUT_STATUS: |
| 731 | 739 | count = (query[offset+4] << 8) + query[offset+5]; |
| 732 | 740 | byte_count = (count / 8.0) + ((count % 8) ? 1 : 0); |
| 733 | 741 | offset = build_response_packet(mb_param, slave, function, byte_count, response); |
| 734 | - offset = response_io_status(address, count, | |
| 735 | - mb_mapping->nb_input_status, mb_mapping->tab_input_status, | |
| 742 | + offset = response_io_status(address, count, mb_mapping->tab_input_status, | |
| 736 | 743 | response, offset); |
| 737 | 744 | break; |
| 738 | 745 | case FC_READ_HOLDING_REGISTERS: |
| ... | ... | @@ -784,7 +791,7 @@ void manage_query(modbus_param_t *mb_param, unsigned char *query, |
| 784 | 791 | - 0 if OK, or a negative error number if the request fails |
| 785 | 792 | - query, message received |
| 786 | 793 | - query_size, size in bytes of the message */ |
| 787 | -int modbus_listen(modbus_param_t *mb_param, unsigned char *query, int *query_size) | |
| 794 | +int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_size) | |
| 788 | 795 | { |
| 789 | 796 | int ret; |
| 790 | 797 | |
| ... | ... | @@ -798,14 +805,14 @@ int modbus_listen(modbus_param_t *mb_param, unsigned char *query, int *query_siz |
| 798 | 805 | |
| 799 | 806 | /* Reads IO status */ |
| 800 | 807 | static int read_io_status(modbus_param_t *mb_param, int slave, int function, |
| 801 | - int start_addr, int count, int *data_dest) | |
| 808 | + int start_addr, int count, uint8_t *data_dest) | |
| 802 | 809 | { |
| 803 | 810 | int query_size; |
| 804 | 811 | int query_ret; |
| 805 | 812 | int response_ret; |
| 806 | 813 | |
| 807 | - unsigned char query[MIN_QUERY_SIZE]; | |
| 808 | - unsigned char response[MAX_PACKET_SIZE]; | |
| 814 | + uint8_t query[MIN_QUERY_SIZE]; | |
| 815 | + uint8_t response[MAX_PACKET_SIZE]; | |
| 809 | 816 | |
| 810 | 817 | query_size = build_query_packet(mb_param, slave, function, |
| 811 | 818 | start_addr, count, query); |
| ... | ... | @@ -843,7 +850,7 @@ static int read_io_status(modbus_param_t *mb_param, int slave, int function, |
| 843 | 850 | /* Reads the boolean status of coils and sets the array elements |
| 844 | 851 | in the destination to TRUE or FALSE. */ |
| 845 | 852 | int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr, |
| 846 | - int count, int *data_dest) | |
| 853 | + const int count, uint8_t *data_dest) | |
| 847 | 854 | { |
| 848 | 855 | int status; |
| 849 | 856 | |
| ... | ... | @@ -859,7 +866,7 @@ int read_coil_status(modbus_param_t *mb_param, int slave, int start_addr, |
| 859 | 866 | |
| 860 | 867 | /* Same as read_coil_status but reads the slaves input table */ |
| 861 | 868 | int read_input_status(modbus_param_t *mb_param, int slave, int start_addr, |
| 862 | - int count, int *data_dest) | |
| 869 | + const int count, uint8_t *data_dest) | |
| 863 | 870 | { |
| 864 | 871 | int status; |
| 865 | 872 | |
| ... | ... | @@ -874,12 +881,12 @@ int read_input_status(modbus_param_t *mb_param, int slave, int start_addr, |
| 874 | 881 | |
| 875 | 882 | /* Reads the data from a modbus slave and put that data into an array */ |
| 876 | 883 | static int read_registers(modbus_param_t *mb_param, int slave, int function, |
| 877 | - int start_addr, int count, int *data_dest) | |
| 884 | + int start_addr, int count, uint16_t *data_dest) | |
| 878 | 885 | { |
| 879 | 886 | int query_size; |
| 880 | 887 | int status; |
| 881 | 888 | int query_ret; |
| 882 | - unsigned char query[MIN_QUERY_SIZE]; | |
| 889 | + uint8_t query[MIN_QUERY_SIZE]; | |
| 883 | 890 | |
| 884 | 891 | query_size = build_query_packet(mb_param, slave, function, |
| 885 | 892 | start_addr, count, query); |
| ... | ... | @@ -896,7 +903,7 @@ static int read_registers(modbus_param_t *mb_param, int slave, int function, |
| 896 | 903 | /* Reads the holding registers in a slave and put the data into an |
| 897 | 904 | array */ |
| 898 | 905 | int read_holding_registers(modbus_param_t *mb_param, int slave, |
| 899 | - int start_addr, int count, int *data_dest) | |
| 906 | + int start_addr, int count, uint16_t *data_dest) | |
| 900 | 907 | { |
| 901 | 908 | int status; |
| 902 | 909 | |
| ... | ... | @@ -913,7 +920,7 @@ int read_holding_registers(modbus_param_t *mb_param, int slave, |
| 913 | 920 | /* Reads the input registers in a slave and put the data into |
| 914 | 921 | an array */ |
| 915 | 922 | int read_input_registers(modbus_param_t *mb_param, int slave, |
| 916 | - int start_addr, int count, int *data_dest) | |
| 923 | + int start_addr, int count, uint16_t *data_dest) | |
| 917 | 924 | { |
| 918 | 925 | int status; |
| 919 | 926 | |
| ... | ... | @@ -930,10 +937,10 @@ int read_input_registers(modbus_param_t *mb_param, int slave, |
| 930 | 937 | |
| 931 | 938 | /* Reads the response data from a slave and puts the data into an |
| 932 | 939 | array */ |
| 933 | -static int read_reg_response(modbus_param_t *mb_param, int *data_dest, | |
| 934 | - unsigned char *query) | |
| 940 | +static int read_reg_response(modbus_param_t *mb_param, uint16_t *data_dest, | |
| 941 | + uint8_t *query) | |
| 935 | 942 | { |
| 936 | - unsigned char response[MAX_PACKET_SIZE]; | |
| 943 | + uint8_t response[MAX_PACKET_SIZE]; | |
| 937 | 944 | int response_ret; |
| 938 | 945 | int offset; |
| 939 | 946 | int i; |
| ... | ... | @@ -953,10 +960,10 @@ static int read_reg_response(modbus_param_t *mb_param, int *data_dest, |
| 953 | 960 | } |
| 954 | 961 | |
| 955 | 962 | /* Gets the raw data from the input stream */ |
| 956 | -static int preset_response(modbus_param_t *mb_param, unsigned char *query) | |
| 963 | +static int preset_response(modbus_param_t *mb_param, uint8_t *query) | |
| 957 | 964 | { |
| 958 | 965 | int ret; |
| 959 | - unsigned char response[MAX_PACKET_SIZE]; | |
| 966 | + uint8_t response[MAX_PACKET_SIZE]; | |
| 960 | 967 | |
| 961 | 968 | ret = modbus_check_response(mb_param, query, response); |
| 962 | 969 | |
| ... | ... | @@ -970,7 +977,7 @@ static int set_single(modbus_param_t *mb_param, int slave, int function, |
| 970 | 977 | int status; |
| 971 | 978 | int query_size; |
| 972 | 979 | int query_ret; |
| 973 | - unsigned char query[MAX_PACKET_SIZE]; | |
| 980 | + uint8_t query[MAX_PACKET_SIZE]; | |
| 974 | 981 | |
| 975 | 982 | query_size = build_query_packet(mb_param, slave, function, |
| 976 | 983 | addr, value, query); |
| ... | ... | @@ -1014,7 +1021,7 @@ int preset_single_register(modbus_param_t *mb_param, int slave, |
| 1014 | 1021 | appropriatly */ |
| 1015 | 1022 | int force_multiple_coils(modbus_param_t *mb_param, int slave, |
| 1016 | 1023 | int start_addr, int coil_count, |
| 1017 | - int *data_src) | |
| 1024 | + uint8_t *data_src) | |
| 1018 | 1025 | { |
| 1019 | 1026 | int i; |
| 1020 | 1027 | int byte_count; |
| ... | ... | @@ -1024,7 +1031,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave, |
| 1024 | 1031 | int query_ret; |
| 1025 | 1032 | int pos = 0; |
| 1026 | 1033 | |
| 1027 | - unsigned char query[MAX_PACKET_SIZE]; | |
| 1034 | + uint8_t query[MAX_PACKET_SIZE]; | |
| 1028 | 1035 | |
| 1029 | 1036 | if (coil_count > MAX_WRITE_COILS) { |
| 1030 | 1037 | printf("WARNING Writing to too many coils\n"); |
| ... | ... | @@ -1064,7 +1071,7 @@ int force_multiple_coils(modbus_param_t *mb_param, int slave, |
| 1064 | 1071 | |
| 1065 | 1072 | /* Copies the values in an array to an array on the slave */ |
| 1066 | 1073 | int preset_multiple_registers(modbus_param_t *mb_param, int slave, |
| 1067 | - int start_addr, int reg_count, int *data_src) | |
| 1074 | + int start_addr, int reg_count, uint16_t *data_src) | |
| 1068 | 1075 | { |
| 1069 | 1076 | int i; |
| 1070 | 1077 | int query_size; |
| ... | ... | @@ -1072,7 +1079,7 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave, |
| 1072 | 1079 | int status; |
| 1073 | 1080 | int query_ret; |
| 1074 | 1081 | |
| 1075 | - unsigned char query[MAX_PACKET_SIZE]; | |
| 1082 | + uint8_t query[MAX_PACKET_SIZE]; | |
| 1076 | 1083 | |
| 1077 | 1084 | if (reg_count > MAX_WRITE_REGS) { |
| 1078 | 1085 | printf("WARNING Trying to write to too many registers\n"); |
| ... | ... | @@ -1101,14 +1108,14 @@ int preset_multiple_registers(modbus_param_t *mb_param, int slave, |
| 1101 | 1108 | |
| 1102 | 1109 | /* Returns the slave id ! */ |
| 1103 | 1110 | int report_slave_id(modbus_param_t *mb_param, int slave, |
| 1104 | - unsigned char *data_dest) | |
| 1111 | + uint8_t *data_dest) | |
| 1105 | 1112 | { |
| 1106 | 1113 | int query_size; |
| 1107 | 1114 | int query_ret; |
| 1108 | 1115 | int response_ret; |
| 1109 | 1116 | |
| 1110 | - unsigned char query[MIN_QUERY_SIZE]; | |
| 1111 | - unsigned char response[MAX_PACKET_SIZE]; | |
| 1117 | + uint8_t query[MIN_QUERY_SIZE]; | |
| 1118 | + uint8_t response[MAX_PACKET_SIZE]; | |
| 1112 | 1119 | |
| 1113 | 1120 | query_size = build_query_packet(mb_param, slave, FC_REPORT_SLAVE_ID, |
| 1114 | 1121 | 0, 0, query); |
| ... | ... | @@ -1519,46 +1526,45 @@ int modbus_connect(modbus_param_t *mb_param) |
| 1519 | 1526 | holding registers. The pointers are stored in modbus_mapping structure. |
| 1520 | 1527 | |
| 1521 | 1528 | Returns: TRUE if ok, FALSE on failure |
| 1522 | - | |
| 1523 | 1529 | */ |
| 1524 | 1530 | int modbus_mapping_new(modbus_mapping_t *mb_mapping, |
| 1525 | 1531 | int nb_coil_status, int nb_input_status, |
| 1526 | - int nb_input_registers, int nb_holding_registers) | |
| 1532 | + int nb_holding_registers, int nb_input_registers) | |
| 1527 | 1533 | { |
| 1528 | 1534 | /* 0X */ |
| 1529 | 1535 | mb_mapping->nb_coil_status = nb_coil_status; |
| 1530 | - mb_mapping->tab_coil_status = (unsigned char *) malloc(nb_coil_status * sizeof(unsigned char)); | |
| 1531 | - memset(mb_mapping->tab_coil_status, 0, nb_coil_status * sizeof(unsigned char)); | |
| 1536 | + mb_mapping->tab_coil_status = (uint8_t *) malloc(nb_coil_status * sizeof(uint8_t)); | |
| 1537 | + memset(mb_mapping->tab_coil_status, 0, nb_coil_status * sizeof(uint8_t)); | |
| 1532 | 1538 | if (mb_mapping->tab_coil_status == NULL) |
| 1533 | 1539 | return FALSE; |
| 1534 | 1540 | |
| 1535 | 1541 | /* 1X */ |
| 1536 | 1542 | mb_mapping->nb_input_status = nb_input_status; |
| 1537 | - mb_mapping->tab_input_status = (unsigned char *) malloc(nb_input_status * sizeof(unsigned char)); | |
| 1538 | - memset(mb_mapping->tab_input_status, 0, nb_input_status * sizeof(unsigned char)); | |
| 1543 | + mb_mapping->tab_input_status = (uint8_t *) malloc(nb_input_status * sizeof(uint8_t)); | |
| 1544 | + memset(mb_mapping->tab_input_status, 0, nb_input_status * sizeof(uint8_t)); | |
| 1539 | 1545 | if (mb_mapping->tab_input_status == NULL) { |
| 1540 | 1546 | free(mb_mapping->tab_coil_status); |
| 1541 | 1547 | return FALSE; |
| 1542 | 1548 | } |
| 1543 | 1549 | |
| 1544 | - /* 3X */ | |
| 1545 | - mb_mapping->nb_input_registers = nb_input_registers; | |
| 1546 | - mb_mapping->tab_input_registers = (unsigned short *) malloc(nb_input_registers * sizeof(unsigned short)); | |
| 1547 | - memset(mb_mapping->tab_input_registers, 0, nb_input_registers * sizeof(unsigned short)); | |
| 1548 | - if (mb_mapping->tab_input_registers == NULL) { | |
| 1550 | + /* 4X */ | |
| 1551 | + mb_mapping->nb_holding_registers = nb_holding_registers; | |
| 1552 | + mb_mapping->tab_holding_registers = (uint16_t *) malloc(nb_holding_registers * sizeof(uint16_t)); | |
| 1553 | + memset(mb_mapping->tab_holding_registers, 0, nb_holding_registers * sizeof(uint16_t)); | |
| 1554 | + if (mb_mapping->tab_holding_registers == NULL) { | |
| 1549 | 1555 | free(mb_mapping->tab_coil_status); |
| 1550 | 1556 | free(mb_mapping->tab_input_status); |
| 1551 | 1557 | return FALSE; |
| 1552 | 1558 | } |
| 1553 | 1559 | |
| 1554 | - /* 4X */ | |
| 1555 | - mb_mapping->nb_holding_registers = nb_holding_registers; | |
| 1556 | - mb_mapping->tab_holding_registers = (unsigned short *) malloc(nb_holding_registers * sizeof(unsigned short)); | |
| 1557 | - memset(mb_mapping->tab_holding_registers, 0, nb_holding_registers * sizeof(unsigned short)); | |
| 1558 | - if (mb_mapping->tab_holding_registers == NULL) { | |
| 1560 | + /* 3X */ | |
| 1561 | + mb_mapping->nb_input_registers = nb_input_registers; | |
| 1562 | + mb_mapping->tab_input_registers = (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t)); | |
| 1563 | + memset(mb_mapping->tab_input_registers, 0, nb_input_registers * sizeof(uint16_t)); | |
| 1564 | + if (mb_mapping->tab_input_registers == NULL) { | |
| 1559 | 1565 | free(mb_mapping->tab_coil_status); |
| 1560 | 1566 | free(mb_mapping->tab_input_status); |
| 1561 | - free(mb_mapping->tab_input_registers); | |
| 1567 | + free(mb_mapping->tab_holding_registers); | |
| 1562 | 1568 | return FALSE; |
| 1563 | 1569 | } |
| 1564 | 1570 | |
| ... | ... | @@ -1570,11 +1576,11 @@ void modbus_mapping_free(modbus_mapping_t *mb_mapping) |
| 1570 | 1576 | { |
| 1571 | 1577 | free(mb_mapping->tab_coil_status); |
| 1572 | 1578 | free(mb_mapping->tab_input_status); |
| 1573 | - free(mb_mapping->tab_input_registers); | |
| 1574 | 1579 | free(mb_mapping->tab_holding_registers); |
| 1580 | + free(mb_mapping->tab_input_registers); | |
| 1575 | 1581 | } |
| 1576 | 1582 | |
| 1577 | -/* Listens for any query from a modbus master */ | |
| 1583 | +/* Listens for any query from a modbus master in TCP */ | |
| 1578 | 1584 | int modbus_init_listen_tcp(modbus_param_t *mb_param) |
| 1579 | 1585 | { |
| 1580 | 1586 | int ret; |
| ... | ... | @@ -1660,3 +1666,51 @@ void modbus_set_debug(modbus_param_t *mb_param, int boolean) |
| 1660 | 1666 | { |
| 1661 | 1667 | mb_param->debug = boolean; |
| 1662 | 1668 | } |
| 1669 | + | |
| 1670 | +/** Utils **/ | |
| 1671 | + | |
| 1672 | +/* Set many inputs/coils form a single byte value (all 8 bits of the | |
| 1673 | + byte value are setted) */ | |
| 1674 | +void set_bits_from_byte(uint8_t *dest, uint16_t address, const uint8_t value) | |
| 1675 | +{ | |
| 1676 | + int i; | |
| 1677 | + | |
| 1678 | + for (i=0; i<8; i++) { | |
| 1679 | + dest[address+i] = (value & (1 << i)) ? ON : OFF; | |
| 1680 | + } | |
| 1681 | +} | |
| 1682 | + | |
| 1683 | +/* Set many inputs/coils from a table of bytes (only the bits between | |
| 1684 | + address and address + nb_bits are setted) */ | |
| 1685 | +void set_bits_from_bytes(uint8_t *dest, uint16_t address, uint16_t nb_bits, const uint8_t tab_byte[]) | |
| 1686 | +{ | |
| 1687 | + int i; | |
| 1688 | + int shift = 0; | |
| 1689 | + | |
| 1690 | + for (i=address; i < address + nb_bits; i++) { | |
| 1691 | + dest[i] = tab_byte[(i - address) / 8] & (1 << shift) ? ON : OFF; | |
| 1692 | + /* gcc doesn't like: shift = (++shift) % 8; */ | |
| 1693 | + shift++; | |
| 1694 | + shift %= 8; | |
| 1695 | + } | |
| 1696 | +} | |
| 1697 | + | |
| 1698 | +/* Get the byte value from many inputs/coils. | |
| 1699 | + To obtain a full byte, set nb_bits to 8. */ | |
| 1700 | +uint8_t get_byte_from_bits(const uint8_t *src, uint16_t address, int nb_bits) | |
| 1701 | +{ | |
| 1702 | + int i; | |
| 1703 | + uint8_t value = 0; | |
| 1704 | + | |
| 1705 | + if (nb_bits > 8) { | |
| 1706 | + printf("Error: nb_bits is too big\n"); | |
| 1707 | + nb_bits = 8; | |
| 1708 | + } | |
| 1709 | + | |
| 1710 | + for (i=0; i<nb_bits; i++) { | |
| 1711 | + value |= (src[address+i] << i); | |
| 1712 | + } | |
| 1713 | + | |
| 1714 | + return value; | |
| 1715 | +} | |
| 1716 | + | ... | ... |
modbus/modbus.h
| ... | ... | @@ -20,6 +20,7 @@ |
| 20 | 20 | #ifndef _MODBUS_H_ |
| 21 | 21 | #define _MODBUS_H_ |
| 22 | 22 | |
| 23 | +#include <stdint.h> | |
| 23 | 24 | #include <termios.h> |
| 24 | 25 | #include <arpa/inet.h> |
| 25 | 26 | |
| ... | ... | @@ -103,6 +104,7 @@ |
| 103 | 104 | #define TOO_MANY_DATAS -0x0F |
| 104 | 105 | #define INVALID_CRC -0x10 |
| 105 | 106 | #define INVALID_EXCEPTION_CODE -0x11 |
| 107 | +#define CONNECTION_CLOSED -0x12 | |
| 106 | 108 | |
| 107 | 109 | /* Internal using */ |
| 108 | 110 | #define MSG_SIZE_UNDEFINED -1 |
| ... | ... | @@ -158,10 +160,10 @@ typedef struct { |
| 158 | 160 | int nb_input_status; |
| 159 | 161 | int nb_input_registers; |
| 160 | 162 | int nb_holding_registers; |
| 161 | - unsigned char *tab_coil_status; | |
| 162 | - unsigned char *tab_input_status; | |
| 163 | - unsigned short *tab_input_registers; | |
| 164 | - unsigned short *tab_holding_registers; | |
| 163 | + uint8_t *tab_coil_status; | |
| 164 | + uint8_t *tab_input_status; | |
| 165 | + uint16_t *tab_input_registers; | |
| 166 | + uint16_t *tab_holding_registers; | |
| 165 | 167 | } modbus_mapping_t; |
| 166 | 168 | |
| 167 | 169 | /* All functions used for sending or receiving data return : |
| ... | ... | @@ -172,22 +174,21 @@ typedef struct { |
| 172 | 174 | /* Reads the boolean status of coils and sets the array elements in |
| 173 | 175 | the destination to TRUE or FALSE */ |
| 174 | 176 | int read_coil_status(modbus_param_t *mb_param, int slave, |
| 175 | - int start_addr, int count, int *dest); | |
| 177 | + int start_addr, int count, uint8_t *dest); | |
| 176 | 178 | |
| 177 | 179 | /* Same as read_coil_status but reads the slaves input table */ |
| 178 | 180 | int read_input_status(modbus_param_t *mb_param, int slave, |
| 179 | - int start_addr, int count, int *dest); | |
| 181 | + int start_addr, int count, uint8_t *dest); | |
| 180 | 182 | |
| 181 | 183 | /* Reads the holding registers in a slave and put the data into an |
| 182 | 184 | array */ |
| 183 | 185 | int read_holding_registers(modbus_param_t *mb_param, int slave, |
| 184 | - int start_addr, int count, int *dest); | |
| 185 | - | |
| 186 | + int start_addr, int count, uint16_t *dest); | |
| 186 | 187 | |
| 187 | 188 | /* Reads the input registers in a slave and put the data into an |
| 188 | 189 | array */ |
| 189 | 190 | int read_input_registers(modbus_param_t *mb_param, int slave, |
| 190 | - int start_addr, int count, int *dest); | |
| 191 | + int start_addr, int count, uint16_t *dest); | |
| 191 | 192 | |
| 192 | 193 | /* Turns on or off a single coil on the slave device */ |
| 193 | 194 | int force_single_coil(modbus_param_t *mb_param, int slave, |
| ... | ... | @@ -200,15 +201,14 @@ int preset_single_register(modbus_param_t *mb_param, int slave, |
| 200 | 201 | /* Takes an array of ints and sets or resets the coils on a slave |
| 201 | 202 | appropriatly */ |
| 202 | 203 | int force_multiple_coils(modbus_param_t *mb_param, int slave, |
| 203 | - int start_addr, int coil_count, int *data); | |
| 204 | + int start_addr, int coil_count, uint8_t *data); | |
| 204 | 205 | |
| 205 | 206 | /* Copy the values in an array to an array on the slave */ |
| 206 | 207 | int preset_multiple_registers(modbus_param_t *mb_param, int slave, |
| 207 | - int start_addr, int reg_count, int *data); | |
| 208 | + int start_addr, int reg_count, uint16_t *data); | |
| 208 | 209 | |
| 209 | 210 | /* Returns some useful information about the modbus controller */ |
| 210 | -int report_slave_id(modbus_param_t *mb_param, int slave, | |
| 211 | - unsigned char *dest); | |
| 211 | +int report_slave_id(modbus_param_t *mb_param, int slave, uint8_t *dest); | |
| 212 | 212 | |
| 213 | 213 | /* Initialises a parameters structure |
| 214 | 214 | - device : "/dev/ttyS0" |
| ... | ... | @@ -259,18 +259,34 @@ void modbus_set_debug(modbus_param_t *mb_param, int boolean); |
| 259 | 259 | /* Slave/client functions */ |
| 260 | 260 | int modbus_mapping_new(modbus_mapping_t *mb_mapping, |
| 261 | 261 | int nb_coil_status, int nb_input_status, |
| 262 | - int nb_input_registers, int nb_holding_registers); | |
| 262 | + int nb_holding_registers, int nb_input_registers); | |
| 263 | 263 | void modbus_mapping_free(modbus_mapping_t *mb_mapping); |
| 264 | 264 | |
| 265 | 265 | int modbus_init_listen_tcp(modbus_param_t *mb_param); |
| 266 | 266 | |
| 267 | -int modbus_listen(modbus_param_t *mb_param, unsigned char *query, int *query_size); | |
| 267 | +int modbus_listen(modbus_param_t *mb_param, uint8_t *query, int *query_size); | |
| 268 | 268 | |
| 269 | -void manage_query(modbus_param_t *mb_param, unsigned char *query, | |
| 269 | +void manage_query(modbus_param_t *mb_param, uint8_t *query, | |
| 270 | 270 | int query_size, modbus_mapping_t *mb_mapping); |
| 271 | 271 | |
| 272 | 272 | /* Not implemented : |
| 273 | 273 | - read_exception_status() |
| 274 | 274 | */ |
| 275 | 275 | |
| 276 | +/** Utils **/ | |
| 277 | + | |
| 278 | +/* Set many inputs/coils form a single byte value (all 8 bits of the | |
| 279 | + byte value are setted) */ | |
| 280 | +void set_bits_from_byte(uint8_t *dest, uint16_t address, | |
| 281 | + const uint8_t value); | |
| 282 | + | |
| 283 | +/* Set many inputs/coils from a table of bytes (only the bits between | |
| 284 | + address and address + nb_bits are setted) */ | |
| 285 | +void set_bits_from_bytes(uint8_t *dest, uint16_t address, uint16_t nb_bits, | |
| 286 | + const uint8_t *tab_byte); | |
| 287 | + | |
| 288 | +/* Get the byte value from many inputs/coils. | |
| 289 | + To obtain a full byte, set nb_bits to 8. */ | |
| 290 | +uint8_t get_byte_from_bits(const uint8_t *src, uint16_t address, int nb_bits); | |
| 291 | + | |
| 276 | 292 | #endif /* _MODBUS_H_ */ | ... | ... |