?? motor.c
字號:
#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_Flag = 1;
}
}
}
interrupt [WDT_VECTOR] void WDT_ISR(void)
{
unsigned char sw_state;
static unsigned char one_sec_flag = 0;
// 獲得P1口的輸入
sw_state = ~P1IN & 0x0f;
// 判斷是否有鍵按下
if( sw_state == 0x00 )
{
// 禁止看門狗中斷
IE1 &= ~WDTIE;
// 判斷是否S2的激活狀態小于1秒
if( !one_sec_flag && (SW[1] >= DEBOUNCE_CNT) )
{
toggle_motion();
}
// 復位狀態計數器
SW[0] = 0;
SW[1] = 0;
SW[2] = 0;
SW[3] = 0;
// 復位標志
one_sec_flag = 0;
// 使能P1口的中斷功能
P1IFG = 0x00;
P1IE = 0x0f;
}
else
{
// 檢查是否是S1狀態
if( sw_state & 0x01 )
{
if( SW[0] < ONE_SEC_CNT )
{
// 增加狀態計數器
++SW[0];
}
if( SW[0] == DEBOUNCE_CNT )
{
toggle_direction();
}
}
else
{
SW[0] = 0;
}
// 檢查是否是S2狀態
if( sw_state & 0x02 )
{
if( SW[1] < ONE_SEC_CNT )
{
// 增加狀態計數器
++SW[1];
}
if( SW[1] == ONE_SEC_CNT )
{
toggle_stepping_mode();
one_sec_flag = 1;
SW[1] = 0;
}
}
else
{
// 判斷是否S2的激活狀態小于1秒
if( !one_sec_flag && (SW[1] >= DEBOUNCE_CNT) )
{
toggle_motion();
}
one_sec_flag = 0;
SW[1] = 0;
}
// 檢查是否是S3狀態
if( sw_state & 0x04 )
{
// 檢查是否是連續模式
if( (state & MOTION_MASK) == 0 )
{
if( SW[2] < ONE_SEC_CNT )
{
// 增加狀態計數器
++SW[2];
}
if( SW[2] == DEBOUNCE_CNT )
{
increase_stepping_rate();
}
}
else // 單步模式
{
// 增加狀態計數器
++SW[2];
if( (SW[2] % DEBOUNCE_CNT) == 0 )
{
increase_stepping_rate();
}
}
}
else
{
SW[2] = 0;
}
// 檢查是否是S4狀態
if( sw_state & 0x08 )
{
if( SW[3] < ONE_SEC_CNT )
{
// 增加狀態計數器
++SW[3];
}
if( SW[3] == DEBOUNCE_CNT )
{
decrease_stepping_rate();
}
}
else
{
SW[3] = 0;
}
}
}
interrupt [PORT1_VECTOR] void PORT1_ISR(void)
{
// 禁止端口1的中斷
P1IE = 0x00;
// 清除端口1的中斷標志
P1IFG = 0x00;
// 使能看門狗中斷
IE1 |= WDTIE;
}
void increase_stepping_rate(void)
{
unsigned int new_rate;
// 檢查是否是連續模式
if( (state & MOTION_MASK) == 0 )
{
new_rate = rate >> 1;
if( new_rate >= max_rate )
{
rate = new_rate;
change_rate_flag = 1;
}
}
//使能定時器A的中斷
TACCTL0 |= CCIE;
}
void decrease_stepping_rate(void)
{
// 檢查是否是連續模式
if( (state & MOTION_MASK) == 0 )
{
if( rate <= (min_rate >> 1) )
{
rate <<= 1;
change_rate_flag = 1;
}
}
// 使能定時器A的中斷
TACCTL0 |= CCIE;
}
void toggle_stepping_mode(void)
{
// 切換步進模式
state ^= STEP_MASK;
// 檢查是否是半步模式
if( state & STEP_MASK )
{
// 從整步模式切換到半步模式
// 定時器的頻率加倍
rate = (rate >> 1);
change_rate_flag = 1;
max_rate = (MAX_RATE >> 1);
min_rate = (MIN_RATE >> 1);
}
else // 整步模式
{
// 從半步模式切換到整步模式
// 定時器的頻率減半
rate = (rate << 1);
change_rate_flag = 1;
max_rate = MAX_RATE;
min_rate = MIN_RATE;
}
}
void toggle_motion(void)
{
state ^= MOTION_MASK;
// 檢查是否是連續步進模式
if( (state & MOTION_MASK) == 0 )
{
// 使能定時器中斷
TACCTL0 |= CCIE;
}
}
void toggle_direction(void)
{
state ^= DIR_MASK;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -