仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
单片机源程序如下:
- /* 步进电机程序 */
- /*P1^0 为四相单四拍, P1^1 为四相双四拍, P1^2 为四相八拍 */
- /*P1^3 为启动 / 停止控制、 P1^4 方向控制、 P1^5 加速、 P1^6 减速 */
- /* 用 4 位 LED 数码管显示工作步数。 */
- /* 用 3 个发光二极管显示状态 */
- /* 正转时红灯亮,反转时黄灯亮,不转时绿灯亮 */
- /* 编写人: */
- /* 时间: 2013-06-26 */
- /***********************************************************/
- #include<reg51.h>
- #define uchar unsigned char
- #define uint unsigned int
- #define SegData P0 // 数码管数据口
- #define KeyData P1 // 按键控制数据口
- #define MotorData P2 // 电机控制数据口
- #define dula P0 //段选
- sbit wela1=P3^0; // 数码管位选 1
- sbit wela2=P3^1; // 数码管位选 2
- sbit wela3=P3^3; // 数码管位选 3
- sbit wela4=P3^7; // 数码管位选 4
- sbit wela5=P2^4; // 数码管位选 5
- sbit wela6=P2^5; // 数码管位选 6
- sbit wela7=P2^6; // 数码管位选 7
- sbit wela8=P2^7; // 数码管位选 8
- sbit RS=P2^6;
- sbit RW=P2^5;
- sbit E=P2^7;
- #define LCD_data P0
- uchar code table2[13]={"RAOZU:Y90S-2"};
- uchar code table3[25]={"DZ:0X200 ZS:75"};
- sbit LedGreen=P3^4;// 控制绿灯-停止
- sbit LedRed=P3^5; // 控制红灯-停止
- sbit LedYellow=P3^6;// 控制黄灯-停止
- uchar PositiveSingleFour[]={0xf1,0xf4,0xf2,0xf8}; // 步进电机正相单四拍数表 ;
- uchar PositiveDoubleFour[]={0xf5,0xf6,0xfa,0xf9}; // 步进电机正相双四拍数表 ;
- uchar PositiveEight[]={0xf1,0xf5,0xf4,0xf6,0xf2,0xfa,0xf8,0xf9};// 步进电机正相八拍数表 ;
- uchar NegitiveSingleFour[]={0xf1,0xf8,0xf2,0xf4}; // 步进电机反相单四拍数表 ;
- uchar NegitiveDoubleFour[]={0xf9,0xfa,0xf6,0xf5}; // 步进电机反相双四拍数表 ;
- uchar NegitiveEight[]={0xf1,0xf9,0xf8,0xfa,0xf2,0xf6,0xf4,0xf5};// 步进电机反相八拍数表 ;
- uchar table[]={
- 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,
- 0x40,0x76,0x38};//数码管显示
- uchar Flag=0; // 用来控制拍数循环;
- uchar Mode=0; // 用来标志工作模式;
- uchar Way=0; // 用来标志运转方向
- uchar Num=0; // 用来定时计数
- uchar Delay=0; // 用来标志延时时间到
- uchar Move=0; // 用来标志启动或停止
- uint Step=0; // 用来计算步数的;
- char Speed=12; // 用来表示速度
- char SpeedMax=2; // 最大速度 - 参数为时间
- char SpeedMin=22; // 最小速度
- char SpeedChang=1; // 速度每次改变量
- uint Pulse=0; //计数
- uint Period=0 ; //周期计数
- uint real_speed=0; //实际转速
- uint lilun_speed=0; //理论转速
- /****************** 函数声明部分 **********************/
- void Init();
- //void Display(uint);
- void DelayMs(uint);
- void KeyScan();
- void Motor();
- void display(uint first,uint second,uint third,uint forth);
- void display2(uint first,uint second,uint third,uint forth);
- /****************** 主函数 **********************/
- /********************************/
- void delay_us(); //18us
- void delay_ms(uint);
- void lcd_init();
- void lcd_write_com(uchar com);
- void lcd_write_dat(uchar dat);
- void lcd_init();
- void lcd_display(uchar add,uchar dat);
- /***********************************/
- void delay_us()
- {
- uchar x;
- for(x=0;x<5;x++);
- }
- void delay_ms(uint z)
- {
- uint x,y;
- for(x=0;x<z;x++)
- for(y=0;y<123;y++);
- }
- void lcd_write_com(uchar com)
- {
- E=0;
- RS=0;
- RW=0;
- delay_us();
- LCD_data=com;
- E=1; //高脉冲写入数据
- delay_us();
- E=0;
- }
- void lcd_write_dat(uchar dat)
- {
- E=0;
- RS=1;
- RW=0;
- delay_us();
- LCD_data=dat;
- E=1; //高脉冲写入数据
- delay_us();
- E=0;
- }
- void lcd_init() //lcd初始化
- {
- delay_ms(15);
- lcd_write_com(0x38);
- delay_ms(10);
- lcd_write_com(0x0c);
- lcd_write_com(0x06);
- lcd_write_com(0x01);
- delay_ms(2);
-
-
- }
- void lcd_display(uchar add,uchar dat) //lcd显示(地址,数据)
- {
- lcd_write_com(add);
-
- lcd_write_dat(dat);
- delay_us();
- }
- void main()
- {
- char i;
- lcd_init();
- for(i=0;i<12;i++)
- {
- lcd_display(0x80+i,table2[i]);
- }
- for(i=0;i<14;i++)
- {
- lcd_display(0x80+0x40+i,table3[i]);
- }
- Init();
- while(1)
- {
- KeyScan();
- Motor();
- // display(real_speed/1000,real_speed%1000/100,real_speed%100/10,real_speed%10) ;
- display(lilun_speed/1000,lilun_speed%1000/100,lilun_speed%100/10,lilun_speed%10) ;
- }
- }
- //显示函数
- void display(uint first,uint second,uint third,uint forth)
- {
- wela1 = 0;
- dula = table[first]; //显示第一个
- DelayMs(1);
- wela1 = 1;
- dula = 0x00; //一定要加,否则不稳定
- wela2 = 0;
- dula = table[second]; //显示第二个
- DelayMs(1);
- wela2 = 1;
- dula = 0x00;
- wela3 = 0;
- dula = table[third]; //显示第三个
- DelayMs(1);
- wela3 = 1;
- dula = 0x00;
- wela4 = 0;
- dula = table[forth]; //显示第4个
- DelayMs(1);
- wela4 = 1;
- dula = 0x00;
- }
- //显示函数
- void display2(uint first,uint second,uint third,uint forth)
- {
- wela5 = 0;
- dula = table[first]; //显示第一个
- DelayMs(1);
- wela5 = 1;
- dula = 0x00; //一定要加,否则不稳定
- wela6 = 0;
- dula = table[second]; //显示第二个
- DelayMs(1);
- wela6 = 1;
- dula = 0x00;
- wela7 = 0;
- dula = table[third]; //显示第三个
- DelayMs(1);
- wela7 = 1;
- dula = 0x00;
- wela8 = 0;
- dula = table[forth]; //显示第4个
- DelayMs(1);
- wela8 = 1;
- dula = 0x00;
- }
- /****************** 电机运转函数 **********************/
- void Motor()
- {
- if(Move==1)
- {
- LedGreen=0;
- if(Delay==1)
- {
- Delay=0;
- if(Way==0)
- {
- LedRed=0;
- LedYellow=1;
- switch(Mode)
- {
- /* 电机步进拍数表数据送到电机控制口;判断一周拍数是否完成;步数加 1*/
- case 1:MotorData=PositiveSingleFour[Flag++];if(Flag>=4) Flag=0;Step++;break;
- case 2:MotorData=PositiveDoubleFour[Flag++];if(Flag>=4) Flag=0;Step++;break;
- case 3:MotorData=PositiveEight[Flag++];if(Flag>=8) Flag=0;Step++;break;
- default: ;
- }
- }
- else
- {
- LedRed=1;
- LedYellow=0;
- switch(Mode)
- {
- case 1:MotorData=NegitiveSingleFour[Flag++];if(Flag>=4) Flag=0;Step++;break;
- case 2:MotorData=NegitiveDoubleFour[Flag++];if(Flag>=4) Flag=0;Step++;break;
- case 3:MotorData=NegitiveEight[Flag++];if(Flag>=8) Flag=0;Step++;break;
- default: ;
- }
- }
- }
- }
- else
- {
- MotorData=0xef;
- LedGreen=1;
- }
- }
- /****************** 初始化函数 **********************/
- void Init()
- {
- Move=0;
- LedGreen=1;
- Step=0;
- MotorData=0xef;
- IT0=1;//跳变沿出发方式(下降沿)
- EX0=1;//打开INT0的中断允许。
- EA=1;//打开总中断
- TMOD=0x11; // 定时器 0 初始化
- TH0=(65536-2000)/256;
- TL0=(65536-2000)%256;
- EA=1; // 开总中断
- ET0=1; // 开定时器 0 中断
- TR0=1; // 开始计时
- }
- /****************** 按键检测函数 **********************/
- void KeyScan()
- {
- uchar Temp,Over=0;
- Temp=KeyData;
- Temp=Temp&0x08;
- if(Temp!=0x08) // 启动键按下
- {
- Move=1;
- Temp=KeyData;
- Temp=Temp&0x60;
- if(Temp!=0x60)
- {
- DelayMs(2); // 按键软件消抖
- Temp=KeyData;
- Temp=Temp&0x60;
- if(Temp!=0x60)
- {
- Over=1; // 有键按下则不扫描后续按键
- if(Temp==0x40) // 加速键按下
- {
- while(Temp!=0xe7) // 按键松开检测
- {
- Temp=KeyData;
- Temp=Temp&0xe7;
- }
- Speed=Speed-SpeedChang;
- if(Speed<=SpeedMax)
- {
- Speed=SpeedMax; // 一直按加速键则保持到最大速度
- }
- }
- else if(Temp==0x20) // 减速键按下
- {
- while(Temp!=0xe7)
- {
- Temp=KeyData;
- Temp=Temp&0xe7;
- }
- Speed=Speed+SpeedChang;
- if(Speed>=SpeedMin)
- {
- Speed=SpeedMin;
- }
- }
- }
- }
- if(Over==0) // 判断前是否有键按下
- {
- Temp=KeyData;
- Temp=Temp&0x10;
- if(Temp!=0x10)
- {
- DelayMs(2);
- Temp=KeyData;
- Temp=Temp&0x10;
- if(Temp!=0x10)
- {
- Way=0; // 方向按键按下,电机顺时针转动
- }
- }
- else
- {
- Way=1;
- }
- }
- if(Over==0)
- {
- Temp=KeyData;
- Temp=Temp&0x07;
- if(Temp!=0x07)
- {
- DelayMs(2);
- Temp=KeyData;
- Temp=Temp&0x07;
- if(Temp!=0x07)
- {
- switch(Temp)
- {
- case 0x06: Mode=1;break;// 电机四相单四拍运行
- case 0x05: Mode=2;break;// 电机四相双四拍运行
- case 0x03: Mode=3;break;// 电机四相八拍运行
- }
- }
- }
- }
- }
- else
- {
- Move=0; // 电机停止
- }
- }
- /**************** 毫秒延时 ***************/
- void DelayMs(uint z)
- {
- uint t1,y;
- for(t1=z;t1>0;t1--)
- for(y=110;y>0;y--);
- }
- /**************** 定时器 0 中断函数 ***************/
- void T0_time() interrupt 1
- {
- // TH0=(65536-45872)/256;
- // TL0=(65536-45872)%256;
- TH0=(65536-2000)/256;
- TL0=(65536-2000)%256;
- Num++;
- Period++;
- if(Num>=Speed)
- {
- Num=0;
- Delay=1; // 延时时间到
- }
- if(Period >= 500)
- {
- real_speed=Pulse*60; //实际转速
- lilun_speed =Step*15; //理论转速
- Step=0;
- Pulse=0;
- Period=0;
- }
- }
- /*外部中断0的中断函数*/
- void Int0() interrupt 0
- {
- Pulse++;//脉冲++
- }
复制代码 全部资料51hei下载地址:
步进电机1602 数码管.rar
(155.69 KB, 下载次数: 87)
|