Author Topic: Also about the uart get data!  (Read 9274 times)

Offline tr111

  • Jr. Member
  • **
  • Posts: 72
    • View Profile
Also about the uart get data!
« on: September 08, 2007, 10:40:45 AM »
 When I send the data to the uart.data=(0x11,0x22,0x33,0x44,0x55)
       like this:
       #else
        if ((iAppState & (STATE_ACTIVE | STATE_DELAYING | STATE_ESCAPING | STATE_RESTARTING | STATE_VALIDATING)) && (Length = fnMsgs(SerialPortID))) {
            while ((Length = fnRead( SerialPortID, ucInputMessage, MEDIUM_MESSAGE)) != 0) {
                fnEchoInput(ucInputMessage, Length);
                fnDebugMsg("\n\rLED ON OFF\n\r");
                if (usData_state == ES_NO_CONNECTION) {
                    if (fnCommandInput(ucInputMessage, Length, SOURCE_SERIAL)) {
                        if (fnInitiateLogin(ES_SERIAL_LOGIN) == TELNET_ON_LINE) {
                            static const CHAR ucCOMMAND_MODE_BLOCKED[] = "Command line blocked\r\n";
                            fnWrite(SerialPortID, (unsigned char *)ucCOMMAND_MODE_BLOCKED, sizeof(ucCOMMAND_MODE_BLOCKED));
                        }
                    }
                }
       I find the Length always 1,and printf the "LED ON OFF" five times! Why!
       I want the get the data(0x11,0x22,0x33,0x44,0x55) is a long buff,not the CHAR_MODE one by one!
       I want the Length is 5 not 1,so that I can easy to use the buff.not like the char!
       

     When I #define TEST_MSG_MODE,but it never go to the
     #ifdef TEST_MSG_MODE
          #ifdef TEST_MSG_CNT_MODE
            while (fnMsgs(SerialPortID)) {
                unsigned char ucLength;

                fnRead( SerialPortID, &ucLength, 1);                     // get message length
                Length = fnRead( SerialPortID, ucInputMessage, ucLength);
              fnDebugMsg("\n\rLED ON 1OFF\n\r");
                fnEchoInput(ucInputMessage, ucLength);
            }
          #else
            while (fnMsgs(SerialPortID)) {
                Length = fnRead( SerialPortID, ucInputMessage, MEDIUM_MESSAGE);
                 fnDebugMsg("\n\rLED2 ON OFF\n\r");
                fnEchoInput(ucInputMessage, Length);
            }
          #endif
fnMsgs(SerialPortID); This is called to return the number of waiting messages. In character mode this is equal to the number of characters but in message mode it will indicate the number of complete messages and not individual characters.
   how can I get the "in message mode",I want to get complete messages and not individual characters!

« Last Edit: September 08, 2007, 10:56:45 AM by tr111 »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: Also about the uart get data!
« Reply #1 on: September 08, 2007, 11:40:52 AM »
Hi

It is normal that in character mode the task is woken on each received character. Then the demo code is sending each character back.

If you want to collect the received bytes until you have a 'complete' message different methods are possible:

1. If your messages always have a terminating character then you can use message mode. This terminating character must be known and fixed, and entered when configuring the interface:
tInterfaceParameters.ucMessageTerminator = '\r'
This is most useful when human entry is used since a line feed can be used as a terminating character. This is however not a possibility when the received data is of random content.

2. Fixed message lengths.
If the received messages have random content but fixed length, they can be collected until a complete message is available. In character mode, the following could be used (called each time the task is worken by a character reception).
while (fnMsgs(SerialPortID) >= MESSAGE_LENGTH) {
    unsigned char ucBuff[MESSAGE_LENGTH];
    fnRead(SerialPortID, ucBuff, MESSAGE_LENGTH);         // read a complete message which is waiting
    fnWrite(SerialPortID, ucBuff, MESSAGE_LENGTH);        // send complete message back
}


3. Protocol based messages
Often binary messages are protocol based whhere the length field is included in the message. Generally the best solution here is to collect each received character to a local buffer (this means that the input buffer of the tty queue can be set very short since messages are not collected there but rather copied immediately to a local copy). The message can be interpreted as the bytes arrive and once the message is complete it can be processed. The following is a typical example where ucInputMessage[] and other variables are declared as static so that they retain the data between calls.

Code: [Select]
  while (fnRead( PortID, &ucInputMessage[iRxCnt], 1 )) {                 // while bytes waiting at input
    if (STATE_RECEIVING == iProtState) {
      if (ucInputMessage[iRxCnt] == CONTROL_CHAR) {
        iProtState = STATE_ENDING;                                       // possible packet end being received
      }
      else {
        iRxCnt++;                                                        // keep the received byte
      }
    }
    else if (STATE_ENDING == iProtState) {
      if (ucInputMessage[iRxCnt] == END_BYTE) {
        fnProcessRx(ucInputMessage, iRxCnt);                             // remove end byte from buffer
        iProtState = STATE_ACTIVE;                                       // complete message has been collected
        iRxCnt = 0;                                                      // flush old data - ready to receive new in our input buffer
        ucInputMessage[1] = 0;                                           // ensure zero terminated (for Linux console)
      }
    }
  }

4. In some cases (example when transferring random binary data from the serial port to somewhere else - like TCP) there is no framing possibilities. In this case each received character can be sent on but it can result in lots of short frames. A technique often used is to collect the received data in a buffer and send a packet once a certain length has been received (this optimises the frame lengths so that larger frames are sent rather than lots of short ones when there is a lot of data). However if there are only a few sporadish bytes of received data this causes a proble since they will only be sent when enough has been collected (very long pauses). To correct this a timer is used as well as the buffer. If no received data has been received for a certain amount of time (say 100ms) the buffer will also be sent, no matter how many bytes have been collected.
Working with a buffer length and a timeout it is possible to set these as parameters to acheive efficient throughput/frame size for a certain application - thsi mode of operation (including these set up parameters) is typical for RS232 <-> LAN converter operation.

Another point to note is that when working with binary data USE_XON_OFF must be removed since it will cause the transmitter to blocked on an XOFF (0x13) character reception and only started again on XON (0x11).



Good luck

Regards

Mark