motor.c
上传用户:xs588588
上传日期:2021-03-30
资源大小:242k
文件大小:11k
源码类别:

DSP编程

开发平台:

C/C++

  1. #include  <msp430x14x.h>
  2. #define DCO_FREQ        1000000      // DCO frequency
  3. #define ONE_SEC_CNT     512          // Number of WDT interrupts in 1 second
  4. #define DEBOUNCE_CNT    0x05         // (1/512)*5 = ~10 msec debounce
  5. #define DIR_MASK        0x01         // 0x01 is clockwise, 0x00 is counter-clockwise
  6. #define STEP_MASK       0x02         // 0x00 is full-stepping, 0x02 is half-stepping
  7. #define MOTION_MASK     0x04         // 0x00 is continuous, 0x04 is single-step
  8. #define DEFAULT_RATE     0x8000      // Default stepping rate
  9. #define MIN_RATE         0x8000      // Minimum stepping rate
  10. #define MAX_RATE         0x0800      // Maximum stepping rate
  11. // Default state is full-stepping, clockwise, continuous
  12. unsigned char state = 1;             // State variable
  13. unsigned char stepIndex = 0;         // State table index
  14. unsigned int  rate = DEFAULT_RATE;   // Stepping rate
  15. unsigned char change_rate_flag = 0;  // Flag indicating rate change
  16. unsigned int  max_rate = MAX_RATE;   // Maximum stepping rate
  17. unsigned int  min_rate = MIN_RATE;   // Minimum stepping rate
  18. unsigned int SW[4]; 
  19. void sys_init(void);
  20. void Set_DCO(unsigned long freq);
  21. void timerA_Init(void);
  22. void uart0_Init(void);
  23. void wdt_Init(void);
  24. void toggle_stepping_mode(void);
  25. void increase_stepping_rate(void);
  26. void decrease_stepping_rate(void);
  27. void toggle_motion(void);
  28. void toggle_direction(void);
  29. //定义串口操作变量
  30. char nRev_UART0; // 串口 0 的接收标志
  31. char UART0_TX_BUF[10]; // 串口 0 的发送缓冲区
  32. char UART1_RX_Temp[10];
  33. char UART0_RX_BUF[10]; // 串口 0 的接收缓冲区
  34. int nTX0_Len;
  35. int nRX0_Len;
  36. int nRX0_Len_temp;
  37. char nTX0_Flag;
  38. int nSend_TX0;
  39. // 整步状态表A
  40. static const unsigned char fullStepA[] =
  41. {
  42. 0x00,
  43. 0x00,
  44. 0x01,
  45. 0x01
  46. };
  47. //  半步状态表B
  48. static const unsigned char fullStepB[] =
  49. {
  50. 0x01,
  51. 0x00,
  52. 0x00,
  53. 0x01
  54. };
  55. // 半步状态表A
  56. static const unsigned char HalfStepA[] =
  57. {
  58. 0x01,   // 001   1
  59. 0x06,   // 110   2
  60. 0x00,   // 000   3
  61. 0x00,   // 000   4
  62. 0x00,   // 000   5
  63. 0x07,   // 111   6
  64. 0x01,   // 001   7
  65. 0x01    // 001   8
  66. };
  67. // 逆时钟、半步状态表B
  68. static const unsigned char CcwHalfStepB[] =
  69. {
  70. 0x01,   // 001   1
  71. 0x01,   // 001   2
  72. 0x01,   // 001   3
  73. 0x06,   // 110   4
  74. 0x00,   // 000   5
  75. 0x00,   // 000   6
  76. 0x00,   // 000   7
  77. 0x07    // 111   8
  78. };
  79. // 顺时钟、半步状态表B
  80. static const unsigned char CwHalfStepB[] =
  81. {
  82. 0x00,   // 000   1
  83. 0x00,   // 000   2
  84. 0x00,   // 000   3
  85. 0x07,   // 111   4
  86. 0x01,   // 001   5
  87. 0x01,   // 001   6
  88. 0x01,   // 001   7
  89. 0x06    // 110   8
  90. };
  91. void main(void)
  92. {
  93. int i;
  94. // 停止WDT
  95. WDTCTL = WDTPW + WDTHOLD;
  96. sys_init();
  97. _EINT();
  98. for(;;)
  99. {
  100. if(nRev_UART0 == 1)
  101.      {
  102.          nRev_UART0 = 0;
  103. for(i = 0;i < nRX0_Len;i++) UART1_RX_Temp[i] = UART0_RX_BUF[i];
  104. if((UART1_RX_Temp[0] == 'A') && (UART1_RX_Temp[1] == 'T'))
  105. {
  106. UART0_TX_BUF[0] = 'O';
  107. UART0_TX_BUF[1] = 'K';
  108. UART0_TX_BUF[2] = 13;
  109. nTX0_Len = 3;
  110. switch(UART1_RX_Temp[2])
  111. {
  112. case 'D': // 方向
  113. toggle_direction();
  114. break;
  115. case 'C': // 运动模式
  116. toggle_motion();
  117. break;
  118. case 'M': // 步进模式
  119. toggle_stepping_mode();
  120. break;
  121. case 'F': // 增加速率
  122. increase_stepping_rate();
  123. break;
  124. case 'S': // 降低速率
  125. decrease_stepping_rate();
  126. break;
  127. default: break;
  128. }
  129. }
  130. else
  131. {
  132. UART0_TX_BUF[0] = 'E';
  133. UART0_TX_BUF[1] = 'R';
  134. UART0_TX_BUF[2] = 'O';
  135. UART0_TX_BUF[3] = 'R';
  136. UART0_TX_BUF[4] = 'R';
  137. UART0_TX_BUF[5] = 13;
  138. nTX0_Len = 6;
  139. }
  140. // 设置中断标志,进入发送中断程序
  141. IFG1 |= UTXIFG0;
  142.      nRX0_Len = 0;
  143. }
  144. }
  145. }
  146. void sys_init(void)
  147. {
  148. // 设置下降沿触发中断
  149. P1IES = 0x0f;
  150. P1IFG = 0x00;
  151. P1IE = 0x0f;
  152. // 设置 P2.3,2,1,0 为输出
  153. // 设置 P3.3,2,1,0 为输出
  154. P2OUT = 0x00;
  155. P3OUT = 0x00;
  156. P2DIR |= 0x0f;
  157. P3DIR |= 0x0f;
  158. // 设置DCO
  159. Set_DCO(DCO_FREQ);
  160. // 初始化 Timer A
  161. timerA_Init();
  162. // 初始化 UART0
  163. uart0_Init();
  164. // 初始化 WDT
  165. wdt_Init();
  166. }
  167. void Set_DCO(unsigned long freq)
  168. {
  169. unsigned int clkCnt;
  170. unsigned int numDcoClks;
  171. unsigned int prevCnt = 0;
  172. // ACLK = LFXT1CLK/8 = 4096 Hz
  173. BCSCTL1 |= DIVA_3;                   
  174. numDcoClks = freq/4096;              
  175. TACCTL2 = CM_1 + CCIS_1 + CAP;
  176. TACTL = TASSEL_2 + MC_2 + TACLR;     
  177. while(1)
  178. {
  179. while( !(TACCTL2 & CCIFG) )
  180. {
  181. }
  182. TACCTL2 &= ~CCIFG;
  183. clkCnt = TACCR2 - prevCnt;
  184. prevCnt = TACCR2;
  185. if( numDcoClks == clkCnt )
  186. {
  187. break;
  188. }
  189. else if( clkCnt > numDcoClks )
  190. {
  191. DCOCTL--;
  192. if( DCOCTL == 0xFF )
  193. {
  194. if( BCSCTL1 & 0x07 )
  195. {
  196. BCSCTL1--;
  197. }
  198. else
  199. {
  200. break;
  201. }
  202. }
  203. }
  204. else
  205. {
  206. DCOCTL++;
  207. if( DCOCTL == 0x00 )
  208. {
  209. if( (BCSCTL1 & 0x07) != 0x07 )
  210. {
  211. BCSCTL1++;                   
  212. }
  213. else
  214. {
  215. break;
  216. }
  217. }
  218. }
  219. }
  220. // ACLK = LFXT1CLK/1 = 32768 Hz
  221. BCSCTL1 &= ~DIVA_3;                  
  222. TACCTL2 = 0; 
  223. TACTL = 0;
  224. }
  225. void wdt_Init(void)
  226. {
  227. // 设置时钟源为ACLK,1秒内产生512此
  228. WDTCTL = WDTPW + WDTTMSEL + WDTCNTCL + WDTSSEL + WDTIS0 + WDTIS1;
  229. }
  230. void uart0_Init(void)
  231. {
  232.     //将寄存器的内容清零
  233.     U0CTL = 0X00;
  234. //数据位为8bit
  235.     U0CTL += CHAR;
  236.     
  237.     U0TCTL = 0X00;
  238. //波特率发生器选择ACLK
  239.     U0TCTL += SSEL0;
  240.     
  241. //波特率为9600
  242.     UBR0_0 = 0X03;
  243.     UBR1_0 = 0X00;
  244.     UMCTL_0 = 0x4A;
  245.     //使能UART0的TXD和RXD
  246.     ME1 |= UTXE0 + URXE0; 
  247. //使能UART0的RX中断
  248.     IE1 |= URXIE0;
  249. //使能UART0的TX中断
  250.     IE1 |= UTXIE0;
  251.     
  252. //设置P3.4为UART0的TXD
  253.     P3SEL |= BIT4;
  254. //设置P3.5为UART0的RXD
  255.     P3SEL |= BIT5;
  256.     //P3.4为输出管脚
  257.     P3DIR |= BIT4;
  258. }
  259. void timerA_Init(void)
  260. {
  261. TACCR0 = rate;
  262. TACCTL0 = CCIE;
  263. TACTL = TASSEL_2 + MC_1 + TACLR;
  264. }
  265. interrupt [TIMERA0_VECTOR] void TimerA_ISR(void)
  266. {
  267. unsigned char index;
  268. unsigned char p2 = 0;
  269. unsigned char p3 = 0;
  270. // 判断步进速率是否需要改变
  271. if( change_rate_flag )
  272. {
  273. TACCR0 = rate;
  274. change_rate_flag = 0;
  275. }
  276. // 判断状态
  277. switch( (state & 0x3) )
  278. {
  279. case 0x00:  // 整步、逆时钟方向
  280. index = stepIndex & 0x03;
  281. p2 |= fullStepA[index];
  282. p3 |= fullStepB[index];
  283. P2OUT = p2;
  284. P3OUT = p3;
  285. ++stepIndex;
  286. break;
  287. case 0x01:  // 整步、顺时钟方向
  288. index = stepIndex & 0x03;
  289. p3 |= fullStepA[index];
  290. p2 |= fullStepB[index];
  291. P3OUT = p3;
  292. P2OUT = p2;
  293. ++stepIndex;
  294. break;
  295. case 0x02:  // 半步、逆时钟方向
  296. index = stepIndex & 0x07;
  297. p2 |= HalfStepA[index];
  298. p3 |= CcwHalfStepB[index];
  299. P2OUT = p2;
  300. P3OUT = p3;
  301. ++stepIndex;
  302. break;
  303. case 0x03:  // 半步、顺时钟方向
  304. index = stepIndex & 0x07;
  305. p3 |= CwHalfStepB[index];
  306. p2 |= HalfStepA[index];
  307. P3OUT = p3;
  308. P2OUT = p2;
  309. ++stepIndex;
  310. break;
  311. default: break;
  312. }
  313. // 如果单步状态下,禁止定时器中断
  314. if( state & MOTION_MASK )
  315. {
  316. TACCTL0 &= ~CCIE;
  317. }
  318. }
  319. ////////////////////////////////////////
  320. // 处理来自串口 0 的接收中断
  321. interrupt [UART0RX_VECTOR] void UART0_RX_ISR(void)
  322. {
  323. //接收来自的数据
  324.     UART0_RX_BUF[nRX0_Len_temp] = RXBUF0;
  325.     
  326.     nRX0_Len_temp += 1;
  327.         
  328.     if(nRX0_Len_temp >= 2)
  329.     if(UART0_RX_BUF[nRX0_Len_temp - 2] == 'r' && 
  330. UART0_RX_BUF[nRX0_Len_temp - 1] == 'n')
  331.     {
  332. // 过滤掉回车换行(rn)
  333.      if(nRX0_Len_temp == 2)
  334.      {
  335.          nRX0_Len_temp = 0;
  336.      }
  337.      else if(nRX0_Len_temp > 2)
  338.      {
  339.          nRX0_Len = nRX0_Len_temp;
  340.          nRev_UART0 = 1;
  341.          nRX0_Len_temp = 0;
  342.      }    
  343.     }
  344. }
  345. ////////////////////////////////////////
  346. // 处理来自串口 0 的发送中断
  347. interrupt [UART0TX_VECTOR] void UART0_TX_ISR(void)
  348. {
  349.     if(nTX0_Len != 0)
  350.     {
  351. // 表示缓冲区里的数据没有发送完
  352.      nTX0_Flag = 0;
  353.     
  354.      TXBUF0 = UART0_TX_BUF[nSend_TX0];
  355.      nSend_TX0 += 1;    
  356.      if(nSend_TX0 >= nTX0_Len)
  357.      {
  358.          nSend_TX0 = 0;
  359.          nTX0_Len = 0;
  360.          nTX0_Flag = 1;
  361.      }
  362.     }
  363. }
  364. interrupt [WDT_VECTOR] void WDT_ISR(void)
  365. {
  366. unsigned char sw_state;
  367. static unsigned char one_sec_flag = 0;
  368. // 获得P1口的输入
  369. sw_state = ~P1IN & 0x0f;
  370. // 判断是否有键按下
  371. if( sw_state == 0x00 )
  372. {
  373. // 禁止看门狗中断
  374. IE1 &= ~WDTIE;
  375. // 判断是否S2的激活状态小于1秒
  376. if( !one_sec_flag && (SW[1] >= DEBOUNCE_CNT) )
  377. {
  378. toggle_motion();
  379. }
  380. // 复位状态计数器
  381. SW[0] = 0;
  382. SW[1] = 0;
  383. SW[2] = 0;
  384. SW[3] = 0;
  385. // 复位标志
  386. one_sec_flag = 0;
  387. // 使能P1口的中断功能
  388. P1IFG = 0x00;
  389. P1IE = 0x0f;
  390. }
  391. else
  392. {
  393. // 检查是否是S1状态
  394. if( sw_state & 0x01 )
  395. {
  396. if( SW[0] < ONE_SEC_CNT )
  397. {
  398. // 增加状态计数器
  399. ++SW[0];
  400. }
  401. if( SW[0] == DEBOUNCE_CNT )
  402. {
  403. toggle_direction();
  404. }
  405. }
  406. else
  407. {
  408. SW[0] = 0;
  409. }
  410. // 检查是否是S2状态
  411. if( sw_state & 0x02 )
  412. {
  413. if( SW[1] < ONE_SEC_CNT )
  414. {
  415. // 增加状态计数器
  416. ++SW[1];
  417. }
  418. if( SW[1] == ONE_SEC_CNT )
  419. {
  420. toggle_stepping_mode();
  421. one_sec_flag = 1;
  422. SW[1] = 0;
  423. }
  424. }
  425. else
  426. {
  427. // 判断是否S2的激活状态小于1秒
  428. if( !one_sec_flag && (SW[1] >= DEBOUNCE_CNT) )
  429. {
  430. toggle_motion();
  431. }
  432. one_sec_flag = 0;
  433. SW[1] = 0;
  434. }
  435. // 检查是否是S3状态
  436. if( sw_state & 0x04 )
  437. {
  438. // 检查是否是连续模式
  439. if( (state & MOTION_MASK) == 0 )
  440. {
  441. if( SW[2] < ONE_SEC_CNT )
  442. {
  443. // 增加状态计数器
  444. ++SW[2];
  445. }
  446. if( SW[2] == DEBOUNCE_CNT )
  447. {
  448. increase_stepping_rate();
  449. }
  450. }
  451. else // 单步模式
  452. {
  453. // 增加状态计数器
  454. ++SW[2];
  455. if( (SW[2] % DEBOUNCE_CNT) == 0 )
  456. {
  457. increase_stepping_rate();
  458. }
  459. }
  460. }
  461. else  
  462. {
  463. SW[2] = 0;
  464. }
  465. // 检查是否是S4状态
  466. if( sw_state & 0x08 )
  467. {
  468. if( SW[3] < ONE_SEC_CNT )
  469. {
  470. // 增加状态计数器
  471. ++SW[3];
  472. }
  473. if( SW[3] == DEBOUNCE_CNT )
  474. {
  475. decrease_stepping_rate();
  476. }
  477. }
  478. else
  479. {
  480. SW[3] = 0;
  481. }
  482. }
  483. }
  484. interrupt [PORT1_VECTOR] void PORT1_ISR(void)
  485. {
  486. // 禁止端口1的中断
  487. P1IE = 0x00;
  488. // 清除端口1的中断标志
  489. P1IFG = 0x00;
  490. // 使能看门狗中断
  491. IE1 |= WDTIE;
  492. }
  493. void increase_stepping_rate(void)
  494. {
  495. unsigned int new_rate;
  496. // 检查是否是连续模式
  497. if( (state & MOTION_MASK) == 0 )
  498. {
  499. new_rate = rate >> 1;
  500. if( new_rate >= max_rate )
  501. {
  502. rate = new_rate;
  503. change_rate_flag = 1;
  504. }
  505. }
  506. //使能定时器A的中断
  507. TACCTL0 |= CCIE;
  508. }
  509. void decrease_stepping_rate(void)
  510. {
  511. // 检查是否是连续模式
  512. if( (state & MOTION_MASK) == 0 )
  513. {
  514. if( rate <= (min_rate >> 1) )
  515. {
  516. rate <<= 1;
  517. change_rate_flag = 1;
  518. }
  519. }
  520. // 使能定时器A的中断
  521. TACCTL0 |= CCIE;
  522. }
  523. void toggle_stepping_mode(void)
  524. {
  525. // 切换步进模式
  526. state ^= STEP_MASK;
  527. // 检查是否是半步模式
  528. if( state & STEP_MASK )
  529. {
  530. // 从整步模式切换到半步模式
  531. // 定时器的频率加倍
  532. rate = (rate >> 1);
  533. change_rate_flag = 1;
  534. max_rate = (MAX_RATE >> 1);
  535. min_rate = (MIN_RATE >> 1);
  536. }
  537. else // 整步模式
  538. {
  539. // 从半步模式切换到整步模式
  540. // 定时器的频率减半
  541. rate = (rate << 1);
  542. change_rate_flag = 1;
  543. max_rate = MAX_RATE;
  544. min_rate = MIN_RATE;
  545. }
  546. }
  547. void toggle_motion(void)
  548. {
  549. state ^= MOTION_MASK;
  550. // 检查是否是连续步进模式
  551. if( (state & MOTION_MASK) == 0 )
  552. {
  553. // 使能定时器中断
  554. TACCTL0 |= CCIE;
  555. }
  556. }
  557. void toggle_direction(void)
  558. {
  559. state ^= DIR_MASK;
  560. }