Цитата(pokk @ Jul 11 2017, 09:38)

А то как не крути вечно такой колхоз получается
Что касается такого колхоза, то этого хватает у каждого.
И вообще это не колхоз, это классика - см ниже!

Если речь идет о автоматах, кроющих практически всю функциональность устройства, то тут все становится сложнее, потому что не есть проблема реализовать это все, а проблемой является выбор собственного стиля и подхода, чтобы было все понятно и прозрачно в первую очередь для самого себя.
CODE
#define TRANSPORT_TIMEOUT_SERIAL_SEC 10
#define TRANSPORT_TIMEOUT_TCPIP_SEC 5
#define LONG_RUN_TIMEOUT_SEC 60
#define AUTO_PICKUP_TIME_MS 500
#define NUM_RETRIES 3
// added by me timeouts:
#define RECEIVE_TIMEOUT_MS 1000
#define ANSWER_TIMEOUT_MS 100
enum {
errNO=0,
errMESSAGE_SIZE,
errOP_CODE,
errRECORDS_QTY,
errINDEX1,
errINDEX2,
errINDEX3,
errNOT_SUPPORTED,
errREAD_ONLY,
errWRONG_SIZE,
errWRITE_ONLY,
errWRONG_OPCODE,
errSIZE,
};
#define RECEIVED_MESSAGE_LENGTH ((int)com1.rx_buf[1]+((int)com1.rx_buf[2])<<8)
#define RECEIVED_TYPE (com1.rx_buf[3])
#define RECEIVED_SEQUENCE (com1.rx_buf[4])
#define ctrlRECEIVED (com1.rx_buf[5])
#define ctrlACK ('A')
#define ctrlNAK ('N')
#define ctrlEND ('E')
#define ctrlWAIT ('W')
#define ctrlPICKUP ('P')
#define ctrlDROP ('D')
#define XML_PTR_FIRST (char*)(com1.rx_buf+5)
#define XML_PTR_LAST (com1.rx_buf+RECEIVED_MESSAGE_LENGTH-4)
#define ETX_INDEX (RECEIVED_MESSAGE_LENGTH-3)
/*
Control message
1 byte STX StartMessage
2 byte Unsigned Binary Length Length of the entire message; including StartMessage and EndMessage but excluding CRC bytes
1 byte ASCII Type 'C'
1 byte Unsigned Binary Sequence 0x00 is invalid value
1 byte ASCII ControlFunction 'A' ACK
'N' NAK
'E' End Sequence
'W' Wait
'P' Pickup
'D' Drop Link
1 byte ETX EndMessage
2 byte Binary CRC See CRC Calculation
Payload message
1 byte STX StartMessage
2 byte UnsignedBinary Length Length of the entire message; including StartMessage and EndMessage but excluding CRC bytes
1 byte ASCII Type 'P'
1 byte Unsigned Binary Sequence 0x00 is invalid value
Variable Unsigned Binary Payload The transported application protocol message
1 byte ETX EndMessage
2 byte Unsigned Binary CRC See CRC Calculation
*/
#define XML_START_OFFSET 5
#define XML_END_OFFSET 2
char payload_sent_wait_control;
char payload_sent_time;
char payload_sent_qty;
void PrepareTransportPayloadHeader(void)
{ com1.tx_head=com1.tx_buf;
*com1.tx_head++=STX;
com1.tx_head+=2; // pass length
*com1.tx_head++='P'; // payload type
*com1.tx_head++=RECEIVED_SEQUENCE;
}
void PrepareTransportControlMessage(char com)
{
int my_checksum;
com1.tx_head=com1.tx_buf;
*com1.tx_head++=STX;
*com1.tx_head++=7; // length = 7
*com1.tx_head++=0;
*com1.tx_head++='C'; // control type
*com1.tx_head++=RECEIVED_SEQUENCE;
*com1.tx_head++=com;
*com1.tx_head++=ETX;
my_checksum=crc16_ccitt(com1.tx_buf, 7);
*com1.tx_head++=(char)(my_checksum&0x00ff);
*com1.tx_head++=(char)(my_checksum>>8);
}
void PrepareTransportTrailer(void)
{
int my_size;
int my_checksum;
*com1.tx_head++=ETX;
my_size=com1.tx_head- com1.tx_buf;
com1.tx_buf[1]=(char)(my_size&0x00ff);
com1.tx_buf[2]=(char)(my_size>>8);
my_checksum=crc16_ccitt(com1.tx_buf, my_size);
*com1.tx_head++=(char)(my_checksum&0x00ff);
*com1.tx_head++=(char)(my_checksum>>8);
}
enum { UNCONFIGURED,
RESTART_RX,
WAITING_STX,
WAITING_ETX,
WAITING_BCC1,
WAITING_BCC2,
ANALYSE_MESSAGE,
PREPARE_MESSAGE,
START_SEND_MESSAGE,
WAITING_START_TRANSMIT,
WAITING_END_TRANSMIT,
FINAL,
PREPARE_NAK,
PREPARE_DROP,
PREPARE_END };
char transport_error;
#define USE_TIMEOUT 1
u16 TimeoutRunning(void)
{
#ifdef USE_TIMEOUT
return com1.timeout;
#else
return 1;
#endif
}
void fRnt(void)
{
static u16 my_checksum;
static u16 message_checksum;
switch (pstate)
{ case UNCONFIGURED:
Com1Init();
pstate++;
break;
case RESTART_RX:
Com1SetReceive(COM1_WAIT_STX);
prot_error=errNO;
pstate++;
OFF_LED5();
OFF_LED4();
break;
case WAITING_STX:
if ( payload_sent_wait_control )
{ if (payload_sent_qty<2)
{ if (event==evSec)
{ if (payload_sent_time<10)
payload_sent_time++;
else
{ pstate=START_SEND_MESSAGE;
payload_sent_qty++;
payload_sent_time=0;
}
}
}
else // all attempts done
payload_sent_wait_control=0;
}
else
{ payload_sent_qty=0;
payload_sent_time=0;
}
switch (com1.rx_status)
{ case COM1_RECEIVED:
pstate=RESTART_RX; // buffer is over
break;
case COM1_RECEIVING_:
pstate=WAITING_ETX;
com1.timeout=RECEIVE_TIMEOUT_MS;
break;
}
break;
case WAITING_ETX:
ON_LED4(); // recieving starts
if (TimeoutRunning())
{ if (com1.rx_head>com1.rx_tail)
{ switch (*com1.rx_tail)
{
case ETX:
// case EOT:
com1.rx_tail++;
if (com1.rx_tail>com1.rx_buf+5)
pstate++;
break;
default:
com1.rx_tail++;
break;
}
}
}
else
pstate=RESTART_RX;
break;
case WAITING_BCC1:
if (TimeoutRunning())
{ if (com1.rx_head>com1.rx_tail)
{ com1.rx_tail++;
pstate++;
}
}
else
pstate=RESTART_RX;
break;
case WAITING_BCC2:
if (TimeoutRunning())
{ if (com1.rx_head>com1.rx_tail)
{ com1.rx_tail++;
pstate++;
Com1SetReceive(COM1_PASSIVE);
}
}
else
pstate=RESTART_RX;
break;
case ANALYSE_MESSAGE:
OFF_LED4();
if (com1.rx_head<com1.rx_buf+8) // too short message
{ pstate=RESTART_RX;
break;
}
my_checksum=crc16_ccitt(com1.rx_buf, com1.rx_tail-com1.rx_buf-2);
message_checksum= ( ((unsigned int)*(com1.rx_head-2)) ) |
( ((unsigned int)*(com1.rx_head-1))<<8 );
#if (defined IGNORE_CHECKSUM)
#elif (defined USE_CHECKSUM)
if ( (my_checksum!=message_checksum) || // wrong checksum
(*(com1.rx_head-3) !=ETX) //not ETX
)
{ pstate=RESTART_RX;
break;
}
#else
#error "What to do with checksum?"
#endif
switch (RECEIVED_TYPE)
{ case 'C': // control message
switch (ctrlRECEIVED)
{ case ctrlEND:
pstate=PREPARE_END;
break;
case ctrlDROP:
pstate=PREPARE_DROP;
break;
default:
pstate=RESTART_RX;
break;
}
break;
case 'P': //
if (!AnalyseXmlOk(XML_PTR_FIRST,(char*)com1.rx_head-4))
pstate=PREPARE_NAK;
else
pstate=PREPARE_MESSAGE;
break;
}
break;
case PREPARE_MESSAGE:
ON_LED5(); // answering started
com1.tx_head=com1.tx_buf;
PrepareTransportPayloadHeader();
PrepareXml();
PrepareTransportTrailer();
pstate++;
payload_sent_wait_control=1;
payload_sent_time=0;
break;
case START_SEND_MESSAGE:
SET_TRANSMIT(); // for driver
pstate++;
com1.timeout=ANSWER_TIMEOUT_MS;
break;
case WAITING_START_TRANSMIT:
if (!com1.timeout)
{ Com1SetTransmit(COM1_TRANSMITTING);
pstate++;
}
break;
case WAITING_END_TRANSMIT:
if (com1.tx_status==COM1_TRANSMITTED)
if (TRANSMIT_OVER())
{ com1.timeout=0;
pstate++;
}
break;
case FINAL:
OFF_LED5();
pstate=RESTART_RX;
break;
case PREPARE_NAK:
pstate = UNCONFIGURED;
break;
case PREPARE_DROP: //0207004300440389AC
ON_LED5();
PrepareTransportControlMessage('D');
com1.timeout=ANSWER_TIMEOUT_MS;
SET_TRANSMIT();
pstate=WAITING_START_TRANSMIT;
break;
case PREPARE_END:
ON_LED5();
PrepareTransportControlMessage('E');
com1.timeout=ANSWER_TIMEOUT_MS;
SET_TRANSMIT();
pstate=WAITING_START_TRANSMIT;
payload_sent_wait_control=0;
break;
default:
pstate = UNCONFIGURED;
break;
}
}
Уходя, оставьте свет...