|
因為這是第一次接觸步進電機以及電機驅動器,所以編了個簡單的程序,其實是改過來的,有興趣的朋友可以參考一下,喜歡交流的朋友也可以回帖.
這是l連接好的圖片:
我用p1口的0、1、2、3分別接驅動器的+、PU、+、DR接線端,其中PU的脈沖提供了轉速的變化,DR電平的改變決定了旋轉方向下面給出程序,大家有什么不懂的到群里討論。
- #include <reg51.h> //51芯片管腳定義頭文件
- #include <intrins.h> //內部包含延時函數 _nop_() ;
- #define uchar unsigned char
- #define uint unsigned int
- #define delayNOP() ; {_nop_() ;_nop_() ;_nop_() ;_nop_() ;} ;
- uchar code FFW[4]={0xf5,0xf7,0xf5,0xf7} ;
- uchar code REV[4]={0xfd,0xff,0xfd,0xff} ;
- sbit K1 = P3^3 ; //運行與停止
- sbit K2 = P3^2 ; //設定圈數
- sbit K3 = P3^5 ; //方向轉換
- sbit K4 = P3^4 ; //速率調整
- sbit BEEP = P2^4 ; //蜂鳴器
- sbit LCD_RS = P2^6 ;
- sbit LCD_RW = P3^6 ;
- sbit LCD_EN = P2^7 ;
- bit on_off=0 ; //運行與停止標志
- bit direction=1 ; //方向標志
- bit rate_dr=1 ; //速率標志
- bit snum_dr=1 ; //圈數標志
- uchar code cdis1[ ] = {" STEPPING MOTOR "} ;
- uchar code cdis2[ ] = {"CONTROL PROCESS"} ;
- uchar code cdis3[ ] = {" STOP "} ;
- uchar code cdis4[ ] = {"NUM: RATE: "} ;
- uchar code cdis5[ ] = {" RUNNING "} ;
- uchar m,v=0,q=0 ;
- int number=0,number1=0;
- char snum=1,snum1=1 ; //預設定圈數
- char rate=1 ; //預設定速率
- char data_temp,data_temp1,data_temp2 ;
- /********************************************************/
- /*
- /* 延時t毫秒
- /* 11.0592MHz時鐘,延時約1ms
- /*
- /********************************************************/
- void delay(uint t)
- {
- uchar k ;
- while(t--)
- {
- for(k=0 ; k<125 ; k++)
- { }
- }
- }
- /********************************************************/
- void delayB(uchar x) //x*0.14MS
- {
- uchar i ;
- while(x--)
- {
- for (i=0 ; i<13 ; i++)
- { }
- }
- }
- /********************************************************/
- void beep()
- {
- uchar j ;
- for (j=0 ;j<100 ;j++)
- {
- delayB(4) ;
- BEEP=!BEEP ; //BEEP取反
- }
- BEEP=1 ; //關閉蜂鳴器
- delay(170) ;
- }
- /********************************************************/
- /*
- /*檢查LCD忙狀態
- /*lcd_busy為1時,忙,等待。為0時,閑,可寫指令與數據。
- /*
- /********************************************************/
- bit lcd_busy()
- {
- bit result ;
- LCD_RS = 0 ;
- LCD_RW = 1 ;
- LCD_EN = 1 ;
- delayNOP() ;
- result = (bit)(P0&0x80) ;
- LCD_EN = 0 ;
- return(result) ;
- }
- /********************************************************/
- /*
- /*寫指令數據到LCD
- /*RS=L,RW=L,E=高脈沖,D0-D7=指令碼。
- /*
- /********************************************************/
- void lcd_wcmd(uchar cmd)
- {
- while(lcd_busy()) ;
- LCD_RS = 0 ;
- LCD_RW = 0 ;
- LCD_EN = 0 ;
- _nop_() ;
- _nop_() ;
- P0 = cmd ;
- delayNOP() ;
- LCD_EN = 1 ;
- delayNOP() ;
- LCD_EN = 0 ;
- }
- /********************************************************/
- /*
- /*寫顯示數據到LCD
- /*RS=H,RW=L,E=高脈沖,D0-D7=數據。
- /*
- /********************************************************/
- void lcd_wdat(uchar dat)
- {
- while(lcd_busy()) ;
- LCD_RS = 1 ;
- LCD_RW = 0 ;
- LCD_EN = 0 ;
- P0 = dat ;
- delayNOP() ;
- LCD_EN = 1 ;
- delayNOP() ;
- LCD_EN = 0 ;
- }
- /********************************************************/
- /*
- /* LCD初始化設定
- /*
- /********************************************************/
- void lcd_init()
- {
- delay(30) ;
- lcd_wcmd(0x38) ; //16*2顯示,5*7點陣,8位數據
- delay(5) ;
- lcd_wcmd(0x38) ;
- delay(5) ;
- lcd_wcmd(0x38) ;
- delay(5) ;
- lcd_wcmd(0x0c) ; //顯示開,關光標
- delay(5) ;
- lcd_wcmd(0x06) ; //移動光標
- delay(5) ;
- lcd_wcmd(0x01) ; //清除LCD的顯示內容
- delay(5) ;
- }
- /********************************************************/
- /*
- /* 設定顯示位置
- /*
- /********************************************************/
- void lcd_pos(uchar pos)
- {
- lcd_wcmd(pos | 0x80) ; //數據指針=80+地址變量
- }
- /********************************************************/
- /*
- /* LCD1602初始顯示子程序
- /*
- /********************************************************/
- void LCD_init_DIS()
- {
- delay(10) ; //延時
- lcd_init() ; //初始化LCD
-
- lcd_pos(0) ; //設置顯示位置為第一行的第1個字符
- m = 0 ;
- while(cdis1[m] != '\0')
- { //顯示字符
- lcd_wdat(cdis1[m]) ;
- m++ ;
- }
- lcd_pos(0x40) ; //設置顯示位置為第二行第1個字符
- m = 0 ;
- while(cdis2[m] != '\0')
- {
- lcd_wdat(cdis2[m]) ; //顯示字符
- m++ ;
- }
- delay(1000) ; //延時
-
- lcd_pos(0) ; //設置顯示位置為第一行的第1個字符
- m = 0 ;
- while(cdis3[m] != '\0')
- { //顯示字符
- lcd_wdat(cdis3[m]) ;
- m++ ;
- }
- lcd_pos(0x40) ; //設置顯示位置為第二行第1個字符
- m = 0 ;
- while(cdis4[m] != '\0')
- {
- lcd_wdat(cdis4[m]) ; //顯示字符
- m++ ;
- }
- for(m=0 ;m<2 ;m++)
- {
- lcd_pos(0x0c+m) ; //顯示方向符號
- lcd_wdat(0x3e) ;
- }
- }
- /********************************************************/
- /*
- /*數據轉換子程序
- /*
- /********************************************************/
- void data_conv()
- {
- data_temp1=data_temp/10 ; //高位
- if(data_temp1==0)
- {data_temp1=0x20 ;} //高位為0不顯示
- else
- {data_temp1=data_temp1+0x30 ;}
- data_temp2=data_temp%10 ; //低位
- data_temp2=data_temp2+0x30 ;
- }
- /********************************************************/
- /*
- /*數據顯示子程序
- /*
- /********************************************************/
- void data_dis()
- {
- data_temp = snum ; //顯示圈數
- data_conv() ;
- lcd_pos(0x44) ;
- lcd_wdat(data_temp1) ;
- lcd_pos(0x45) ;
- lcd_wdat(data_temp2) ;
-
- data_temp = rate ; //顯示速率
- data_conv() ;
- lcd_pos(0x4d) ;
- lcd_wdat(data_temp1) ;
- lcd_pos(0x4e) ;
- lcd_wdat(data_temp2) ;
- }
- /********************************************************
- /*
- /* 顯示運行方向符號
- /*
- /********************************************************/
- void motor_DR()
- {
- if(direction==1) //正轉方向標志
- { for(m=0 ;m<2 ;m++)
- {
- lcd_pos(0x0c+m) ; //顯示方向符號
- lcd_wdat(0x3e) ;
- }
- }
- else
- { for(m=0 ;m<2 ;m++) //反轉方向標志
- {
- lcd_pos(0x0c+m) ; //顯示方向符號
- lcd_wdat(0x3c) ;
- }
- }
- }
- /********************************************************
- /*
- /* 顯示運行狀態
- /*
- /********************************************************/
- void motor_RUN()
- {
- if(on_off==1)
- { TR0=1 ;
- lcd_pos(0) ; //設置顯示位置為第一行的第1個字符
- m = 0 ;
- while(cdis5[m] != '\0')
- { lcd_wdat(cdis5[m]) ; //RUNNING
- m++ ; }
- motor_DR() ; //
- }
- else
- { TR0=0 ; P1 =0xf0 ;
- lcd_pos(0) ; //設置顯示位置為第一行的第1個字符
- m = 0 ;
- while(cdis3[m] != '\0')
- { lcd_wdat(cdis3[m]) ; //STOP
- m++ ; }
- motor_DR() ; //
- snum=snum1 ; //
- number1=0 ; //清圈數計數器
- }
- }
- /********************************************************
- *
- * 主程序
- *
- *********************************************************/
- main()
- {
- LCD_init_DIS() ;
-
- TMOD = 0x01 ; //T0定時方式1
- TL0 = 0xee ;
- TH0 = 0xff ;
- EA = 1 ;
- ET0 = 1 ;
- P1 = 0xf0 ;
-
- while(1)
- {
- if(K1==0)
- {
- beep() ;
- while(K1==0) ; //等待鍵釋放
- on_off=~on_off ;
- motor_RUN() ;
- } //K1 end
- /********************************************************/
- if(K2==0)
- {
- beep() ;
- if(snum_dr==1)
- { snum++ ;
- snum1=snum ;
- if(snum==10)
- { snum_dr=~snum_dr ;}
- }
- else
- {snum-- ;
- snum1=snum ;
- if(snum==1)
- { snum_dr=~snum_dr ; }
- }
-
- } //K2 end
- /********************************************************/
- if(K3==0)
- {
- beep() ;
- direction=~direction ;
- motor_DR() ;
- }//K3 end
- /********************************************************/
- if(K4==0)
- {
- beep() ;
- if(rate_dr==1)
- { rate++ ;
- if(rate==10)
- { rate_dr=~rate_dr ;}
- }
- else
- {
- rate-- ;
- if(rate==1)
- { rate_dr=~rate_dr ; }
- }
- } //K4 end
-
-
- /********************************************************/
- if(number1==snum1) //與設定圈數是否相等
- { number1=0 ;
- on_off=0 ;
- TR0=0 ;
- snum=snum1 ;
- P1 =0xf0 ;
- motor_RUN() ;
- }
- data_dis() ;
- } // while(1) end
- } //main end
- /********************************************************/
- /*
- /* 定時器 0 中斷
- /*
- /********************************************************/
- void motor_onoff() interrupt 1
- {
- TL0 = 0xff ;
- TH0 = 0xff ;
- q++ ;
- if(q < rate)
- { return ; }
- else
- { q=0 ;
- number++ ; //脈沖計數
-
- if(number==800) //2*400個脈沖電機轉一圈
- { snum-- ;
- number=0 ;
- number1++ ;
- } //電機轉動圈數
-
- if(direction==1) //方向標志
- { if(v<4)
- {P1 = FFW[v] ;v++ ;} //取數據,正轉
- if(v==4)
- { v=0 ; }
- }
-
- else
- { if(v<4)
- {P1 = REV[v] ;v++ ;} //取數據,反轉
- if(v==4)
- { v=0 ; }
-
- }
-
-
- }
- }
復制代碼
以上程序本人運行正常。
|
|