打印
[应用方案]

单片机远程控制步进电机、LED灯和蜂鸣器

[复制链接]
1193|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
Roderman_z|  楼主 | 2016-4-18 22:13 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

通过采用C#语言实现的上位机控制单片机的步进电机模块、LED灯和蜂鸣器模块,使步进电机进行正、反转和停止并控制转速;LED灯模块进行有选择的呼吸式表达;蜂鸣器模块的开始和终止。

上位机通过串口和自定义的通信协议(8字节)控制单片机的步进电机、LED灯和蜂鸣器模块。其中在控制步进电机的过程中,为了使操作能够及时响应,使用了INT0中断来进行及时性速度响应;LED灯使用位运算控制灯的闪烁位置,合理利用了单片机的模块和操作。

注意:由于定时器个数的限制,没能控制更多的模块。

#include <reg52.h>  

sbit WEI=P2^7;  
sbit DUAN=P2^6;  
#define DataPort P0  

unsigned char code dofly_DuanMa[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x40};// 显示段码值0~9  
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码  
unsigned char TempData[8]; //存储显示值的全局变量  
sbit SPK1=P1^4;   

void delay(int t)  
{  
   while(t--);  
}  
sbit A1=P1^0; //定义步进电机连接端口  
sbit B1=P1^1;  
sbit C1=P1^2;  
sbit D1=P1^3;  

#define Coil_AB1 {A1=1;B1=1;C1=0;D1=0;}//AB相通电,其他相断电  
#define Coil_BC1 {A1=0;B1=1;C1=1;D1=0;}//BC相通电,其他相断电  
#define Coil_CD1 {A1=0;B1=0;C1=1;D1=1;}//CD相通电,其他相断电  
#define Coil_DA1 {A1=1;B1=0;C1=0;D1=1;}//D相通电,其他相断电  
#define Coil_A1 {A1=1;B1=0;C1=0;D1=0;}//A相通电,其他相断电  
#define Coil_B1 {A1=0;B1=1;C1=0;D1=0;}//B相通电,其他相断电  
#define Coil_C1 {A1=0;B1=0;C1=1;D1=0;}//C相通电,其他相断电  
#define Coil_D1 {A1=0;B1=0;C1=0;D1=1;}//D相通电,其他相断电  
#define Coil_OFF {A1=0;B1=0;C1=0;D1=0;}//全部断电  

unsigned char Speed;  
unsigned char dir=0;   
unsigned char code rst[]={0xe4,0xc0,0xe0,0xc0,0xe0,0x32};  // 复位代码               
void Init_Timer0(void);  
void DelayUs2x(unsigned char t)  
{     
while(--t);  
}  


沙发
Roderman_z|  楼主 | 2016-4-18 22:13 | 只看该作者
void DelayMs(unsigned char t)  
{  

while(t--)  
{  
     //大致延时1mS  
     DelayUs2x(245);  
     DelayUs2x(245);  
}  
}  

void Display(unsigned char FirstBit,unsigned char Num)  
{  
      static unsigned char i=0;  
       DataPort=0;   //清空数据,防止有交替重影  
       DUAN=1;     //段锁存  
       DUAN=0;  
       DataPort=dofly_WeiMa[i+FirstBit]; //取位码   
       WEI=1;     //位锁存  
       WEI=0;  
       DataPort=TempData; //取显示数据,段码  
       DUAN=1;     //段锁存  
       DUAN=0;  
       i++;  
       if(i==Num)  
          i=0;  
}  

void Rorate()  
{  
   unsigned int i=512;//旋转一周时间  
   Init_Timer0();  
   EA=1;          //全局中断开  
   EX0=1;         //外部中断0开  
   IT0=1;         //1表示边沿触发  
    //Speed=speed;  
    TempData[0]=dofly_DuanMa[Speed/10];//分解显示信息,如要显示68,   
    TempData[1]=dofly_DuanMa[Speed%10];//则68/10=6  68%10=8   
    Coil_OFF  
    while(i--&&dir==0)  //正向  
    {  
       Coil_A1         
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_AB1                 //遇到Coil_AB1  用{A1=1;B1=1;C1=0;D1=0;}代替  
      DelayMs(Speed);         //改变这个参数可以调整电机转速 ,  
       P3=0xeb;  
       P3=0xff;                   //数字越小,转速越大,力矩越小  
      Coil_B1         
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_BC1  
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_C1         
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_CD1  
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_D1         
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_DA1  
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
    }  
     Coil_OFF  
     i=512;  

    while((i--)&&dir)//反向  
     {  
       Coil_A1         
       DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_DA1                  //遇到Coil_AB1  用{A1=1;B1=1;C1=0;D1=0;}代替  
      DelayMs(Speed);         //改变这个参数可以调整电机转速 ,  
       P3=0xeb;  
       P3=0xff;                   //数字越小,转速越大,力矩越小  
      Coil_D1         
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
       Coil_CD1  
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_C1         
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_BC1  
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_B1         
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
      Coil_AB1  
      DelayMs(Speed);  
       P3=0xeb;  
       P3=0xff;  
     }  

}  


使用特权

评论回复
板凳
Roderman_z|  楼主 | 2016-4-18 22:14 | 只看该作者
/*------------------------------------------------
                    串口初始化
------------------------------------------------*/  
void InitUART  (void)  
{  
    SCON  = 0x50;               // SCON: 模式 1, 8-bit UART, 使能接收   
    TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装  
    TH1   = 0xFD;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz   
    TR1   = 1;                  // TR1:  timer 1 打开                           
    EA    = 1;                  //打开总中断  
    ES    = 1;                  //打开串口中断  
}     



/*------------------------------------------------
                    主函数
------------------------------------------------*/  

unsigned int judge[8];  
int cnt=0;  

void main (void)  
{  

   InitUART();  

   ES= 1;//打开串口中断  
  while (1)                        
    {  

       if(judge[0]==0xFF&&judge[1]==0xFE&&judge[6]==0xFD&&judge[7]==0xFC)  
       {   
           //(*((void (*)())(rst)))();  // ,将rst数组当函数调用,进行复位  
           if(judge[2]==0x00)//指定步进电机  
           {  
               P3=0xeb;  
               P3=0xff;  
               if(judge[5]!=0)  
               Rorate();  
           }  
           else if(judge[2]==0x01)//指定LED  
           {  

               unsigned int CYCLE=600,PWM_LOW=0;//定义周期并赋值  



               while (1)         //主循环  
               {  

                    WEI=0;         //位锁存置0电平,防止LED亮的时候数码管亮  
                    DUAN=0;       //段锁存置0电平,防止LED亮的时候数码管亮  
                    P0=0xFF;  
                    delay(60000);        //特意加延时,可以看到熄灭的过程  
                    for(PWM_LOW=1;PWM_LOW<cycle;pwm_low++){ pwm_low表示低="" [="" size][="" color][="" align]                    P0=judge[3];        //点亮LED   
                    delay(PWM_LOW);//延时长度,600次循环中从1加至599  
                    P0=0xFF;        //熄灭LED  
                    delay(CYCLE-PWM_LOW);//延时长度,600次循环中从599减至1  

               }  
               P0=judge[3];  
               for(PWM_LOW=CYCLE-1;PWM_LOW>0;PWM_LOW--){ //与逐渐变亮相反的过程  

               P0=judge[3];  
               delay(PWM_LOW);  
               P0=0xFF;  
               delay(CYCLE-PWM_LOW);  

                }  

             }  

           }  
           else if(judge[2]==0x02)  
           {  
              while(1)  
              {  

                   DelayMs(1); //发出大约500Hz的方波 频率越大声音越尖  
                   SPK1=!SPK1;  

              }  
           }  
       }  
    }  
}  
/*------------------------------------------------
                     串口中断程序
------------------------------------------------*/  
void UART_SER (void) interrupt 4 //串行中断服务程序  
{  
    unsigned char Temp;          //定义临时变量   

   if(RI)                        //判断是接收中断产生  
     {  
      RI=0;                      //标志位清零  
      Temp=SBUF;                 //读入缓冲区的值  

      judge[cnt++]=Temp;  
      if(cnt==8||judge[0]!=0xFF)        
      cnt=0;  

      SBUF=Temp;     //把接收到的值再发回电脑端  
     }  
   if(TI)                        //如果是发送标志位,清零  
     TI=0;  
}   

/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/  
void Init_Timer0(void)  
{  
TMOD |= 0x01;    //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响            
//TH0=0x00;          //给定初值  
//TL0=0x00;  
EA=1;            //总中断打开  
ET0=1;           //定时器中断打开  
TR0=1;           //定时器开关打开  
PT0=1;           //优先级打开  
}  
/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/  
void Timer0_isr(void) interrupt 1   
{  
TH0=(65536-2000)/256;        //重新赋值 2ms  
TL0=(65536-2000)%256;  
  Display(0,8);  
}  

//外部中断程序  
void ISR_INT0(void) interrupt 0   
{  
         Speed=judge[4];  
         dir=judge[3];  
         TempData[0]=dofly_DuanMa[Speed/10];//分解显示信息,如要显示68,   
         TempData[1]=dofly_DuanMa[Speed%10];//则68/10=6  68%10=8     
}  

使用特权

评论回复
地板
energyplants| | 2016-4-20 22:50 | 只看该作者
这个远程控制用的也是2.4G吧,还是用的WiFi?

使用特权

评论回复
5
天灵灵地灵灵| | 2016-4-21 13:44 | 只看该作者
对于简单的应用可以直接通过查表法,把所有可能全部列出来,这样效率非常高。

使用特权

评论回复
6
capturesthe| | 2016-4-21 22:31 | 只看该作者
驱动步进电机的电路经常用哪个芯片?

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

354

帖子

2

粉丝