#include #include "control_station.h" #include "modbus_table_v2.h" #include "options_table.h" #include "RS_modbus_pult.h" #include "DSP281x_Device.h" #include "CRC_Functions.h" #include "RS_Functions.h" #include "RS_modbus_svu.h" #pragma DATA_SECTION(p_analog_data_in, ".logs"); MODBUS_REG_STRUCT *p_analog_data_in; #pragma DATA_SECTION(p_analog_data_out, ".logs"); MODBUS_REG_STRUCT *p_analog_data_out; #pragma DATA_SECTION(p_discrete_data_out, ".logs"); MODBUS_REG_STRUCT *p_discrete_data_out; #pragma DATA_SECTION(p_discrete_data_in, ".logs"); MODBUS_REG_STRUCT *p_discrete_data_in; static int adres_wait_answer_cmd1 = 0; static int count_registers_wait_answer = 0; void ModbusRTUsetDataArrays(MODBUS_REG_STRUCT *array_in, MODBUS_REG_STRUCT *array_out) { p_analog_data_in = array_in; p_analog_data_out = array_out; } void ModbusRTUsetDiscretDataArray(MODBUS_REG_STRUCT *discrete_in, MODBUS_REG_STRUCT *discrete_out) { p_discrete_data_in = discrete_in; p_discrete_data_out = discrete_out; } /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************/ /***************************************************************/ /* Отправка запроса данных по протоколу ModBus - команда 1 Чтение Ячеек данных Digital Output Holding Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUsend1(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start, unsigned int count_bits) { // КонтрольнаЯ сумма unsigned int crc; unsigned int count_data_bytes; count_data_bytes = (count_bits % 8) == 0 ? count_bits / 8 : count_bits / 8 + 1; rs_arr->buffer[0] = LOBYTE(adr_contr); rs_arr->buffer[1] = CMD_RS232_MODBUS_1; rs_arr->buffer[2] = HIBYTE(adr_start); rs_arr->buffer[3] = LOBYTE(adr_start); rs_arr->buffer[4] = HIBYTE(count_bits); rs_arr->buffer[5] = LOBYTE(count_bits); crc = 0xffff; crc = GetCRC16_IBM(crc, rs_arr->buffer, 6); rs_arr->buffer[6] = LOBYTE(crc); rs_arr->buffer[7] = HIBYTE(crc); rs_arr->buffer[8] = 0; rs_arr->buffer[9] = 0; rs_arr->RS_DataWillSend = 1; RS_Send(rs_arr, rs_arr->buffer, 10); /* ждем ответа */ if (adr_contr > 0 && adr_contr < 0xff) { RS_Len[CMD_RS232_MODBUS_1] = 5 + count_data_bytes; count_registers_wait_answer = count_bits; adres_wait_answer_cmd1 = adr_start; RS_SetControllerLeading(rs_arr, true); RS_SetAdrAnswerController(rs_arr, adr_contr); } return; } /***************************************************************/ /***************************************************************/ /* Ответ с данными по протоколу ModBus - команда 1 Чтение Ячеек данных Digital Output Holding Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUreceiveAnswer1(RS_DATA_STRUCT *RS232_Arr) { unsigned int first_word, end_byte_number, count_data_bytes, current_register, last_register; unsigned int displacement_start, displacement, displacement_end, bits_in_last_byte, byte, mask = 0, mask_start, mask_end; unsigned int i = 0, b = 0, buffer_position = 0, j = 0; // unsigned char byte_buffer[SIZE_MODBUS_TABLE_DISCRET * 2]; /* получили начальный адрес чтениЯ. */ first_word = (adres_wait_answer_cmd1 % 16 == 0) && (adres_wait_answer_cmd1 != 0) ? adres_wait_answer_cmd1 / 16 + 1 : adres_wait_answer_cmd1 / 16; displacement_start = adres_wait_answer_cmd1 % 16; displacement = adres_wait_answer_cmd1 % 16; count_data_bytes = RS232_Arr->RS_Header[2]; current_register = adres_wait_answer_cmd1; last_register = adres_wait_answer_cmd1 + count_registers_wait_answer; displacement_end = last_register % 16; ///////////////////////////////////////////////// mask = 0; mask_start = 0; mask_end = 0; for (i = 0; i < displacement_start; ++i) { mask_start |= 1 << i; mask_end |= 1 << i; } mask_start = ~mask_start; displacement = displacement_start; for (i = 0; i < count_data_bytes; ++i) { byte = RS232_Arr->RS_Header[3 + i]; mask = 0; if ((last_register - current_register) > 8) { mask = 0xFF; } else { for (j = 0; j < (last_register - current_register); ++j) { mask |= 1 << j; } } if (displacement < 8) { //mask = mask << displacement; p_discrete_data_out[first_word].all &= ~(mask << displacement); p_discrete_data_out[first_word].all |= (byte & mask) << displacement; } else { mask_start = (mask << displacement) & 0xFF00; p_discrete_data_out[first_word].all &= ~mask_start; p_discrete_data_out[first_word].all |= (byte & mask) << displacement; mask_end = (mask >> (16 - displacement)) & 0xFF; p_discrete_data_out[first_word].all &= ~mask_end; p_discrete_data_out[first_word + 1].all |= (byte & mask) >> (16 - displacement); } displacement += 8; if (displacement >= 16) { displacement -= 16; first_word += 1; } current_register += 8; } RS_SetControllerLeading(RS232_Arr, false); RS_SetAdrAnswerController(RS232_Arr, 0); return; } /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************/ /***************************************************************/ /* Запрос данных от мастера по протоколу ModBus - команда 3 Чтение Ячеек данных Analog Input Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUreceive3(RS_DATA_STRUCT *RS232_Arr) { // Контрольнаy сумма unsigned int crc, Address_MB, Length_MB, i /*, Data*/; // int buf_out[200]; /* получили начальный адрес чтениy. */ Address_MB = (RS232_Arr->RS_Header[2] << 8) | RS232_Arr->RS_Header[3]; /* получили количество слов данных */ Length_MB = (RS232_Arr->RS_Header[4] << 8) | RS232_Arr->RS_Header[5]; ///////////////////////////////////////////////// // Отсылка /* Посчитали контрольную сумму перед самой посылкой */ // f.RScount = SECOND*3; RS232_Arr->buffer[0] = RS232_Arr->addr_recive; //CNTRL_ADDR; RS232_Arr->buffer[1] = CMD_RS232_MODBUS_3; RS232_Arr->buffer[2] = Length_MB * 2; for (i = 0; i < Length_MB; i++) { if (Address_MB >= ADR_MODBUS_TABLE && Address_MB < 0xe00) { // RS232_Arr->buffer[3 + i * 2] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.HB; // RS232_Arr->buffer[3 + i * 2 + 1] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.LB; RS232_Arr->buffer[3 + i * 2] = p_analog_data_out[Address_MB + i].byte.HB; RS232_Arr->buffer[3 + i * 2 + 1] = p_analog_data_out[Address_MB + i].byte.LB; } if (Address_MB >= 0xe00 && Address_MB < 0xf00) { RS232_Arr->buffer[3 + i * 2] = options_controller[Address_MB - 0xe00 + i].byte.HB; RS232_Arr->buffer[3 + i * 2 + 1] = options_controller[Address_MB - 0xe00 + i].byte.LB; } } crc = 0xffff; crc = GetCRC16_IBM(crc, RS232_Arr->buffer, Length_MB * 2 + 3); RS232_Arr->buffer[Length_MB * 2 + 3] = LOBYTE(crc); RS232_Arr->buffer[Length_MB * 2 + 4] = HIBYTE(crc); RS232_Arr->buffer[Length_MB * 2 + 5] = 0; RS232_Arr->buffer[Length_MB * 2 + 6] = 0; // RS232_Arr->RS_DataWillSend = 1; RS_Send(RS232_Arr, RS232_Arr->buffer, Length_MB * 2 + 7); return; } /***************************************************************/ /***************************************************************/ /* Отправка запроса данных по протоколу ModBus - команда 3 Чтение Ячеек данных Analog Input Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUsend3(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start, unsigned int count_word) { // КонтрольнаЯ сумма unsigned int crc; //, Address_MB, Length_MB, i, Data; // int buf_out[200]; // int buf_in[200]; rs_arr->buffer[0] = LOBYTE(adr_contr); rs_arr->buffer[1] = CMD_RS232_MODBUS_3; rs_arr->buffer[2] = HIBYTE(adr_start); rs_arr->buffer[3] = LOBYTE(adr_start); rs_arr->buffer[4] = 0; rs_arr->buffer[5] = LOBYTE(count_word); crc = 0xffff; crc = GetCRC16_IBM(crc, rs_arr->buffer, 6); rs_arr->buffer[6] = LOBYTE(crc); rs_arr->buffer[7] = HIBYTE(crc); rs_arr->buffer[8] = 0; rs_arr->buffer[9] = 0; rs_arr->RS_DataWillSend = 1; RS_Send(rs_arr, rs_arr->buffer, 10); /* ждем ответа */ if (adr_contr > 0 && adr_contr < 0xff) { RS_Len[CMD_RS232_MODBUS_3] = 5 + count_word * 2; adr_read_from_modbus3 = adr_start; RS_SetControllerLeading(rs_arr, true); RS_SetAdrAnswerController(rs_arr, adr_contr); } return; } /***************************************************************/ /***************************************************************/ /* Ответ с данными по протоколу ModBus - команда 3 Чтение Ячеек данных Analog Input Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUreceiveAnswer3(RS_DATA_STRUCT *RS232_Arr) { unsigned int Address_MB, Length_MB, i; MODBUS_REG_STRUCT elementData; /* получили начальный адрес чтениЯ. */ Address_MB = adr_read_from_modbus3; /* получили количество слов данных */ Length_MB = RS232_Arr->RS_Header[2] >> 1; ///////////////////////////////////////////////// // Отсылка /* Посчитали контрольную сумму перед самой посылкой */ for (i = 0; i < Length_MB; i++) { elementData.byte.HB = RS232_Arr->RS_Header[3 + i * 2]; elementData.byte.LB = RS232_Arr->RS_Header[3 + i * 2 + 1]; // p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].all = elementData.all; if ((Address_MB + i)buffer[0] = LOBYTE(adr_contr); rs_arr->buffer[1] = CMD_RS232_MODBUS_4; rs_arr->buffer[2] = HIBYTE(adr_start); rs_arr->buffer[3] = LOBYTE(adr_start); rs_arr->buffer[4] = 0; rs_arr->buffer[5] = LOBYTE(count_word); crc = 0xffff; crc = GetCRC16_IBM(crc, rs_arr->buffer, 6); rs_arr->buffer[6] = LOBYTE(crc); rs_arr->buffer[7] = HIBYTE(crc); rs_arr->buffer[8] = 0; rs_arr->buffer[9] = 0; rs_arr->RS_DataWillSend = 1; RS_Send(rs_arr, rs_arr->buffer, 10); /* ждем ответа */ if (adr_contr > 0 && adr_contr < 0xff) { RS_Len[CMD_RS232_MODBUS_4] = 5 + count_word * 2; adr_read_from_modbus3 = adr_start; RS_SetControllerLeading(rs_arr, true); RS_SetAdrAnswerController(rs_arr, adr_contr); } return; } /***************************************************************/ /***************************************************************/ /* Ответ с данными по протоколу ModBus - команда 4 Чтение Ячеек данных Analog Output Holding Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUreceiveAnswer4(RS_DATA_STRUCT *RS232_Arr) { unsigned int Address_MB, Length_MB, i; static unsigned int prev_Address_MB = 0; MODBUS_REG_STRUCT elementData; /* получили начальный адрес чтениЯ. */ Address_MB = adr_read_from_modbus3; /* получили количество слов данных */ Length_MB = RS232_Arr->RS_Header[2] >> 1; ///////////////////////////////////////////////// // Отсылка /* Посчитали контрольную сумму перед самой посылкой */ for (i = 0; i < Length_MB; i++) { elementData.byte.HB = RS232_Arr->RS_Header[3 + i * 2]; elementData.byte.LB = RS232_Arr->RS_Header[3 + i * 2 + 1]; // p_analog_data_in[Address_MB - ADR_MODBUS_TABLE + i].all = elementData.all; if ((Address_MB + i)RS_DataReadyFullUpdate = 1; prev_Address_MB = Address_MB; return; } /***************************************************************/ /***************************************************************/ /* Запрос данных от мастера по протоколу ModBus - команда 4 Чтение Ячеек данных Analog Output Holding Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUreceive4(RS_DATA_STRUCT *RS232_Arr) { // Контрольнаy сумма unsigned int crc, Address_MB, Length_MB, i /*, Data*/; // int buf_out[200]; /* получили начальный адрес чтениy. */ Address_MB = (RS232_Arr->RS_Header[2] << 8) | RS232_Arr->RS_Header[3]; /* получили количество слов данных */ Length_MB = (RS232_Arr->RS_Header[4] << 8) | RS232_Arr->RS_Header[5]; ///////////////////////////////////////////////// // Отсылка /* Посчитали контрольную сумму перед самой посылкой */ // f.RScount = SECOND*3; RS232_Arr->buffer[0] = RS232_Arr->addr_recive; //CNTRL_ADDR; RS232_Arr->buffer[1] = CMD_RS232_MODBUS_4; RS232_Arr->buffer[2] = Length_MB * 2; for (i = 0; i < Length_MB; i++) { if (Address_MB >= ADR_MODBUS_TABLE && Address_MB < 0xe00) { // RS232_Arr->buffer[3 + i * 2] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.HB; // RS232_Arr->buffer[3 + i * 2 + 1] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.LB; RS232_Arr->buffer[3 + i * 2] = p_analog_data_out[Address_MB + i].byte.HB; RS232_Arr->buffer[3 + i * 2 + 1] = p_analog_data_out[Address_MB + i].byte.LB; } if (Address_MB >= 0xe00 && Address_MB < 0xf00) { RS232_Arr->buffer[3 + i * 2] = options_controller[Address_MB - 0xe00 + i].byte.HB; RS232_Arr->buffer[3 + i * 2 + 1] = options_controller[Address_MB - 0xe00 + i].byte.LB; } } crc = 0xffff; crc = GetCRC16_IBM(crc, RS232_Arr->buffer, Length_MB * 2 + 3); RS232_Arr->buffer[Length_MB * 2 + 3] = LOBYTE(crc); RS232_Arr->buffer[Length_MB * 2 + 4] = HIBYTE(crc); RS232_Arr->buffer[Length_MB * 2 + 5] = 0; RS232_Arr->buffer[Length_MB * 2 + 6] = 0; // RS232_Arr->RS_DataWillSend = 1; RS_Send(RS232_Arr, RS232_Arr->buffer, Length_MB * 2 + 7); return; } /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************/ /***************************************************************/ /* Отправка запроса данных по протоколу ModBus - команда 5 Чтение Ячеек данных Analog Output Holding Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUsend5(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start) { // КонтрольнаЯ сумма unsigned int crc; unsigned int byte_number; unsigned int bit_number; byte_number = adr_start / 16; bit_number = adr_start % 16; rs_arr->buffer[0] = LOBYTE(adr_contr); rs_arr->buffer[1] = CMD_RS232_MODBUS_5; rs_arr->buffer[2] = HIBYTE(adr_start); rs_arr->buffer[3] = LOBYTE(adr_start); if ((p_discrete_data_out[byte_number].all >> bit_number) & 1) { rs_arr->buffer[4] = 0xFF; rs_arr->buffer[5] = 0; } else { rs_arr->buffer[4] = 0; rs_arr->buffer[5] = 0; } crc = 0xffff; crc = GetCRC16_IBM(crc, rs_arr->buffer, 6); rs_arr->buffer[6] = LOBYTE(crc); rs_arr->buffer[7] = HIBYTE(crc); rs_arr->buffer[8] = 0; rs_arr->buffer[9] = 0; rs_arr->RS_DataWillSend = 1; RS_Send(rs_arr, rs_arr->buffer, 10); /* ждем ответа */ if (adr_contr > 0 && adr_contr < 0xff) { RS_Len[CMD_RS232_MODBUS_5] = 8; adr_read_from_modbus3 = adr_start; RS_SetControllerLeading(rs_arr, true); RS_SetAdrAnswerController(rs_arr, adr_contr); } return; } /****************************************************************/ /****************************************************************/ /* Ответ с данными по протоколу ModBus - команда 5 Запись Ячееки данных Digital Output Holding Registers */ /****************************************************************/ /****************************************************************/ void ModbusRTUreceiveAnswer5(RS_DATA_STRUCT *RS232_Arr) { unsigned int Address_MB, Length_MB, i; MODBUS_REG_STRUCT elementData; /* получили начальный адрес чтениЯ. */ Address_MB = adr_read_from_modbus3; /* получили количество слов данных */ Length_MB = RS232_Arr->RS_Header[2] >> 1; RS_SetControllerLeading(RS232_Arr, false); RS_SetAdrAnswerController(RS232_Arr, 0); return; } /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************/ /***************************************************************/ /* Отправка запроса данных по протоколу ModBus - команда 6 запись Ячееки данных Analog Output Holding Registers */ /***************************************************************/ /***************************************************************/ void ModbusRTUsend6(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start) { // КонтрольнаЯ сумма unsigned int crc; //, Address_MB, Length_MB, i, Data; // int buf_out[200]; // int buf_in[200]; rs_arr->buffer[0] = LOBYTE(adr_contr); rs_arr->buffer[1] = CMD_RS232_MODBUS_6; rs_arr->buffer[2] = HIBYTE(adr_start); rs_arr->buffer[3] = LOBYTE(adr_start); rs_arr->buffer[4] = HIBYTE(p_analog_data_out[adr_start].all); rs_arr->buffer[5] = LOBYTE(p_analog_data_out[adr_start].all); crc = 0xffff; crc = GetCRC16_IBM(crc, rs_arr->buffer, 6); rs_arr->buffer[6] = LOBYTE(crc); rs_arr->buffer[7] = HIBYTE(crc); rs_arr->buffer[8] = 0; rs_arr->buffer[9] = 0; rs_arr->RS_DataWillSend = 1; RS_Send(rs_arr, rs_arr->buffer, 10); // control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] = 1; /* ждем ответа */ if (adr_contr > 0 && adr_contr < 0xff) { RS_Len[CMD_RS232_MODBUS_6] = 8; adr_read_from_modbus3 = adr_start; RS_SetControllerLeading(rs_arr, true); RS_SetAdrAnswerController(rs_arr, adr_contr); } return; } /****************************************************************/ /****************************************************************/ /* Ответ с данными по протоколу ModBus - команда 6 Чтение Ячеек данных Analog Output Holding Registers */ /****************************************************************/ /****************************************************************/ void ModbusRTUreceiveAnswer6(RS_DATA_STRUCT *RS232_Arr) { unsigned int Address_MB, Length_MB, i; MODBUS_REG_STRUCT elementData; /* получили начальный адрес чтениЯ. */ Address_MB = adr_read_from_modbus3; /* получили количество слов данных */ Length_MB = RS232_Arr->RS_Header[2] >> 1; RS_SetControllerLeading(RS232_Arr, false); RS_SetAdrAnswerController(RS232_Arr, 0); return; } /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************/ /***************************************************************/ /* Отправка запроса данных по протоколу ModBus - команда 15 Запись дискретных данных данных Discrete Output Coils */ /***************************************************************/ /***************************************************************/ void ModbusRTUsend15(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start, unsigned int count_bits) { // КонтрольнаЯ сумма unsigned int crc; unsigned int start_byte_number, end_byte_number, count_data_bytes; unsigned int displacement_start, bits_in_last_byte, mask_start, mask_end; unsigned int i = 0; // char byte_buffer[SIZE_MODBUS_TABLE_DISCRET * 2]; rs_arr->buffer[0] = LOBYTE(adr_contr); rs_arr->buffer[1] = CMD_RS232_MODBUS_15; rs_arr->buffer[2] = HIBYTE(adr_start); rs_arr->buffer[3] = LOBYTE(adr_start); rs_arr->buffer[4] = HIBYTE(count_bits); rs_arr->buffer[5] = LOBYTE(count_bits); start_byte_number = adr_start / 8; end_byte_number = (adr_start + (count_bits - 1)) / 8; count_data_bytes = (count_bits % 8) == 0 ? count_bits / 8 : count_bits / 8 + 1; rs_arr->buffer[6] = count_data_bytes; displacement_start = adr_start % 8; bits_in_last_byte = count_bits % 8; if (bits_in_last_byte == 0) { bits_in_last_byte = 0xFF; } mask_start = 0; for(i = 0; (i < (8 - displacement_start)) && (i < 8); i++) { mask_start |= (1 << (7 - i)); } mask_end = 0; for(i = 0; (i < bits_in_last_byte) && (i < 8); i++) { mask_end |= (1 << i); } for (i = 0; i < count_data_bytes; i++) { if (i < count_data_bytes - 1) { rs_arr->buffer[7 + i] = 0; if (((i + start_byte_number) & 1) == 0) { rs_arr->buffer[7 + i] |= (p_discrete_data_out[(i + start_byte_number) / 2].all >> displacement_start) & 0xFF; } if (((i + start_byte_number) & 1) == 1) { rs_arr->buffer[7 + i] |= (((p_discrete_data_out[(i + start_byte_number) / 2].all >> 8) & mask_start) >> displacement_start); rs_arr->buffer[7 + i] |= (((p_discrete_data_out[(i + start_byte_number) / 2 + 1].all) & ~mask_start) << (8 - displacement_start)); } } else { rs_arr->buffer[7 + i] = 0; if (((i + start_byte_number) & 1) == 0) { rs_arr->buffer[7 + i] |= ((p_discrete_data_out[(i + start_byte_number) / 2].all) >> displacement_start) & mask_end; } if (((i + start_byte_number) & 1) == 1) { rs_arr->buffer[7 + i] |= (((p_discrete_data_out[(i + start_byte_number) / 2].all >> 8) & mask_start) >> displacement_start); rs_arr->buffer[7 + i] |= (((p_discrete_data_out[(i + start_byte_number) / 2 + 1].all) & ~mask_start) << (8 - displacement_start)) & mask_end; } } } crc = 0xffff; crc = GetCRC16_IBM(crc, rs_arr->buffer, count_data_bytes + 7); rs_arr->buffer[count_data_bytes + 7] = LOBYTE(crc); rs_arr->buffer[count_data_bytes + 8] = HIBYTE(crc); rs_arr->buffer[count_data_bytes + 9] = 0; rs_arr->buffer[count_data_bytes + 10] = 0; rs_arr->RS_DataWillSend = 1; // RS_Send(rs_arr, rs_arr->buffer, (count_data_bytes + 10 + 2)); RS_Send(rs_arr, rs_arr->buffer, (count_data_bytes + 10)); // control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] = 1; /* ждем ответа */ if (adr_contr > 0 && adr_contr < 0xff) { RS_Len[CMD_RS232_MODBUS_15] = 8; RS_SetControllerLeading(rs_arr, true); RS_SetAdrAnswerController(rs_arr, adr_contr); } return; } /***************************************************************/ /***************************************************************/ /***************************************************************/ /* Ответ на передачу данных по протоколу ModBus - команда 15 Запись дискретных данных Discrete Output Coils */ /***************************************************************/ /***************************************************************/ /***************************************************************/ void ModbusRTUreceiveAnswer15(RS_DATA_STRUCT *RS232_Arr) { RS_SetAdrAnswerController(RS232_Arr, 0); RS_SetControllerLeading(RS232_Arr, false); } /***************************************************************/ /***************************************************************/ /* Получение данных от мастера по протоколу ModBus - команда 15 Запись дискретных данных данных Discrete Output Coils */ /***************************************************************/ /***************************************************************/ void ModbusRTUreceive15(RS_DATA_STRUCT *RS232_Arr) { // Контрольнаy сумма unsigned int crc, register_address, array_address, length, byte_count, quantity; unsigned int d_word, mask_start, mask_end; unsigned int i1, i2, i; unsigned int word_number, displacement_start, displacement_end; /* получили начальный адрес чтениy. */ register_address = RS232_Arr->RS_Header[3] | (RS232_Arr->RS_Header[2] << 8); array_address = register_address / 16; /* получили quantity. */ quantity = RS232_Arr->RS_Header[5] | ( RS232_Arr->RS_Header[4] << 8); /* получили количество байт данных */ byte_count = RS232_Arr->RS_Header[6]; length = (byte_count & 0x1) ? (byte_count >> 1) + 1 : (byte_count >> 1); word_number = register_address / 16; displacement_end = register_address % 16; displacement_start = 16 - displacement_end; mask_start = 0; for(i = 0; (i < displacement_end) && (i < 15); i++) { mask_start |= (1 << i); } mask_end = 0; for(i = 0; (i < displacement_start) && (i < 15); i++) { mask_end |= (1 << (15 - i)); } for (i = 0; i < length; i++) { // if (register_address >= ADR_MODBUS_TABLE && Address_MB < 0xe00) if (register_address < 0xe00) { d_word = (RS232_Arr->buffer[7 + i * 2] << 8) | RS232_Arr->RS_Header[7 + i * 2 + 1]; p_discrete_data_out[array_address + i].all &= mask_start; p_discrete_data_out[array_address + i].all |= (d_word >> displacement_start) | mask_start; if(i < length - 1) { p_discrete_data_out[array_address + i].all &= mask_end; p_discrete_data_out[array_address + i].all |= (d_word << displacement_end) | mask_end; } } } ///////////////////////////////////////////////// // Отсылка // Посчитали контрольную сумму перед самой посылкой RS232_Arr->buffer[0] = RS232_Arr->addr_recive; RS232_Arr->buffer[1] = CMD_RS232_MODBUS_15; RS232_Arr->buffer[2] = HIBYTE(register_address); RS232_Arr->buffer[3] = LOBYTE(register_address); RS232_Arr->buffer[4] = HIBYTE(quantity); RS232_Arr->buffer[5] = LOBYTE(quantity); crc = 0xffff; crc = GetCRC16_IBM(crc, RS232_Arr->buffer, 6); RS232_Arr->buffer[6] = LOBYTE(crc); RS232_Arr->buffer[7] = HIBYTE(crc); RS232_Arr->buffer[8] = 0; RS232_Arr->buffer[9] = 0; // RS232_Arr->RS_DataWillSend = 1; RS_Send(RS232_Arr, RS232_Arr->buffer, 10); return; } /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /***************************************************************/ /***************************************************************/ /***************************************************************/ /* Передача данных по протоколу ModBus - команда 16 Передача данных */ /***************************************************************/ /***************************************************************/ /***************************************************************/ void ModbusRTUsend16(RS_DATA_STRUCT *rs_arr, int adr_contr, unsigned int adr_start, unsigned int count_word) { // КонтрольнаЯ сумма unsigned int crc, Address_MB, i; //, Length_MB; //, Bytecnt_MB, Data1,Data2; // int Data, digital, ust_I, ust_Time; //Length_MB = count_word; Address_MB = adr_start; // Отсылка // Посчитали контрольную сумму перед самой посылкой rs_arr->buffer[0] = adr_contr; rs_arr->buffer[1] = CMD_RS232_MODBUS_16; rs_arr->buffer[2] = HIBYTE(adr_start); rs_arr->buffer[3] = LOBYTE(adr_start); rs_arr->buffer[4] = HIBYTE(count_word); rs_arr->buffer[5] = LOBYTE(count_word); rs_arr->buffer[6] = LOBYTE(count_word * 2); for (i = 0; i < count_word; i++) { // rs_arr->buffer[7 + i * 2] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.HB; // rs_arr->buffer[7 + i * 2 + 1] = p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.LB; rs_arr->buffer[7 + i * 2] = p_analog_data_out[Address_MB + i].byte.HB; rs_arr->buffer[7 + i * 2 + 1] = p_analog_data_out[Address_MB + i].byte.LB; } crc = 0xffff; // crc = get_crc_ccitt(crc, rs_arr->buffer, Length_MB*2+7); crc = GetCRC16_IBM(crc, rs_arr->buffer, (unsigned long)(count_word * 2 + 7)); rs_arr->buffer[count_word * 2 + 7] = LOBYTE(crc); rs_arr->buffer[count_word * 2 + 8] = HIBYTE(crc); rs_arr->buffer[count_word * 2 + 9] = 0; rs_arr->buffer[count_word * 2 + 10] = 0; rs_arr->RS_DataWillSend = 1; RS_Send(rs_arr, rs_arr->buffer, (count_word * 2 + 10)); // control_station.flag_waiting_answer[CONTROL_STATION_INGETEAM_PULT_RS485] = 1; // ждем ответа if (adr_contr > 0 && adr_contr < 0xff) { RS_Len[CMD_RS232_MODBUS_16] = 8; RS_SetControllerLeading(rs_arr, true); RS_SetAdrAnswerController(rs_arr, adr_contr); } } /***************************************************************/ /***************************************************************/ /* Получение данных от мастера по протоколу ModBus - команда 16 Передача данных */ /***************************************************************/ /***************************************************************/ void ModbusRTUreceive16(RS_DATA_STRUCT *RS232_Arr) { // Контрольнаy сумма unsigned int crc, Address_MB, Length_MB, Bytecnt_MB, i /*, Data1,Data2,Quantity*/; int /*Data,*/ i1, i2; /* получили начальный адрес чтениy. */ Address_MB = RS232_Arr->RS_Header[3] | (RS232_Arr->RS_Header[2] << 8); /* получили quantity. */ //Quantity = RS232_Arr->RS_Header[5] | ( RS232_Arr->RS_Header[4] << 8); /* получили количество байт данных */ // Length_MB = (RS232_Arr->RS_Header[4] << 8 ) | RS232_Arr->RS_Header[5]; Bytecnt_MB = RS232_Arr->RS_Header[6]; Length_MB = Bytecnt_MB >> 1; for (i = 0; i < Length_MB; i++) { if (Address_MB >= ADR_MODBUS_TABLE && Address_MB < 0xe00) { // p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.HB = RS232_Arr->buffer[3 + i * 2]; // p_analog_data_out[Address_MB - ADR_MODBUS_TABLE + i].byte.LB = RS232_Arr->buffer[3 + i * 2 + 1]; p_analog_data_out[Address_MB + i].byte.HB = RS232_Arr->buffer[3 + i * 2]; p_analog_data_out[Address_MB + i].byte.LB = RS232_Arr->buffer[3 + i * 2 + 1]; } if (Address_MB >= 0xe00 && Address_MB < 0xf00) { options_controller[Address_MB - 0xe00 + i].byte.HB = RS232_Arr->RS_Header[7 + i * 2]; options_controller[Address_MB - 0xe00 + i].byte.LB = RS232_Arr->RS_Header[7 + i * 2 + 1]; } } if (Address_MB >= 0xe00 && Address_MB < 0xf00) { i1 = options_controller[0].all; i2 = options_controller[1].all; store_data_flash(options_controller, sizeof(options_controller)); SetCntrlAddr(i1, i2); /* Установка адреса контроллера */ } ///////////////////////////////////////////////// // Отсылка // Посчитали контрольную сумму перед самой посылкой RS232_Arr->buffer[0] = RS232_Arr->addr_recive; RS232_Arr->buffer[1] = CMD_RS232_MODBUS_16; RS232_Arr->buffer[2] = HIBYTE(Address_MB); RS232_Arr->buffer[3] = LOBYTE(Address_MB); RS232_Arr->buffer[4] = 0; RS232_Arr->buffer[5] = 2; crc = 0xffff; crc = GetCRC16_IBM(crc, RS232_Arr->buffer, 6); RS232_Arr->buffer[6] = LOBYTE(crc); RS232_Arr->buffer[7] = HIBYTE(crc); RS232_Arr->buffer[8] = 0; RS232_Arr->buffer[9] = 0; // RS232_Arr->RS_DataWillSend = 1; RS_Send(RS232_Arr, RS232_Arr->buffer, 10); return; } /***************************************************************/ /***************************************************************/ /***************************************************************/ /* Ответ на передачу данных по протоколу ModBus - команда 16 Передача данных */ /***************************************************************/ /***************************************************************/ /***************************************************************/ void ModbusRTUreceiveAnswer16(RS_DATA_STRUCT *RS232_Arr) { // КонтрольнаЯ сумма unsigned int Address_MB; //, crc, Length_MB, Bytecnt_MB/*, i, Data1,Data2*/; //int Data, digital, ust_I, ust_Time; /* получили начальный адрес чтениЯ. */ // Address_MB = RS232_Arr->RS_Header[3] | ( RS232_Arr->RS_Header[2] << 8); // if (Address_MB == ADRES_LOG_REGISTERS) { // } err_send_log_16 = 0; /* получили количество слов данных */ //Length_MB = (RS232_Arr->RS_Header[4] << 8 ) | RS232_Arr->RS_Header[5]; //Bytecnt_MB = RS232_Arr->RS_Header[6]; RS_SetAdrAnswerController(RS232_Arr, 0); RS_SetControllerLeading(RS232_Arr, false); err_modbus16 = 0; return; } /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////