Continuing with my treatise on how to control your robot modules if your robot brain is a PC computer running any sort of High Level language and allowing the smaller modules to perform menial tasks, I am attaching below the code that I use on my MSP430 applications to take care of the byte reception and command execution. It is in C, so I am thinking a good deal of it may be ported to other microcontrollers (except for the configuration registers and the interrupt vectors, of course).
//****************************************************************************//
// MSP430 with an UART resource code to receive x number of bytes
// This code was taken from AE MSP430F1612 RTOS
//****************************************************************************//
//----------------------------------------------------------------------------//
// Code from COMM.h
//----------------------------------------------------------------------------//
//****************************************************************************//
// Communication Engine Globals
// To change how many bytes are received from the PC, modify SERIAL_BUFFER_LENGTH
// To change how many bytes are returned to the PC, modify SERIAL_OUT_LENGTH
//****************************************************************************//
#define SERIAL_BUFFER_LENGTH 5
#define SERIAL_OUT_LENGTH 3
extern char SerialPointer;
extern char SerialBuffer[SERIAL_BUFFER_LENGTH];
extern char SerialOutPointer;
extern char SerialOutBuffer[SERIAL_OUT_LENGTH];
extern bool MessageComplete;
extern int CommTimeOut;
//----------------------------------------------------------------------------//
// Code from COMM.cpp MSP430F1612 Interrupt Service Routines servicing UART0
//----------------------------------------------------------------------------//
char SerialPointer;
char SerialBuffer[SERIAL_BUFFER_LENGTH];
char SerialOutBuffer[3];
char SerialOutPointer;
bool MessageComplete;
int CommTimeOut;
//****************************************************************************//
// Receive Bytes ISR. When a byte is received, it is shifted into the Serial
// Buffer. When SERIAL_BUFFER_LENGTH bytes have been received, the MessageComplete
// flag is raised. TASK0 will use this flag to determine if a new command has
// arrived. Serial pointer is cleared once the total number of bytes have been
// received.
//****************************************************************************//
#pragma vector=USART0RX_VECTOR
__interrupt void USART0_Receive(void)
{
SerialBuffer[SerialPointer] = RXBUF0;
SerialPointer += 1;
if (SerialPointer == SERIAL_BUFFER_LENGTH)
{
SerialPointer = 0;
MessageComplete = true;
}
}
//****************************************************************************//
// Transmit Bytes ISR. ISR transmit bytes on the Serial Out Buffer until
// SERIAL_OUT_LENGTH bytes have been sent. Once all bytes have been sent, the
// interrupt is disabled. Interrupt is enabled only when a command has been
// executed.
//****************************************************************************//
#pragma vector=USART0TX_VECTOR
__interrupt void USART0_Transmit(void)
{
SerialOutPointer += 1;
TXBUF0 = SerialOutBuffer[SerialOutPointer];
if (SerialOutPointer == SERIAL_OUT_LENGTH - 1)
{
IE1 &= ~UTXIE0;
}
}
//----------------------------------------------------------------------------//
// Code from Task0.cpp Code executing received commands
//----------------------------------------------------------------------------//
//****************************************************************************//
// When a command has been received (MessageComplete = true), the message is
// decoded and executed. First byte is used as an opcode. Subsequent bytes are
// used as data for the particular opcode. SerialOutBuffer is prefilled with
// 1-0-0 but can be modified on a per opcode basis as a troubleshooting tool.
// After command is executed, MessageComplete flag is cleared and transmitter
// is enabled.
//****************************************************************************//
void Task0(void)
{
if (MessageComplete)
{
SerialOutBuffer[0] = 1;
SerialOutBuffer[1] = 0;
SerialOutBuffer[2] = 0;
switch(OPCODE)
{
// Read Memory [Opcode = 0x0 ] [ Address Hi ] [ Address Lo ] [ Not Used ] [ Not Used ]
case (READ_MEM):
int * MyPointer;
int Address;
Address = (SerialBuffer[1]*256 + SerialBuffer[2]);
MyPointer = (int *) Address;
SerialOutBuffer[1] = (*MyPointer & 0xFF00) >> 8;
SerialOutBuffer[2] = (*MyPointer & 0xFF);
break;
// Write Memory [Opcode = 0x1 ] [ Address Hi ] [ Address Lo ] [ Data Hi ] [ Data Lo ]
case (WRITE_WMEM):
int Data;
Address = (SerialBuffer[1]*256 + SerialBuffer[2]);
Data = (SerialBuffer[3]*256 + SerialBuffer[4]);
MyPointer = (int *) Address;
*MyPointer = Data;
break;
}
MessageComplete = false;
SerialOutPointer = 0;
TXBUF0 = SerialOutBuffer[SerialOutPointer];
IE1 |= UTXIE0;
}
}