Here is the definition code for those
commands:
#define CMD_PING 0x01
#define CMD_SEND 0x81
#define CMD_DEMO 0x0F
//Take a
//reading
//Send the
//data back
//In demo mode
Figure 5. Sensor board SCI state machine.
a command to do a sonar reading. Another command
tells the board to return the converted distance
measurement (in inches). I included a third command
that will put the sensor board in demo mode which makes
it take a sonar reading every five seconds and display it
on the LCD.
Note that the MSB of the command is set
in the CMD_SEND command; this tells the SCI
state machine that it will be sending data back
to the master.
Many more things can be done with
commands than just this. One I have in mind
for the future is a command to set the device
address to something other than its default
and save it in the EEPROM.
So, how does one create a state machine
to handle the SCI communications? The first
step is to sit down and draw what you think
it would look like. Typically you have too few
states, then too many, then you can trim it to
be just right. I ended up with five states
which you can see in Figure 5. State 0, idle is where the
state machine sits when nothing is happening. As soon as
a clock is detected then it transitions to state 1, AddCmd.
In this state, the device address and command are clocked
in and checked. If the address isn’t for “me,” then I sit
in this state and discard the next 16 bits. Otherwise, I
LISTING 1. SCI state machine code.
#int_global
void isr(void)
/* I will handle the pre/post amble for the ISR
because I know which memory locations I’ll
use. Incoming commands are read in, as would
be any incoming data. The main program
would determine what to do with the data.
Whenever a command comes in that has bit 7
(msb) of the command byte set the ISR will
transmit back whatever is in the data buffer.
The main program will have no choice in the
matter, it had better have the data in
myData, because whatever IS there will be
sent back!
*/
{
#asm
//store current state of processor
MOVWF save_w
SWAPF status,W
MOVWF save_status
SWAPF FSR,W
MOVWF save_FSR
BCF status,5
#endasm
//Set to page 0 for SFR’s
set_timer0(0);
16 SERVO 06.2009
//start the timeout clock ticking.
switch (spiState) {
//Kick start the state machine
case S_IDLE:
bCount = 0; //clear count
spiState = S_ADDRCMD; //next state
case S_ADDRCMD:
if (bCount <8) { //Target address
shift_right(&addrIn,1,
input(SDA));
//Get the current data bit
}
else if(bCount < 16) { //Command
shift_right(&cmdIn,1,
input(SDA));
}
if (bCount == 15) { //cmd & addr
if (addrIn == myAddr) { // Me?
if ((cmdIn & 0x80) != 0) {
//next state is data out
spiState = S_DOUT;
dataOut = myData;
}
else {
// next state is 16 bits
// data in
spiState = S_DIN;
}