#include <msp430x14x.h>
#define DCO_FREQ 1000000 // DCO frequency
#define ONE_SEC_CNT 512 // Number of WDT interrupts in 1 second
#define DEBOUNCE_CNT 0x05 // (1/512)*5 = ~10 msec debounce
#define DIR_MASK 0x01 // 0x01 is clockwise, 0x00 is counter-clockwise
#define STEP_MASK 0x02 // 0x00 is full-stepping, 0x02 is half-stepping
#define MOTION_MASK 0x04 // 0x00 is continuous, 0x04 is single-step
#define DEFAULT_RATE 0x8000 // Default stepping rate
#define MIN_RATE 0x8000 // Minimum stepping rate
#define MAX_RATE 0x0800 // Maximum stepping rate
// Default state is full-stepping, clockwise, continuous
unsigned char state = 1; // State variable
unsigned char stepIndex = 0; // State table index
unsigned int rate = DEFAULT_RATE; // Stepping rate
unsigned char change_rate_flag = 0; // Flag indicating rate change
unsigned int max_rate = MAX_RATE; // Maximum stepping rate
unsigned int min_rate = MIN_RATE; // Minimum stepping rate
unsigned int SW[4];
void sys_init(void);
void Set_DCO(unsigned long freq);
void timerA_Init(void);
void uart0_Init(void);
void wdt_Init(void);
void toggle_stepping_mode(void);
void increase_stepping_rate(void);
void decrease_stepping_rate(void);
void toggle_motion(void);
void toggle_direction(void);
//定义串口操作变量
char nRev_UART0; // 串口 0 的接收标志
char UART0_TX_BUF[10]; // 串口 0 的发送缓冲区
char UART1_RX_Temp[10];
char UART0_RX_BUF[10]; // 串口 0 的接收缓冲区
int nTX0_Len;
int nRX0_Len;
int nRX0_Len_temp;
char nTX0_Flag;
int nSend_TX0;
// 整步状态表A
static const unsigned char fullStepA[] =
{
0x00,
0x00,
0x01,
0x01
};
// 半步状态表B
static const unsigned char fullStepB[] =
{
0x01,
0x00,
0x00,
0x01
};
// 半步状态表A
static const unsigned char HalfStepA[] =
{
0x01, // 001 1
0x06, // 110 2
0x00, // 000 3
0x00, // 000 4
0x00, // 000 5
0x07, // 111 6
0x01, // 001 7
0x01 // 001 8
};
// 逆时钟、半步状态表B
static const unsigned char CcwHalfStepB[] =
{
0x01, // 001 1
0x01, // 001 2
0x01, // 001 3
0x06, // 110 4
0x00, // 000 5
0x00, // 000 6
0x00, // 000 7
0x07 // 111 8
};
// 顺时钟、半步状态表B
static const unsigned char CwHalfStepB[] =
{
0x00, // 000 1
0x00, // 000 2
0x00, // 000 3
0x07, // 111 4
0x01, // 001 5
0x01, // 001 6
0x01, // 001 7
0x06 // 110 8
};
void main(void)
{
int i;
// 停止WDT
WDTCTL = WDTPW + WDTHOLD;
sys_init();
_EINT();
for(;;)
{
if(nRev_UART0 == 1)
{
nRev_UART0 = 0;
for(i = 0;i < nRX0_Len;i++) UART1_RX_Temp[i] = UART0_RX_BUF[i];
if((UART1_RX_Temp[0] == 'A') && (UART1_RX_Temp[1] == 'T'))
{
UART0_TX_BUF[0] = 'O';
UART0_TX_BUF[1] = 'K';
UART0_TX_BUF[2] = 13;
nTX0_Len = 3;
switch(UART1_RX_Temp[2])
{
case 'D': // 方向
toggle_direction();
break;
case 'C': // 运动模式
toggle_motion();
break;
case 'M': // 步进模式
toggle_stepping_mode();
break;
case 'F': // 增加速率
increase_stepping_rate();
break;
case 'S': // 降低速率
decrease_stepping_rate();
break;
default: break;
}
}
else
{
UART0_TX_BUF[0] = 'E';
UART0_TX_BUF[1] = 'R';
UART0_TX_BUF[2] = 'O';
UART0_TX_BUF[3] = 'R';
UART0_TX_BUF[4] = 'R';
UART0_TX_BUF[5] = 13;
nTX0_Len = 6;
}
// 设置中断标志,进入发送中断程序
IFG1 |= UTXIFG0;
nRX0_Len = 0;
}
}
}
void sys_init(void)
{
// 设置下降沿触发中断
P1IES = 0x0f;
P1IFG = 0x00;
P1IE = 0x0f;
// 设置 P2.3,2,1,0 为输出
// 设置 P3.3,2,1,0 为输出
P2OUT = 0x00;
P3OUT = 0x00;
P2DIR |= 0x0f;
P3DIR |= 0x0f;
// 设置DCO
Set_DCO(DCO_FREQ);
// 初始化 Timer A
timerA_Init();
// 初始化 UART0
uart0_Init();
// 初始化 WDT
wdt_Init();
}
void Set_DCO(unsigned long freq)
{
unsigned int clkCnt;
unsigned int numDcoClks;
unsigned int prevCnt = 0;
// ACLK = LFXT1CLK/8 = 4096 Hz
BCSCTL1 |= DIVA_3;
numDcoClks = freq/4096;
TACCTL2 = CM_1 + CCIS_1 + CAP;
TACTL = TASSEL_2 + MC_2 + TACLR;
while(1)
{
while( !(TACCTL2 & CCIFG) )
{
}
TACCTL2 &= ~CCIFG;
clkCnt = TACCR2 - prevCnt;
prevCnt = TACCR2;
if( numDcoClks == clkCnt )
{
break;
}
else if( clkCnt > numDcoClks )
{
DCOCTL--;
if( DCOCTL == 0xFF )
{
if( BCSCTL1 & 0x07 )
{
BCSCTL1--;
}
else
{
break;
}
}
}
else
{
DCOCTL++;
if( DCOCTL == 0x00 )
{
if( (BCSCTL1 & 0x07) != 0x07 )
{
BCSCTL1++;
}
else
{
break;
}
}
}
}
// ACLK = LFXT1CLK/1 = 32768 Hz
BCSCTL1 &= ~DIVA_3;
TACCTL2 = 0;
TACTL = 0;
}
void wdt_Init(void)
{
// 设置时钟源为ACLK,1秒内产生512此
WDTCTL = WDTPW + WDTTMSEL + WDTCNTCL + WDTSSEL + WDTIS0 + WDTIS1;
}
void uart0_Init(void)
{
//将寄存器的内容清零
U0CTL = 0X00;
//数据位为8bit
U0CTL += CHAR;
U0TCTL = 0X00;
//波特率发生器选择ACLK
U0TCTL += SSEL0;
//波特率为9600
UBR0_0 = 0X03;
UBR1_0 = 0X00;
UMCTL_0 = 0x4A;
//使能UART0的TXD和RXD
ME1 |= UTXE0 + URXE0;
//使能UART0的RX中断
IE1 |= URXIE0;
//使能UART0的TX中断
IE1 |= UTXIE0;
//设置P3.4为UART0的TXD
P3SEL |= BIT4;
//设置P3.5为UART0的RXD
P3SEL |= BIT5;
//P3.4为输出管脚
P3DIR |= BIT4;
}
void timerA_Init(void)
{
TACCR0 = rate;
TACCTL0 = CCIE;
TACTL = TASSEL_2 + MC_1 + TACLR;
}
interrupt [TIMERA0_VECTOR] void TimerA_ISR(void)
{
unsigned char index;
unsigned char p2 = 0;
unsigned char p3 = 0;
// 判断步进速率是否需要改变
if( change_rate_flag )
{
TACCR0 = rate;
change_rate_flag = 0;
}
// 判断状态
switch( (state & 0x3) )
{
case 0x00: // 整步、逆时钟方向
index = stepIndex & 0x03;
p2 |= fullStepA[index];
p3 |= fullStepB[index];
P2OUT = p2;
P3OUT = p3;
++stepIndex;
break;
case 0x01: // 整步、顺时钟方向
index = stepIndex & 0x03;
p3 |= fullStepA[index];
p2 |= fullStepB[index];
P3OUT = p3;
P2OUT = p2;
++stepIndex;
break;
case 0x02: // 半步、逆时钟方向
index = stepIndex & 0x07;
p2 |= HalfStepA[index];
p3 |= CcwHalfStepB[index];
P2OUT = p2;
P3OUT = p3;
++stepIndex;
break;
case 0x03: // 半步、顺时钟方向
index = stepIndex & 0x07;
p3 |= CwHalfStepB[index];
p2 |= HalfStepA[index];
P3OUT = p3;
P2OUT = p2;
++stepIndex;
break;
default: break;
}
// 如果单步状态下,禁止定时器中断
if( state & MOTION_MASK )
{
TACCTL0 &= ~CCIE;
}
}
////////////////////////////////////////
// 处理来自串口 0 的接收中断
interrupt [UART0RX_VECTOR] void UART0_RX_ISR(void)
{
//接收来自的数据
UART0_RX_BUF[nRX0_Len_temp] = RXBUF0;
nRX0_Len_temp += 1;
if(nRX0_Len_temp >= 2)
if(UART0_RX_BUF[nRX0_Len_temp - 2] == '\r' &&
UART0_RX_BUF[nRX0_Len_temp - 1] == '\n')
{
// 过滤掉回车换行(\r\n)
if(nRX0_Len_temp == 2)
{
nRX0_Len_temp = 0;
}
else if(nRX0_Len_temp > 2)
{
nRX0_Len = nRX0_Len_temp;
nRev_UART0 = 1;
nRX0_Len_temp = 0;
}
}
}
////////////////////////////////////////
// 处理来自串口 0 的发送中断
interrupt [UART0TX_VECTOR] void UART0_TX_ISR(void)
{
if(nTX0_Len != 0)
{
// 表示缓冲区里的数据没有发送完
nTX0_Flag = 0;
TXBUF0 = UART0_TX_BUF[nSend_TX0];
nSend_TX0 += 1;
if(nSend_TX0 >= nTX0_Len)
{
nSend_TX0 = 0;
nTX0_Len = 0;
nTX0_Fla