📄 stepper.c
字号:
//-----------------------------------------------------------------------------
// Stepper.c
//-----------------------------------------------------------------------------
// Copyright 2003 Silicon Laboratories, Inc.
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <c8051f300.h> // include SFR declarations
//-----------------------------------------------------------------------------
// defines and typedefs
//-----------------------------------------------------------------------------
#define SYSCLK 24500000 // SYSCLK frequency in Hz
#define BAUDRATE 57600 // Baud rate of UART in bps
#define READ_BUFFER_SIZE 16 // change UART receive buffer size here
#define WRITE_BUFFER_SIZE 16 // change UART receive buffer size here
#define ON 0 // LED is active low
#define OFF 1
#define ACCELERATE 3 // motor states
#define SLEWING 2
#define DECELERATE 1
#define DONE 0
#define INIT_TZERO 80 // Tzero used at start-up and with
// manual mode, change value here for
// different stepper motors
typedef union // union used for writing to TL0 & TH0
{
struct
{
unsigned char hi;
unsigned char lo;
} b;
unsigned int w;
}udblbyte;
//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
//
// half step stepper motor step pattern
// transistors are in order B-,B+,A-,A+
//
// 0x01 = 0001
// 0x05 = 0101
// 0x04 = 0100
// 0x06 = 0110
// 0x02 = 0010
// 0x0A = 1010
// 0x08 = 1000
// 0x09 = 1001
const unsigned char code StepPattern[8]=
{0x01,0x05,0x04,0x06,0x02,0x0A,0x08,0x09};
//
// stepper motor linear velocity profile
// 255 * [sqrt(n+1)-sqrt(n)]
// n = 0 to 255
//
const unsigned char code StepTable[256]=
{
0xFF, 0x69, 0x51, 0x44, 0x3C, 0x36, 0x32, 0x2E,
0x2B, 0x29, 0x27, 0x25, 0x24, 0x22, 0x21, 0x20,
0x1F, 0x1E, 0x1D, 0x1C, 0x1C, 0x1B, 0x1A, 0x1A,
0x19, 0x19, 0x18, 0x18, 0x17, 0x17, 0x17, 0x16,
0x16, 0x16, 0x15, 0x15, 0x15, 0x14, 0x14, 0x14,
0x14, 0x13, 0x13, 0x13, 0x13, 0x12, 0x12, 0x12,
0x12, 0x12, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E, 0x0E,
0x0E, 0x0E, 0x0E, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0A, 0x0A,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
0x0A, 0x0A, 0x0A, 0x09, 0x09, 0x09, 0x09, 0x09,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07, 0x07
};
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
//
// main and user interface functions
void SYSCLK_Init (void); // initialize port pins and crossbar
void PORT_Init (void); // initialize system clock and watchdog
void Timer_Init (void); // initialize timer for Motor and UART
void UART_Init (void); // initialize UART
void Motor_Init(void); // initialize Motor variables
void doneMsg(void); // display done message
void error(void); // display error message
void delay (void); // delay used for position updating
void INT0_ISR (void); // external interrupt used for SW2
//
// stepper motor control functions
void move (unsigned int);
void Timer_ISR (void);
unsigned int MUL8x8(unsigned char, unsigned char);
//
// BUFFERED UART FUNCTION PROTOTYPES
//--Top Level - User Functions ------------------------------------------------
// put a string into transmit buffer, used to display text messages
void puts (char *);
// converts a 16 bit number to a string of ASCII characters
// and stores the characters into the transmit buffer
void putuint(unsigned int);
// converts an 8 bit number to a string of ASCII characters
// and stores the characters into the transmit buffer
void putuchar(unsigned char);
// retrieves ASCII characters from the receiver buffer
// and converts a string of digits into an 8-bit number
unsigned char getuchar(void);
// retrieves ASCII characters from the receiver buffer
// and converts a string of digits into an 16bit number
unsigned int getuint(void);
void newline(void); // outputs carriage return & line feed
//----------Middle Level - Primitive User Functions ---------------------------
// retrieves one character from the receive buffer using readc and echoes
// the character to the transmit buffer
char getc (void);
// stores one character into the transmit buffer using writec
void putc (char);
void readClear(void); // clears read buffer
void writeClear(void); // clears write buffer
//----------------Lowest level - Hardware access functions --------------------
char readc (void); // pulls one character directly
// from the receive buffer
void writec (char); // writes one character directly
// to the transmit buffer
//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------
//
// user interface variables
sbit LED = P0 ^ 6; // bit set high to turn LED on
//
// Stepper Motor Variables
unsigned int Position; // current motor position
unsigned char TableIndex; // index for stepper motor table
unsigned char MaxTableIndex; // maximum index for desired profile
unsigned int SlewCount; // down counter for slewing phase
unsigned char Tzero; // initial period, sqrt(2/alpha)
unsigned char PatternIndex; // index for step pattern, modulus 8 counter
bit Forward; // 1 for forward, 0 for reverse
bit doneFlag; // done flag used for Timer ISR handshake
unsigned char motorState; // motor state variable
//
// UART Global Variables
// UART receiver buffer
char idata readBuffer[READ_BUFFER_SIZE];
// UART transmitter buffer
char idata writeBuffer[WRITE_BUFFER_SIZE];
unsigned char writeIndex; // points to next free write byte
unsigned char readIndex; // points to next free read byte
unsigned char writeCount; // number of bytes in write buffer
unsigned char readCount; // number of bytes in read buffer
bit TX_Idle; // flag set when TX buffer is empty
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
//
// The main function initializes everything and then services the user
// interface. The user interface parses characters from the UART and
// executes basic commands. There are three interrupt service routines
// which function in the background - The Timer_ISR which controls the
// stepper motor; The UART_ISR which moves characters to/from the buffers;
// and the INT0_ISR that handles the pushbutton switch commands.
//
void main (void)
{
char theChar; // the character to be parsed
unsigned int newP; // new position to move to
SYSCLK_Init (); // Init system clock to 24.5MHz
PORT_Init (); // Init crossbar and GPIO
Timer_Init(); // Init T0 for stepper motor and
// T1 for Baud rate
UART_Init(); // Init UART
Motor_Init(); // Init motor global variables
EA = 1; // enable global interrupts
putc('>'); // display prompt
while(1) // main loop
{
if(LED==ON) // display position while moving
{
putuint(Position); // display position
puts(" "); // blank out trailing characters
putc('\r'); // overwrite line by not using linefeed
delay(); // delay sets display update rate
}
else
{
if(doneFlag)
{
doneMsg(); // if done display message
}
theChar = getc(); // get character to be parsed
switch(theChar) // parse character
{
case '\r': // if return character
putc('\n'); // linefeed with no carriage return
putc('>'); // display prompt
break;
case 'p': // p for new position
newP = getuint(); // get number as unsigned integer
newline();
puts("Moving..."); // display moving status indicator
newline();
puts("Position:"); // display position tag
newline();
move(newP); // initiate move to new position
break;
case 'a': // a for change acceleration
Tzero = getuchar(); // get number as unsigned character
newline();
puts("Acceleration:"); // confirm acceleration changed
newline();
putuint(Tzero); // display new acceleration
newline();
putc('>');
break;
case 's': // s for display status
newline();
puts("Position:"); // display position tag
newline();
putuint(Position); // display position value
newline();
puts("Acceleration:"); // display acceleration tag
newline();
putuint(Tzero); // display acceleration value
newline();
putc('>'); // display prompt
break;
default:
error(); // display error message
}
}
}
}
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use the internal 24.5MHz
// oscillator as its clock source. Also enables missing clock detector reset.
//
void SYSCLK_Init (void)
{
OSCICN = 0x07; // set SYSCLK to OSC frequency
RSTSRC = 0x04; // enable missing clock detector
PCA0MD &= ~0x40; // disable watchdog timer
}
//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports.
// P0.0 - A+
// P0.1 - A-
// P0.2 - B+
// P0.3 - B-
// P0.4 - Txd
// P0.5 - Rxd
// P0.6 - LED
// P0.7 - C2D/Switch
//
void PORT_Init (void)
{
XBR0 = 0x4F; // Crossbar Register 1
XBR1 = 0x03; // Crossbar Register 2
XBR2 = 0x40; // Crossbar Register 3
P0 = 0xC0; // Turn off MOSFETs, Set P0.6 & P0.7
P0MDOUT = 0x5F; // Output configuration for P0
P0MDIN = 0xFF; // Input configuration for P0
IP = 0x02; // T0 high priority, others low
IT01CF = 0x70; // use P0.7 for INT1
IT1 = 1; // edge sensitive interrupt
IE1 = 0; // clear external interrupt
EX1 = 1; // enable external interrupt 1
}
//-----------------------------------------------------------------------------
void Timer_Init (void)
{
CKCON = 0x12; // T1 uses sysclk, T0 uses /48,
TMOD = 0x21; // T1 mode 2, T0 mode 1
}
//-----------------------------------------------------------------------------
void UART_Init(void)
{
SCON0 = 0x10; // mode 1, 8-bit UART, disable receiver
TH1 = 0x2C; // set Timer1 reload value for 57600
TR1 = 1; // start Timer1
TX_Idle = 1; // set idle flag
readClear(); // zero out read buffer
writeClear(); // zero out write buffer
ES0 = 1; // enable UART interrupt
}
//-----------------------------------------------------------------------------
void Motor_Init()
{
Tzero = INIT_TZERO; // initialize acceleration
Position = 0x0000; // zero position
LED = OFF; // turn off LED
doneFlag = 0; // clear done flag
}
//-----------------------------------------------------------------------------
void error (void) // used by main
{
newline();
puts("invalid character"); // display error message
newline();
putc('>');
}
//-----------------------------------------------------------------------------
void delay (void) // used by main
{
unsigned char i,j;
for(i=255;i>0;i--) // simple delay for display update
{
for(j=255;j>0;j--);
}
}
//-----------------------------------------------------------------------------
void doneMsg(void) // called from Timer_ISR
{
putc('\r'); // overwrite final position
putuint(Position); // display int as string
newline();
puts("done!"); // indicate move complete
newline();
putc('>'); // display prompt
doneFlag=0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -