|
|
|
Component
AsynchroSerial
Asynchronous serial communication
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 */
...
}
|