Author Topic: How to use the timer in the uart get data!  (Read 9749 times)

Offline tr111

  • Jr. Member
  • **
  • Posts: 72
    • View Profile
How to use the timer in the uart get data!
« on: September 10, 2007, 10:54:39 AM »
HELLO:
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.

look like this in the char mode :
       while  (fnMsgs(SerialPortID)) {
             Length =   fnRead( SerialPortID, ucInputMessage, BIG_MESSAGE);
                get_buff[ii]=*ucInputMessage;
                //printfk(get_buff[ii]);
               // printfk(ii);
             
                ii++;
               buff_len=ii;
               // timeout=1;
               //printfk(i);
            //  fnEchoInput(ucInputMessage, Length);
              }

     this will be right only the first time ,the second frames arrived will be wrong.Because  I don't to set ii=0 at right time to get the next frames !
    When get data I don't how to use timer to " no received data has been received for a certain amount of time "! How to get the end of the frames!
    In the Dynamic C 8.01 for rabbit it is use this to get data:
       memset(serBuffer,0,sizeof(serBuffer));
       rec_len=serBread( serBuffer, sizeof(serBuffer),SERL_REC_TIME);
       if (rec_len<=0) return;
     the rec_len is the all the frames 's number.then I can use the serBuffer to do what i want!
      if I send the 0x01 0x02 0x03 0x04 ,the rec_len will be 4.
     
« Last Edit: September 10, 2007, 11:02:23 AM by tr111 »

Offline mark

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 3236
    • View Profile
    • uTasker
Re: How to use the timer in the uart get data!
« Reply #1 on: September 10, 2007, 11:21:55 AM »
Hi

Here is an example of using the timer:

Code: [Select]
#define OWN_TASK             MY_TASK

#define INITIALISATION       0
#define ACTIVE               1

#define E_TIMER_SEND_SERIAL  1

#define SEND_LENGTH          20

#define PAUSE_DELAY_TIME     (DELAY_LIMIT)(0.1*SEC)

void fnMyTask(TTASKTABLE *ptrTaskTable)                                  // Task configured to run once at start up and then sleep
{
    static unsigned char ucSerialInput[RX_BUFFER_SIZE];                  // static buffer for collecting UART data
    static int iSerialRxLenth = 0;                                       // length of collected UART data
    static int iTaskState = INITIALISATION;
    static QUEUE_HANDLE SerialPortID;

    QUEUE_HANDLE        PortIDInternal = ptrTaskTable->TaskID;           // queue ID for task input
    unsigned char       ucInputMessage[RX_BUFFER_SIZE];                  // reserve space for receiving messages


    if (INITIALISATION == iTaskState) {                                  // configure interfaces on initialisation
        SerialPortID = fnConfigureAndOpenUART();
        iTaskState = ACTIVE;
    }

    while ( fnRead( PortIDInternal, ucInputMessage, HEADER_LENGTH )) {   // check input queue
        switch ( ucInputMessage[ MSG_SOURCE_TASK ] ) {                   // switch depending on message source
        case TIMER_EVENT:                                                // timer event
            if (E_TIMER_SEND_SERIAL == ucInputMessage[ MSG_TIMER_EVENT ]) {  // pause between characters, send data
                fnWrite(SerialPortID, ucSerialInput, iSerialRxLenth);    // transmit available buffer
                iSerialRxLenth = 0;                                      // reset UART message length counter
            }
            break;
        }
    }

    while (fnRead(SerialPortID, &ucSerialInput[iSerialRxLenth++], 1) != 0) { // collect serial port data
        if (iSerialRxLenth >= SEND_LENGTH) {
            fnWrite(SerialPortID, ucSerialInput, iSerialRxLenth);        // transmit full buffer
            iSerialRxLenth = 0;                                          // reset UART message length counter
            uTaskerStopTimer(OWN_TASK);                                  // stop pause monitor timer
        }
        else {
            uTaskerMonoTimer( OWN_TASK, PAUSE_DELAY_TIME, E_TIMER_SEND_SERIAL );// start monitor timer
        }
    }
}

Each time a characters is received (in character mode) it is saved to a local buffer (ucSerialInput). A timer is started (100ms, with timeout event E_TIMER_SEND_SERIAL) on each character (retriggerable mono-stable). If SEND_LENGTH characters are received, they are sent to the serial port and the pause timer stopped.
If less that SEND_LENGTH characters have been received and the pause monitor timer fires, the timer event causes the available characters to be send.
The result is that if lots of serial data is arriving quickly it will be send in 'packets' of SEND_LENGTH. If there is a pause between characters of more than 100ms, the available number of bytes will be sent after this time.

Regards

Mark

Offline tr111

  • Jr. Member
  • **
  • Posts: 72
    • View Profile
Re: How to use the timer in the uart get data!
« Reply #2 on: September 10, 2007, 04:40:15 PM »
MARK:
      Thank you!