新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > 基于ARM的步進電機控制示例(串口方式+中斷方式)

        基于ARM的步進電機控制示例(串口方式+中斷方式)

        作者: 時間:2016-11-21 來源:網絡 收藏
          本設計實現了通過ARM對步進電機(Motor)的控制。控制方式有兩種,一種是通過外部中斷,另外一種是通過串口發送命令進行控制。

          本設計可實現步進電機的速度和方向控制。通過串口方式控制電機時,只要在仿真過程中在虛擬終端(Virtual Terminal)輸入相應的命令即可控制電機的運轉。

        本文引用地址:http://www.104case.com/article/201611/319082.htm

          

        虛擬終端

          串口控制命令(雙引號內字符,可自己定義)如下:

          "<": 使電機逆時針方向轉動;

          ">": 使電機順時針方向轉動;

          "+": 加速;

          "-" : 減速。

          

          如果讀者在仿真過程中不小心關閉了虛擬終端(Virtual Terminal),可以在調試(Debug)菜單下找到它。

          

          整體電路連接如下圖所示:

          如果讀者在實踐過程中出現電機運轉不穩定的情況可嘗試把電機的Maximum RPM設置為一個較大的數值,此處筆者設置為7200,如下圖所示:

          附上本設計源代碼:

        1 #include "config.h"
        2
        3 int DelayTime=60; //延時參數
        4
        5 typedef struct UartMode
        6 {
        7 uint8 datab; //字長度,5/6/7/8可選
        8 uint8 stopb; //停止位,1/2可選
        9 uint8 parity; //奇偶校驗位,0:無校驗;1:奇檢驗;2:偶檢驗
        10 }UARTMODE;
        11
        12 uint8 rcv_buf; //UART0數據接收緩沖區
        13 uint8 rcv_new; //接收數據標志
        14
        15 //延時函數原型聲明
        16 void delay(int dly);
        17
        18 //工作模式設置函數原型聲明
        19 void SetWorkMode(char WorkMode);
        20
        21 //中斷服務程序原型聲明
        22 void __irq IRQ_Eint0(void);
        23 void __irq IRQ_Eint1(void);
        24 void __irq IRQ_Eint2(void);
        25 void __irq IRQ_Eint3(void);
        26
        27 //中斷初始化函數
        28 void Int_Init(void);
        29
        30 //串口0接收中斷服務程序
        31 void __irq IRQ_UART0(void);
        32
        33 //串口0數據發送函數
        34 void UART0_SendByte(uint8 dat);
        35
        36 //串口0初始化函數
        37 uint8 UART0_Init(uint32 baud, UARTMODE set);
        38
        39
        40 //********************************************************************************************************
        41 //主函數
        42 int main (void)
        43 {
        44
        45 UARTMODE set;
        46
        47 set.datab=8; //設置字長度為8位
        48 set.stopb=1; //設置停止位為1位
        49 set.parity=0; //設置檢驗方式為無校驗
        50
        51 rcv_new=0; //接收數據標志初始化
        52
        53 //配置引腳功能
        54 PINSEL0=0x0005c0c5;
        55 PINSEL1=0x00000301;
        56
        57 IO0DIR=0x03<<21; //設P0.21-P0.22為輸出
        58
        59 UART0_Init(9600, set); //串口初始化
        60 U0FCR=0x01; //使能FIFO,并設置觸發點為1字節
        61 U0IER=0x01; //允許RBR中斷,即接收中斷
        62
        63 Int_Init(); //中斷初始化(外部中斷、串口中斷)
        64
        65 while(1)
        66 {
        67 if(rcv_new==1)
        68 {
        69 rcv_new=0;
        70 SetWorkMode(rcv_buf); //根據輸入的控制信號改變步進電機的工作模式
        71 UART0_SendByte(rcv_buf); //把鍵盤輸入發回虛擬終端回顯
        72 }
        73 //模擬脈沖信號驅動步進電機轉動
        74 IO0SET=0x01<<22;
        75 delay(DelayTime);
        76 IO0CLR=0x01<<22;
        77 delay(DelayTime);
        78 }
        79 return 0;
        80 }
        81
        82 //********************************************************************************************************
        83 //延時函數
        84 void delay(int dly)
        85 {
        86 int i,j;
        87 for(i=0; i88 for(j=0; j<1200; j++);
        89
        90 }
        91
        92 //********************************************************************************************************
        93 //工作模式設置函數
        94 void SetWorkMode(char WorkMode)
        95 {
        96 //WorkMode:控制信號
        97 // +:加速 -:減速 <:逆時針 >:順時針
        98 switch(WorkMode)
        99 {
        100 case +:
        101 if(DelayTime>20)
        102 DelayTime=DelayTime-20; //減少延時,即加速
        103 break;
        104 case -:
        105 if(DelayTime<100)
        106 DelayTime=DelayTime+20; //增加延時,即減速
        107 break;
        108 case <:
        109 IO0CLR=0x01<<21; //設置的步進電機的運轉方向為逆時針
        110 break;
        111 case >:
        112 IO0SET=0x01<<21; //設置的步進電機的運轉方向為順時針
        113 break;
        114 default :break;
        115 }
        116 }
        117
        118 //********************************************************************************************************
        119 //外部中斷0服務程序
        120 void __irq IRQ_Eint0(void)
        121 {
        122 IO0CLR=0x01<<21; //設置的步進電機的運轉方向為逆時針
        123
        124 while((EXTINT&0x01)!=0)
        125 {
        126 EXTINT=0x01; //清除中斷標志
        127 }
        128 VICVectAddr=0;
        129 }
        130
        131 //********************************************************************************************************
        132 //外部中斷1服務程序
        133 void __irq IRQ_Eint1(void)
        134 {
        135 IO0SET=0x01<<21; //設置的步進電機的運轉方向為順時針
        136
        137 while((EXTINT&0x02)!=0)
        138 {
        139 EXTINT=0x02; //清除中斷標志
        140 }
        141 VICVectAddr=0;
        142 }
        143
        144 //********************************************************************************************************
        145 //外部中斷2服務程序
        146 void __irq IRQ_Eint2(void)
        147 {
        148 if(DelayTime>20)
        149 DelayTime=DelayTime-5; //減少延時,即加速
        150
        151 while((EXTINT&0x04)!=0)
        152 {
        153 EXTINT=0x04; //清除中斷標志
        154 }
        155 VICVectAddr=0;
        156 }
        157
        158 //********************************************************************************************************
        159 //外部中斷3服務程序
        160 void __irq IRQ_Eint3(void)
        161 {
        162 if(DelayTime<100)
        163 DelayTime=DelayTime+5; //增加延時,即減速
        164 while((EXTINT&0x08)!=0)
        165 {
        166 EXTINT=0x08; //清除中斷標志
        167 }
        168 VICVectAddr=0;
        169 }
        170
        171 //********************************************************************************************************
        172 //中斷初始化函數
        173 void Int_Init(void)
        174 {
        175 EXTMODE=0x00; //設置外部中斷為電平觸發
        176
        177 IRQEnable(); //使能IRQ中斷
        178
        179 VICIntSelect=0x00000000; //設置所有分配為IRQ中斷
        180
        181 VICVectCntl4=0x20|0x0e; //分配外部中斷4到向量中斷0
        182 VICVectCntl1=0x20|0x0f; //分配外部中斷1到向量中斷0
        183 VICVectCntl2=0x20|0x10; //分配外部中斷2到向量中斷0
        184 VICVectCntl3=0x20|0x11; //分配外部中斷3到向量中斷0
        185 VICVectCntl0=0x20|0x06; //分配Uart0中斷到向量中斷0
        186
        187
        188 //設置中斷服務程序地址
        189 VICVectAddr4=(uint32)IRQ_Eint0;
        190 VICVectAddr1=(uint32)IRQ_Eint1;
        191 VICVectAddr2=(uint32)IRQ_Eint2;
        192 VICVectAddr3=(uint32)IRQ_Eint3;
        193 VICVectAddr0=(uint32)IRQ_UART0;
        194
        195 EXTINT=0x0f; //清除所有外部中斷標志
        196
        197 VICIntEnable=(1<<0x0e)|(1<<0x0f)|(1<<0x10)|(1<<0x11)|(1<<0x06); //使能所用到的中斷
        198 }
        199
        200 //********************************************************************************************************
        201 //串口0接收中斷服務程序
        202 void __irq IRQ_UART0(void)
        203 {
        204 if((U0IIR&0x0f)==0x04)
        205 rcv_new=1; //設置接收到新的數據標志
        206
        207 rcv_buf=U0RBR; //讀取FIFO的數據,并清除中斷
        208
        209 VICVectAddr=0;
        210 }
        211
        212 //********************************************************************************************************
        213 //串口0數據發送函數
        214 void UART0_SendByte(uint8 dat)
        215 {
        216 U0THR=dat;
        217 while((U0LSR&0x20)==0); //等待數據發送完畢
        218 }
        219
        220 //********************************************************************************************************
        221 //串口0初始化函數
        222 uint8 UART0_Init(uint32 baud, UARTMODE set)
        223 {
        224 uint32 bak;
        225
        226 //參數過濾
        227 if((baud==0)||(baud>115200))return(0);
        228 if((set.datab<5)||(set.datab>8))return(0);
        229 if((set.stopb==0)||(set.stopb>2))return(0);
        230 if(set.parity>4)return(0);
        231
        232 //設置串口的波特率
        233 U0LCR=0x80; //DLAB=1
        234 bak=(Fpclk>>4)/baud;
        235 U0DLM=bak>>8;
        236 U0DLL=bak&0xff;
        237
        238 //設置串口模式
        239 bak=set.datab-5; //設置字長
        240 if(set.stopb==2)bak|=0x04; //判斷是否為2位停止位
        241
        242 if(set.parity!=0)
        243 {
        244 set.parity=set.parity-1;
        245 bak|=0x08;
        246 }
        247 bak|=set.parity<<4; //設置奇偶校驗
        248
        249 U0LCR=bak;
        250
        251 return(1);
        252 }
        253
        254



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 赤城县| 霞浦县| 双牌县| 榕江县| 桃源县| 七台河市| 吴旗县| 商河县| 武威市| 翁牛特旗| 台湾省| 吐鲁番市| 正镶白旗| 新民市| 洪泽县| 长垣县| 双鸭山市| 鄂伦春自治旗| 修武县| 庆安县| 丽水市| 大名县| 南溪县| 安达市| 阿合奇县| 新丰县| 黑河市| 延长县| 桦南县| 三都| 安福县| 阜平县| 泰和县| 通江县| 宁晋县| 磐安县| 长汀县| 光山县| 水城县| 金昌市| 特克斯县|