AsynchroSerial
 
Component AsynchroSerial
Asynchronous serial communication
Component Level: High
Typical Usage:
(Examples of a typical usage of the component in user code. For more information please see the page Component Code Typical Usage.)

All the following examples suppose the component name is "AS1".
There are several typical usage modes:

  • Without interrupts

    The simplest mode of the AsynchroSerial component is setting with Interrupt service/event disabled (so called polling mode). The code in this mode is very small and simple. However it is outweighed by the necessity to regularly check for incoming data and wait for transmitted data to complete.

    The following example demonstrates a simple "Hello world" program. The program sends text "Hello world" and then waits until a character 'e' is received to send some other data.

     MAIN.C
    
    char message[] = "Hello world";
    AS1_TComData ch;                                         // TComData type is defined in the AS1.h header file
    byte i, err;
    void main(void)
    {
      .
      .
      .
      for(i = 0; i < sizeof(message); i++) {
        while(AS1_SendChar((byte)message[i]) != ERR_OK) {}   // trying to send a character until the SendChar method returns ERR_OK
      }
    
      ch = 0;
      do {                                                   // execute the loop until the character 'e' is received
        err = AS1_RecvChar(&ch);                             // check if a character is received
      } while((err != ERR_OK) && (ch != 'e'));               // test if the 'e' character was received
    
      while(AS1_SendChar((byte)'B') != ERR_OK) {}            // trying to send 'B' until success
      while(AS1_SendChar((byte)'Y') != ERR_OK) {}            // trying to send 'Y' until success
      .
      .
      .
      for(;;) {} 
    }
    
    

  • Using interrupts with events

    To avoid the necessity to continually check for incoming data the Interrupt service/event property can be enabled (so called interrupt mode). In this mode the AsynchroSerial component uses the capability of the cpu to interrupt the flow of the program to execute a different part of code. The hardware of the asynchroserial module may generate the interrupt upon various occasions - when a new character is received, when sending of a character is completed, when a receive error is detected, etc.

    The events of the AsynchroSerial component are set of call-back functions, which are automatically invoked from the interrupt service routine. Because the body of the event function is defined by user it is possible to react immediately without wasting time in waiting loops.

    The following example demonstrates usage of the OnRxChar event. The event is invoked when a character is received. The example implements simple repeater - when OnRxChar event is invoked the received character is read and sent back.

     EVENTS.C
    
    void AS1_OnRxChar(void)
    {
      AS1_TComData ch;                         // TComData type is defined in the AS1.h header file
    
      //Read received character and send it if no error is detected
      if(AS1_RecvChar(&ch) == ERR_OK)
        AS1_SendChar(ch);
    
    }
    
    

  • Usage of block transfer

    When in the interrupt mode (Interrupt service/event property is enabled) the AsynchroSerial component can be configured to define and use internal circular buffers to store received data or data for transmit. Instead of sending/receiving individual bytes user can work with blocks of data.

    Send methods (SendChar and SendBlock) store data into the internal buffer. When the transmitter becomes empty one character from the internal buffer is sent, until the internal buffer is empty.

    All received characters are placed into the internal buffer. Methods RecvChar or RecvBlock can be used to read later the data from the internal buffer.

    The following program demonstrates a typical usage of block transfer functions. In this example the component will be used to receive and send fixed size packets of data. The structure of the packet is - 1B header, 1B command, 2B data, 1B checksum

    Suppose the following component settings:

    Definition of the packet structure:

    struct {
      byte Header;
      byte Command;
      word Data;
      byte Checksum;
    } message;
    

    A data packet fills the receive buffer, so the OnFullRxBuf event is invoked when a data packet is received. The received packet may be read using the RecvBlock method.

    Example of the OnFullRxBuf event code:

      void AS1_OnFullRxBuf(void)
      {
        word Received;
        byte err;
        err = AS1_RecvBlock((byte*)&message, sizeof(message), &Received);
        ....
      }
    
    To send a data packet the SendBlock method may be used:
    byte err;
    word Sent;
    void main(void)
    {
      ...
      message.Header = 0x55;
      message.Command = 0x01;
      message.Data = 0x0A0B;
      message.Checksum = message.Header + message.Command + (message.Data & 0x00ff) + (message.Data >> 8);
      err = AS1_SendBlock((byte*)&message, sizeof(message), &Sent);
      ....
    }
    
    
    

  • Receive error detection

    The hardware of an asynchroserial module usually supports several methods of error detection - parity error, overrun error, etc. The AsynchroSerial component contains basically two ways how to obtain information that an error has been detected:

    • Return value of a receive method (RecvChar or RecvBlock) - the method returns an error value ERR_COMMON in case that an receive error has been detected since the last successful call or during execution of the method
    • OnError event - this event is invoked immediately after a receive error has been detected

    Both methods inform that an error has been detected, but no information about specific error type (if it is parity error, framing error, etc.). This information is provided by the GetError method.

    In the polling mode (the Interrupt service/event property is disabled) the only way to detect a receive error is the return value of the RecvChar method. The following example demonstrates typical error detection scheme in this mode.

     MAIN.C
    
    AS1_TComData ch;                         // TComData type is defined in the AS1.h header file
    byte err;
    AS1_TError error;                       // TError type is defined in the AS1.h header file
    void main(void)
    {
      .
      .
      .
      do {
        err = AS1_RecvChar(&ch);            // test if a character is received
      } while (err != ERR_EMPTY);           // execute the loop until a character is received
      
      if (err = ERR_COMMON) {               // if an error was detected
        AS1_GetError(&error);               // determine the type of error
        if (error.ErrName.Parity) {
          //Parity error
        } else if (error.errName.Framing) {
          //Framing error
        } else if ...
      }
    }
    

    When in the interrupt mode Interrupt service/event property is enabled) the preferred method to detect a receive error is to use the OnError event. The RecvChar/RecvBlock methods also return information about the receive error, but this information is redundant and should not be used when OnError method is enabled. Please note that the GetError method returns information which communication errors happened since the last call of this method. As a result when GetError method is already called in the OnError event then call after e.g. RecvChar method will not return which error has occurred.

    The following example demonstrates typical error detection scheme in the interrupt mode.

     EVENTS.C
    
    void AS1_OnError(void)
    {
      AS1_TError error;        // TError type is defined in the AS1.h header file
      
      AS1_GetError(&error);    // determine the type of error
      if(error.errName.Parity) {
        //Parity error
      } else if(error.errName.Framing){
        //Framing error
      } else if ... 
    }
    
    

  • Break character detection

    Break character consists of several zeros and has no start bit nor stop bit. Depending on configuration of the asynchroserial module the break character may consist of 10 or more consecutive zeros. To enable handling of the break character the Break signal property must be enabled.

    The behaviour of AsynchroSerial component depends on the setting of the Interrupt service/event property. In the polling mode the RecvChar method returns error code ERR_BREAK when break character is detected. In the interrupt mode, when a break character is detected the OnBreak event is invoked (if enabled) and the receive methods (RecvChar/RecvBlock) return error code ERR_COMMON.

    In the interrupt mode when OnBreak event is not enabled either GetError or GetBreak method can be used to get information if break character has been detected.

    Example of using GetError method to test break character reception (event OnBreak disabled):

     EVENTS.C
    
    AS1_TComData ch;                        // TComData type is defined in the AS1.h header file
    
    void AS1_OnRxChar(void)
    {
      byte err;
      AS1_TError error;                     // TError type is defined in the AS1.h header file
    
      err = AS1_RecvChar(&ch);              // receive a character
      
      if (err = ERR_COMMON) {               // if an error was detected
        AS1_GetError(&error);               // determine the type of error
        if (error.Break) {
                    // break character has been received
        } else {
                    // a receive error detected
        }
      }
    }
    

    Example of using GetBreak method to test break character reception (event OnBreak disabled):

     EVENTS.C
    
    AS1_TComData ch;                        // TComData type is defined in the AS1.h header file
    
    void AS1_OnRxChar(void)
    {
      boll break;
      AS1_TError error;                     // TError type is defined in the AS1.h header file
    
      err = AS1_RecvChar(&ch);              // receive a character
      
      if (err = ERR_COMMON) {               // if an error was detected
        AS1_GetBreak(&break);
        if (break)) {
                    // break character has been received
        } else {
                    // a receive error detected
        }
      }
    }
    

    Note: When both the GetBreak and GetError methods are enabled, the GetBreak method has to be called before the GetError method, because both methods use the same internal flags. Calling GetError clears this flag so the GetBreak method will not return correct information.


  • Transfer using DMA
    The next typical usage of this component is a communication using DMA transfer. Interrupts can be enabled or disabled. This typical usage can be used by the derivatives with a DMA controller.
     MAIN.C
    AS1_TComData ch;                        // TComData type is defined in the AS1.h header file
    AS1_TError error;                       // TError type is defined in the AS1.h header file
    void main(void)
    {
    
      //Start DMA request (DMA request have to be specified first!)
      AS1_RecvChar(&ch);
    
      //Wait for any character
      while(AS1_GetCharsInRxBuf() == 0);
    
      //Read the last communication errors
      AS1_GetError(&error)
      if(error.err == 0)
        //Send the last received character if no error is detected
        AS1_SendChar(ch);
      else
        if(error.errName.Parity)
          //Parity error
        else if(error.errName.Framing)
          //Framing error
        .
        .
        .
    }
    
     EVENTS.C
    
    void AS1_OnFullRxBuf(void)
    {
      //Requested data have been received. DMA transfer is finished.
    }
    
    void AS1_OnFreeTxBuf(void)
    {
      //Requested data have been sent. DMA transfer is finished.
    }
    
    

  • Changing baud rate during run-time

    The AsynchroSerial component allows user to change baud rate value at runtime.

    In the timing dialog of the Baud rate property set runtime setting type to "from list of values". Then it is possible to enter up to 16 different values. The SetBaudRateMode method is used to select the actual baud rate. The component generates a special symbolic constant for each baud rate value defined (see SetBaudRateMode), e.g. AS1_BM_2400BAUD, AS1_BM_4800BAUD, etc. The constant is used as a parameter of the SetBaudRateMode method.

    
    void main(void) {
      ...
      AS1_SetBaudRateMode(AS1_BM_2400BAUD)
      ...
      ...
      AS1_SetBaudRateMode(AS1_BM_4800BAUD)
      ..
    }
    

  • Version specific information for Freescale HC08 derivatives featuring the Enhanced SCI peripheral.
    Baud rate detection

    The Enhanced SCI module of these CPUs supports automatic baud rate detection. The component contains special methods which support the mechanism.

    Example:

    
    byte status, err;
    void main(void)
    {
      ...
      err = AS1_ClearArbiterFlags();            /* Clear all flags of the ESCI arbiter */
      err = AS1_ResetArbiterCounter();          /* Reset arbitration counter */
      err = AS1_SetFallingEdgesMeasurement();   /* Start measurement in the falling edge mode */
      do {
        err = AS1_GetArbiterStatus(&status);    /* Get status of the ESCI arbiter */
      } while(!(status & 0x04));                /* Wait while the measurement is not finished */
      err = AS1_AdjustBaudRate();               /* Adjust the baud rate according to the measured value */
      AS1_SendChar(0x55);                       /* Send a character to confirm the baud rate */
      ...
    }