⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iec103m.cpp

📁 一个完整的RTU程序源码,用DOS平台,支持16串口,在天津港用的很多,8个规约103,modbus,cdt,1801,u4f
💻 CPP
字号:
#include "sc_cfg.h"
#include "common.h"
#include "class.h"
#include "extern.h"

const INT8U CIec103M::RESET_CU = 0;
const INT8U CIec103M::CALL_CLASS1 = 10;
const INT8U CIec103M::CALL_CLASS2 = 11;
const INT8U CIec103M::CALL_ALL = 7;

CIec103M::CIec103M(INT8U portno):CMasterPollingProtocol(portno)
{
	FCB = NULL;
	ACDFlag = NULL;
	isGI = NULL;
	LastCommand = NULL;

	if ((FCB = new INT8U[dev_num]) == NULL) ErrorExit("FCB memory alloc error in port%d", myportno);
	if ((ACDFlag = new INT8U[dev_num]) == NULL) ErrorExit("ACDFlag memory alloc error in port%d", myportno);
	if ((isGI = new BOOLEAN[dev_num]) == NULL) ErrorExit("isGI memory alloc error in port%d", myportno);
	if ((LastCommand = new INT8U[dev_num]) == NULL) ErrorExit("LastCommand memory alloc error in port%d", myportno);

	memset(FCB, 0, dev_num);
	memset(ACDFlag, 0, dev_num); // communicate
	memset(isGI, TRUE, dev_num);
	memset(LastCommand, RESET_CU, dev_num);

	PortSet_t *pPort = GetPortSet(myportno);

	SetQueryGap(4000000L / pPort->Baud); // wait data transfer

	send_cycle = 0;
}

void CIec103M::PreProcess()
{
	if (port_yk_info.Y_PRESET) { //yk preset
		if (port_yk_info.yk_des == myportno) {
			port_yk_info.Y_PRESET = FALSE;
			port_yk_info.Y_CHECK = TRUE;
			port_yk_info.check_result = YKROK;
			return;
		}
	}
}

void CIec103M::master_send()
{
	INT8U	index = CurrentQueryAddr - DevStartAddr;

	if (ACDFlag[index]) { // have class1 data
		switch (LastCommand[index]) { // then call class1 data
			case CALL_CLASS2:
			case RESET_CU:
			case CALL_ALL:
				query_class1_data();
				QueryStatus = QUERY;
				LastCommand[index] = CALL_CLASS1;
				return;
		}
	}

	if (++CurrentQueryAddr > DevEndAddr) {
		CurrentQueryAddr = DevStartAddr;
		send_cycle++;
	}

	index = CurrentQueryAddr - DevStartAddr;

	if (!isLink[index]) { // if dev failure send reset cu
		reset_cu();
		QueryStatus = QUERY;
		ACDFlag[index] = 0;
		FCB[index] = 0;
		isGI[index] = FALSE;
		LastCommand[index] = RESET_CU;
		return;
	}

	if (port_yk_info.Y_EXEC) { //yk execute
		if (port_yk_info.yk_des == myportno) {
			port_yk_info.Y_EXEC = FALSE;
			send_asdu20_yk();
			QueryStatus = BOARDCAST;
			return;
		}
	}

	if (port_yk_info.Y_ESC) { //yk escape
		if (port_yk_info.yk_des == myportno) {
			port_yk_info.Y_ESC = FALSE;
			return;
		}
	}

	if (send_cycle >= 4000) { // per 4000 cycle call general interration
		for (int i = 0; i <= dev_num; i++)
			isGI[i] = TRUE;
		send_cycle = 0;
	}

	if (send_cycle % 100 == 1) { // per 99 cycle once asdu6
		send_asdu6();
		send_cycle++;
		QueryStatus = BOARDCAST;
		return;
	}

	switch (isGI[index]) {
		case TRUE: // general interration
			isGI[index] = FALSE;
			send_asdu7();
			QueryStatus = QUERY;
			LastCommand[index] = CALL_ALL;
			break;
		case FALSE: // class 2
			isGI[index] = FALSE;
			query_class2_data();
			QueryStatus = QUERY;
			LastCommand[index] = CALL_CLASS2;
			break;
	}
}

void CIec103M::master_receive()
{
	INT8U recbuf[IEC103_RECE_BUFSIZE];
	INT16U rece_len = get_com_rece_num(myportno);

	if (rece_len > 255) return; // too big
	if (rece_len < 5) return; // too little
	get_com_rece_nbytes(recbuf, 5, myportno);

	if ((recbuf[0] == 0x10) && (recbuf[4] == 0x16)
		&& (checksum(&recbuf[1], 2) == recbuf[3])) {
		read_com_rece_nbytes(recbuf, 5, myportno);
		draw_rece_message(myportno, recbuf, 5, POLL_RECE_COLOR);
		process_fixed(recbuf);
		return;
	}

	INT16U framelen = recbuf[1] + 6;
	if ((recbuf[0] == 0x68) && (recbuf[3] == 0x68) && (recbuf[1] == recbuf[2])) {
		if (rece_len >= framelen) {
			read_com_rece_nbytes(recbuf, rece_len, myportno);
			if ((recbuf[framelen - 1] == 0x16) &&
				(checksum(&recbuf[4], recbuf[1]) == recbuf[framelen - 2])) {
				draw_rece_message(myportno, recbuf, framelen, POLL_RECE_COLOR);
				process_var(recbuf);
			}
		}
	}
	else del_com_rece_one(myportno);
}

void CIec103M::process_fixed(INT8U *buf)
{
	INT8U index = CurrentQueryAddr - DevStartAddr;

	if (buf[1] & 0x20) { //acd = 1
		ACDFlag[index] = 1;
	}

	switch (buf[1] & 0x0f) {
		case 0:
			if (buf[2] == CurrentQueryAddr) QueryStatus = ANSWER;
			break;
		case 9:
			if (buf[2] == CurrentQueryAddr) QueryStatus = ANSWER;
			break;
		case 1:
		case 11:
		case 14:
		case 15:
			if (buf[2] == CurrentQueryAddr) QueryStatus = ANSWER;
			break;
	}
}

void CIec103M::process_var(INT8U *buf)
{
	INT8U index = CurrentQueryAddr - DevStartAddr;

	if (buf[4] & 0x20) {
		ACDFlag[index] = 1;
	}

	if (buf[9] == CurrentQueryAddr) QueryStatus = ANSWER;

	if ((buf[4] & 0x0f) == 8) {
		switch (buf[6]) {
			case 1: // asdu1 = time tip (single dot yx)
				process_asdu1(buf);
				break;
			case 2: // asdu2 = relative time tip (protect infomation)
				process_asdu2(buf);
				break;
			case 5: // asdu5 = type
				break;
			case 8: // asdu8 = general interration end
				break;
			case 9: // asdu9 = measurement II
				process_asdu9(buf);
				break;
			case 205: // asdu205 = power data
				process_asdu205(buf);
				break;
		}
	}
}

void CIec103M::process_asdu1(INT8U *buf)
{
	INT8U value = 0;
	soe_record_t temp_soe;
	yxbw_record_t temp_yx_bw;
	sclock sclk;
	INT16U temp = 0;
	INT16U switch_no = 0;
	YxDefine_t *pyx = NULL;

	for (int i = 0; i < yx_num; i++) {
		pyx = GetYxDefine(pyx_tbl[i]);
		if ((buf[9] == pyx->devno) &&
			(buf[10] == pyx->type) && (buf[11] == pyx->info)) {

			if ((buf[12] & 0x03) == 2) value = 1; // switch close
			else if ((buf[12] & 0x03) == 1) value = 0; // switch open
			else continue;

			yx_update_db(pyx_tbl[i], value);

			if (buf[8] != 1) continue; // if yx change, go on

			temp_soe.status_switch_no = pyx_tbl[i] & 0xfff;
			if (value)
				temp_soe.status_switch_no |= 0x8000;
			else temp_soe.status_switch_no &= 0x7fff;	// 0x80:0->1  0x00:1->0

			GetClock(&sclk);
			temp = ((buf[14] << 8) & 0xff00) + buf[13];

			temp_soe.day = sclk.day;
			temp_soe.hour = buf[16];
			temp_soe.minute = buf[15];
			temp_soe.second = temp / 1000;
			temp_soe.msecond = temp % 1000;

			insert_soe(&temp_soe);

			switch_no = temp_soe.status_switch_no & 0xfff;
			temp_yx_bw.func_code = switch_no / 32;
			temp_yx_bw.yx_code[0] = dbdata.Yx[switch_no / 32 * 2];
			temp_yx_bw.yx_code[1] = dbdata.Yx[switch_no / 32 * 2 + 1];
			insert_yx_bw(&temp_yx_bw);							// add to yx bw buffer
		}
	}
}

void CIec103M::process_asdu2(INT8U *buf)
{
	INT8U value = 0;
	soe_record_t temp_soe;
	yxbw_record_t temp_yx_bw;
	sclock sclk;
	INT16U temp = 0;
	INT16U switch_no = 0;
	YxDefine_t *pyx = NULL;

	for (int i = 0; i < yx_num; i++) {
		pyx = GetYxDefine(pyx_tbl[i]);
		if ((buf[9] == pyx->devno) &&
			(buf[10] == pyx->type) && (buf[11] == pyx->info)) {

			if ((buf[12] & 0x03) == 2) value = 1; // switch close
			else if ((buf[12] & 0x03) == 1) value = 0; // switch open
			else continue;
			yx_update_db(pyx_tbl[i], value);

			if (buf[8] != 1) continue; // if yx change, go on

			temp_soe.status_switch_no = i & 0xfff;
			if (value)
				temp_soe.status_switch_no |= 0x8000;
			else temp_soe.status_switch_no &= 0x7fff;	// 0x80:0->1  0x00:1->0

			GetClock(&sclk);
			temp = ((buf[18] << 8) & 0xff00) + buf[17];

			temp_soe.day = sclk.day;
			temp_soe.hour = buf[20];
			temp_soe.minute = buf[19];
			temp_soe.second = temp / 1000;
			temp_soe.msecond = temp % 1000;

			insert_soe(&temp_soe);

			switch_no = temp_soe.status_switch_no & 0xfff;
			temp_yx_bw.func_code = switch_no / 32;
			temp_yx_bw.yx_code[0] = dbdata.Yx[switch_no / 32 * 2];
			temp_yx_bw.yx_code[1] = dbdata.Yx[switch_no / 32 * 2 + 1];
			insert_yx_bw(&temp_yx_bw);							// add to yx bw buffer
		}
	}
}

void CIec103M::process_asdu9(INT8U *buf)
{
	INT16U value = 0;
	YcDefine_t *pyc = NULL;

	for (int i = 0; i < yc_num; i++) {
		pyc = GetYcDefine(pyc_tbl[i]);
		if ((buf[9] == pyc->devno) &&
			(buf[10] == pyc->type) && (buf[11] == pyc->info)) {
			if ((buf[7] & 0x7f) < pyc->order) continue;
			// add yc data process here

			value = buf[pyc->order * 2 + 11];
			value = (value << 8) + buf[pyc->order * 2 + 10];
			if (value & 0x02) continue; // incorrect yc data
			value = (value >> 3) & 0x1fff;
			if (value & 0x1000) value = (~value & 0xfff) | 0x800;//negative
			yc_update_db(pyc_tbl[i], value);
		}
	}
}

void CIec103M::process_asdu205(INT8U *buf)
{
	INT32U value = 0;
	YmDefine_t *pym = NULL;

	for (int i = 0; i < ym_num; i++) {
		pym = GetYmDefine(pym_tbl[i]);
		if ((buf[9] == pym->devno)
			&& (buf[10] == pym->type) && (buf[11] == pym->info)) {
			value = buf[15];
			value = (value << 8) + buf[14];
			value = (value << 8) + buf[13];
			value = (value << 8) + buf[12];
			if (value & 0x40000000) continue;
			else ym_update_db(pym_tbl[i], value & 0xfffffff);
		}
	}
}

void CIec103M::query_class1_data()
{
	INT8U askbuf[5];
	INT8U index = CurrentQueryAddr - DevStartAddr;

	askbuf[0] = 0x10;
	askbuf[1] = ((FCB[index] & 0x01) << 5) | 0x5a;
	askbuf[2] = CurrentQueryAddr;
	askbuf[3] = checksum(&askbuf[1], 2);
	askbuf[4] = 0x16;

	FCB[index] = ~FCB[index];
	com_transfer(myportno, 5, askbuf);
	draw_send_message(myportno, askbuf, 5, POLL_SEND_COLOR);
}

void CIec103M::query_class2_data()
{
	INT8U askbuf[5];
	INT8U index = CurrentQueryAddr - DevStartAddr;

	askbuf[0] = 0x10;
	askbuf[1] = ((FCB[index] & 0x01) << 5) | 0x5b;
	askbuf[2] = CurrentQueryAddr;
	askbuf[3] = checksum(&askbuf[1], 2);
	askbuf[4] = 0x16;

	FCB[index] = ~FCB[index];
	com_transfer(myportno, 5, askbuf);
	draw_send_message(myportno, askbuf, 5, POLL_SEND_COLOR);
}

void CIec103M::reset_cu()
{
	INT8U askbuf[5];

	askbuf[0] = 0x10;
	askbuf[1] = 0x40;
	askbuf[2] = CurrentQueryAddr;
	askbuf[3] = checksum(&askbuf[1], 2);
	askbuf[4] = 0x16;

	com_transfer(myportno, 5, askbuf);
	draw_send_message(myportno, askbuf, 5, POLL_SEND_COLOR);
}

//boardcasting sync time
void CIec103M::send_asdu6()
{
	sclock clk;
	INT16U temp;
	INT8U	askbuf[21];

	GetClock(&clk);

	askbuf[0] = 0x68;
	askbuf[1] = 15;
	askbuf[2] = 15;
	askbuf[3] = 0x68;
	askbuf[4] = 0x44; //send/no confirm
	askbuf[5] = 0xff; //boardcast address
	askbuf[6] = 0x06; //C_SYN_TA_3
	askbuf[7] = 0x81; //VSQ
	askbuf[8] = 0x08; //COT
	askbuf[9] = 0xff; //boardcast address
	askbuf[10] = 0xff; //GLB
	askbuf[11] = 0;

	temp = clk.second * 1000 + clk.msecond;
	askbuf[12] = temp & 0xff;
	askbuf[13] = (temp >> 8) & 0xff;
	askbuf[14] = clk.minute & 0xff;
	askbuf[15] = clk.hour & 0xff;
	askbuf[16] = ((clk.weekday & 0x00) << 5) + (clk.day & 0x1f);
	askbuf[17] = clk.month & 0xff;
	askbuf[18] = clk.year % 100;

	askbuf[19] = checksum(&askbuf[4], 15);
	askbuf[20] = 0x16;

	com_transfer(myportno, 21, askbuf);
	draw_send_message(myportno, askbuf, 21, POLL_SEND_COLOR);
}

// general interration
void CIec103M::send_asdu7()
{
	INT8U askbuf[15];
	INT8U index = CurrentQueryAddr - DevStartAddr;

	askbuf[0] = 0x68;
	askbuf[1] = 0x09;
	askbuf[2] = 0x09;
	askbuf[3] = 0x68;
	askbuf[4] = 0x53 | ((FCB[index] << 5) & 0x20);
	askbuf[5] = CurrentQueryAddr;

	askbuf[6] = 0x07;
	askbuf[7] = 0x81;
	askbuf[8] = 0x09;
	askbuf[9] = CurrentQueryAddr;
	askbuf[10] = 0xff; //GLB
	askbuf[11] = 0;
	askbuf[12] = CurrentQueryAddr;
	askbuf[13] = checksum(&askbuf[4], 9);
	askbuf[14] = 0x16;

	FCB[index] = ~FCB[index];
	com_transfer(myportno, 15, askbuf);
	draw_send_message(myportno, askbuf, 15, POLL_SEND_COLOR);
}

// general command yk
void CIec103M::send_asdu20_yk()
{
	INT8U askbuf[16];
	INT8U index = port_yk_info.dev_no - DevStartAddr;

	askbuf[0] = 0x68;
	askbuf[1] = 0x0a;
	askbuf[2] = 0x0a;
	askbuf[3] = 0x68;
	askbuf[4] = 0x53 | ((FCB[index] << 5) & 0x20);
	askbuf[5] = port_yk_info.dev_no;
	askbuf[6] = 0x14;
	askbuf[7] = 0x81;
	askbuf[8] = 20;
	askbuf[9] = port_yk_info.dev_no;
	askbuf[10] = port_yk_info.type;
	askbuf[11] = port_yk_info.yk_no;
	if (port_yk_info.yk_cmd == YKCTRIP) askbuf[12] = 1; // switch open
	else if (port_yk_info.yk_cmd == YKCCLOSE) askbuf[12] = 2; // switch close
	else askbuf[12] = 0;
	askbuf[13] = 0;

	askbuf[14] = checksum(&askbuf[4], 10);
	askbuf[15] = 0x16;

	FCB[index] = ~FCB[index];
	com_transfer(myportno, 16, askbuf);
	draw_send_message(myportno, askbuf, 16, POLL_SEND_COLOR);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -