Hello,
The following example code shows how the SPI module might be used, as previously proposed. There are two functions, one for frequent execution within the main loop, for processing all six steppers, and another for setting a new destination position for a specific stepper.
/****************************************************************************** File: Unipolar.h UNIPOLAR STEPPER MOTOR POSITION CONTROL ******************************************************************************/#ifndef _UNIPOLAR_H#define _UNIPOLAR_H#include "derivative.h"// Adjust to suit GPIO pin used.#define STROBE_HI PTDDD_PTDDD0 = 1; PTDD_PTDD0 = 1#define STROBE_LO PTDDD_PTDDD0 = 1; PTDD_PTDD0 = 0#define STEP_DELAY 5 // 5ms delay between steps (200 steps/s)// Stepper motor control structure:struct stepctrl { byte phase; int stepcount; byte timeout;};union SPI_buf { byte B[3]; // Individual bytes for SPI send dword D;};/******************************************************************************/// Function prototypes:// Stepper motor control update - to be frequently called within main loopvoid control_update( void);// Setup motor destinationvoid set_destination( byte id, // 'A' to 'F' -> motor number 0 - 5, forward direction // 'a' to 'f' -> motor number 0 - 5, reverse direction int steps); // number of steps#endif /* _UNIPOLAR_H */
/****************************************************************************** File: Unipolar.c UNIPOLAR STEPPER MOTOR POSITION CONTROL ******************************************************************************/#include "Unipolar.h"#include "SPI.h" // SPI_send() macro definition#include "TPM.h" // Declaration for 'tflag'// Static variables:static struct stepctrl motor[6]; // Array of structuresstatic union SPI_buf mcontrol;// Stepper motor control sequence table:const byte motor_phase[] = { 0x09, 0x0A, 0x06, 0x05 };/******************************************************************************/// Stepper motor control update// To be frequently called within the main loop.void control_update( void){ byte i, c, s; if (tflag) { // Ready for further processing tflag = 0; // Clear timing flag for (i = 0; i < 6; i++) { // Process each stepper motor if (motor[i].timeout == 0) { // Ready for next step if (motor[i].stepcount) { // Motor needs to step motor[i].timeout = STEP_DELAY; // Delay to next step after this one if (motor[i].stepcount > 0) { // Forward step motor[i].stepcount--; c = (++motor[i].phase) & 0x03; // Next phase } if (motor[i].stepcount < 0) { // Reverse step motor[i].stepcount++; c = (--motor[i].phase) & 0x03; // Next phase } s = (byte)(4 * i); // Shift value mcontrol.D &= ~(0x0F << s); // Clear motor control value mcontrol.D |= (motor_phase[c] << s); // Place new control value } } else motor[i].timeout--; } // Update control for all motors SPI_send( mcontrol.B[0]); SPI_send( mcontrol.B[1]); SPI_send( mcontrol.B[2]); STROBE_HI; STROBE_LO; }}/******************************************************************************/// Setup motor destination// id - 'A' to 'F' represents motor number 0 - 5, forward direction// - 'a' to 'f' represents motor number 0 - 5, reverse direction// steps - number of stepsvoid set_destination( byte id, int steps){ if (id >= 'A' && id <= 'F') { id -= 'A'; // Value 0 - 5 motor[id].stepcount += steps; } if (id >= 'a' && id <= 'f') { id -= 'a'; // Value 0 - 5 motor[id].stepcount -= steps; }}
The code assumes a 1 millisecond tick rate from the TPM1 module (software output compare mode), and provides 5 millisecond spacing between successive steps.
I do not understand the format of your data packets, particularly how the number of steps is represented. If by a sequence of ASCII digits, these would need to be separately converted to a binary value, for use by the set_destination() function.
I could not work out your intent with the handler for the SCI2 received data. I would tend to place the incoming data into a FIFO buffer, and then parse the packet data from within the buffer, from outside the ISR handler.
Regards,
Mac