motor.c
资源名称:msp430.rar [点击查看]
上传用户:xs588588
上传日期:2021-03-30
资源大小:242k
文件大小:11k
源码类别:
DSP编程
开发平台:
C/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')
- {
- // 过滤掉回车换行(rn)
- 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;
- }