[应用方案] 单片机远程控制步进电机、LED灯和蜂鸣器

[复制链接]
1416|5
 楼主| Roderman_z 发表于 2016-4-18 22:13 | 显示全部楼层 |阅读模式

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

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

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

  1. #include <reg52.h>  

  2. sbit WEI=P2^7;  
  3. sbit DUAN=P2^6;  
  4. #define DataPort P0  

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

  9. void delay(int t)  
  10. {  
  11.    while(t--);  
  12. }  
  13. sbit A1=P1^0; //定义步进电机连接端口  
  14. sbit B1=P1^1;  
  15. sbit C1=P1^2;  
  16. sbit D1=P1^3;  

  17. #define Coil_AB1 {A1=1;B1=1;C1=0;D1=0;}//AB相通电,其他相断电  
  18. #define Coil_BC1 {A1=0;B1=1;C1=1;D1=0;}//BC相通电,其他相断电  
  19. #define Coil_CD1 {A1=0;B1=0;C1=1;D1=1;}//CD相通电,其他相断电  
  20. #define Coil_DA1 {A1=1;B1=0;C1=0;D1=1;}//D相通电,其他相断电  
  21. #define Coil_A1 {A1=1;B1=0;C1=0;D1=0;}//A相通电,其他相断电  
  22. #define Coil_B1 {A1=0;B1=1;C1=0;D1=0;}//B相通电,其他相断电  
  23. #define Coil_C1 {A1=0;B1=0;C1=1;D1=0;}//C相通电,其他相断电  
  24. #define Coil_D1 {A1=0;B1=0;C1=0;D1=1;}//D相通电,其他相断电  
  25. #define Coil_OFF {A1=0;B1=0;C1=0;D1=0;}//全部断电  

  26. unsigned char Speed;  
  27. unsigned char dir=0;   
  28. unsigned char code rst[]={0xe4,0xc0,0xe0,0xc0,0xe0,0x32};  // 复位代码               
  29. void Init_Timer0(void);  
  30. void DelayUs2x(unsigned char t)  
  31. {     
  32. while(--t);  
  33. }  


 楼主| Roderman_z 发表于 2016-4-18 22:13 | 显示全部楼层
  1. void DelayMs(unsigned char t)  
  2. {  

  3. while(t--)  
  4. {  
  5.      //大致延时1mS  
  6.      DelayUs2x(245);  
  7.      DelayUs2x(245);  
  8. }  
  9. }  

  10. void Display(unsigned char FirstBit,unsigned char Num)  
  11. {  
  12.       static unsigned char i=0;  
  13.        DataPort=0;   //清空数据,防止有交替重影  
  14.        DUAN=1;     //段锁存  
  15.        DUAN=0;  
  16.        DataPort=dofly_WeiMa[i+FirstBit]; //取位码   
  17.        WEI=1;     //位锁存  
  18.        WEI=0;  
  19.        DataPort=TempData; //取显示数据,段码  
  20.        DUAN=1;     //段锁存  
  21.        DUAN=0;  
  22.        i++;  
  23.        if(i==Num)  
  24.           i=0;  
  25. }  

  26. void Rorate()  
  27. {  
  28.    unsigned int i=512;//旋转一周时间  
  29.    Init_Timer0();  
  30.    EA=1;          //全局中断开  
  31.    EX0=1;         //外部中断0开  
  32.    IT0=1;         //1表示边沿触发  
  33.     //Speed=speed;  
  34.     TempData[0]=dofly_DuanMa[Speed/10];//分解显示信息,如要显示68,   
  35.     TempData[1]=dofly_DuanMa[Speed%10];//则68/10=6  68%10=8   
  36.     Coil_OFF  
  37.     while(i--&&dir==0)  //正向  
  38.     {  
  39.        Coil_A1         
  40.       DelayMs(Speed);  
  41.        P3=0xeb;  
  42.        P3=0xff;  
  43.       Coil_AB1                 //遇到Coil_AB1  用{A1=1;B1=1;C1=0;D1=0;}代替  
  44.       DelayMs(Speed);         //改变这个参数可以调整电机转速 ,  
  45.        P3=0xeb;  
  46.        P3=0xff;                   //数字越小,转速越大,力矩越小  
  47.       Coil_B1         
  48.       DelayMs(Speed);  
  49.        P3=0xeb;  
  50.        P3=0xff;  
  51.       Coil_BC1  
  52.       DelayMs(Speed);  
  53.        P3=0xeb;  
  54.        P3=0xff;  
  55.       Coil_C1         
  56.       DelayMs(Speed);  
  57.        P3=0xeb;  
  58.        P3=0xff;  
  59.       Coil_CD1  
  60.       DelayMs(Speed);  
  61.        P3=0xeb;  
  62.        P3=0xff;  
  63.       Coil_D1         
  64.       DelayMs(Speed);  
  65.        P3=0xeb;  
  66.        P3=0xff;  
  67.       Coil_DA1  
  68.       DelayMs(Speed);  
  69.        P3=0xeb;  
  70.        P3=0xff;  
  71.     }  
  72.      Coil_OFF  
  73.      i=512;  

  74.     while((i--)&&dir)//反向  
  75.      {  
  76.        Coil_A1         
  77.        DelayMs(Speed);  
  78.        P3=0xeb;  
  79.        P3=0xff;  
  80.       Coil_DA1                  //遇到Coil_AB1  用{A1=1;B1=1;C1=0;D1=0;}代替  
  81.       DelayMs(Speed);         //改变这个参数可以调整电机转速 ,  
  82.        P3=0xeb;  
  83.        P3=0xff;                   //数字越小,转速越大,力矩越小  
  84.       Coil_D1         
  85.       DelayMs(Speed);  
  86.        P3=0xeb;  
  87.        P3=0xff;  
  88.        Coil_CD1  
  89.       DelayMs(Speed);  
  90.        P3=0xeb;  
  91.        P3=0xff;  
  92.       Coil_C1         
  93.       DelayMs(Speed);  
  94.        P3=0xeb;  
  95.        P3=0xff;  
  96.       Coil_BC1  
  97.       DelayMs(Speed);  
  98.        P3=0xeb;  
  99.        P3=0xff;  
  100.       Coil_B1         
  101.       DelayMs(Speed);  
  102.        P3=0xeb;  
  103.        P3=0xff;  
  104.       Coil_AB1  
  105.       DelayMs(Speed);  
  106.        P3=0xeb;  
  107.        P3=0xff;  
  108.      }  

  109. }  


 楼主| Roderman_z 发表于 2016-4-18 22:14 | 显示全部楼层
  1. /*------------------------------------------------
  2.                     串口初始化
  3. ------------------------------------------------*/  
  4. void InitUART  (void)  
  5. {  
  6.     SCON  = 0x50;               // SCON: 模式 1, 8-bit UART, 使能接收   
  7.     TMOD |= 0x20;               // TMOD: timer 1, mode 2, 8-bit 重装  
  8.     TH1   = 0xFD;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz   
  9.     TR1   = 1;                  // TR1:  timer 1 打开                           
  10.     EA    = 1;                  //打开总中断  
  11.     ES    = 1;                  //打开串口中断  
  12. }     



  13. /*------------------------------------------------
  14.                     主函数
  15. ------------------------------------------------*/  

  16. unsigned int judge[8];  
  17. int cnt=0;  

  18. void main (void)  
  19. {  

  20.    InitUART();  

  21.    ES= 1;//打开串口中断  
  22.   while (1)                        
  23.     {  

  24.        if(judge[0]==0xFF&&judge[1]==0xFE&&judge[6]==0xFD&&judge[7]==0xFC)  
  25.        {   
  26.            //(*((void (*)())(rst)))();  // ,将rst数组当函数调用,进行复位  
  27.            if(judge[2]==0x00)//指定步进电机  
  28.            {  
  29.                P3=0xeb;  
  30.                P3=0xff;  
  31.                if(judge[5]!=0)  
  32.                Rorate();  
  33.            }  
  34.            else if(judge[2]==0x01)//指定LED  
  35.            {  

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



  37.                while (1)         //主循环  
  38.                {  

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

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

  50.                P0=judge[3];  
  51.                delay(PWM_LOW);  
  52.                P0=0xFF;  
  53.                delay(CYCLE-PWM_LOW);  

  54.                 }  

  55.              }  

  56.            }  
  57.            else if(judge[2]==0x02)  
  58.            {  
  59.               while(1)  
  60.               {  

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

  63.               }  
  64.            }  
  65.        }  
  66.     }  
  67. }  
  68. /*------------------------------------------------
  69.                      串口中断程序
  70. ------------------------------------------------*/  
  71. void UART_SER (void) interrupt 4 //串行中断服务程序  
  72. {  
  73.     unsigned char Temp;          //定义临时变量   

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

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

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

  86. /*------------------------------------------------
  87.                     定时器初始化子程序
  88. ------------------------------------------------*/  
  89. void Init_Timer0(void)  
  90. {  
  91. TMOD |= 0x01;    //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响            
  92. //TH0=0x00;          //给定初值  
  93. //TL0=0x00;  
  94. EA=1;            //总中断打开  
  95. ET0=1;           //定时器中断打开  
  96. TR0=1;           //定时器开关打开  
  97. PT0=1;           //优先级打开  
  98. }  
  99. /*------------------------------------------------
  100.                  定时器中断子程序
  101. ------------------------------------------------*/  
  102. void Timer0_isr(void) interrupt 1   
  103. {  
  104. TH0=(65536-2000)/256;        //重新赋值 2ms  
  105. TL0=(65536-2000)%256;  
  106.   Display(0,8);  
  107. }  

  108. //外部中断程序  
  109. void ISR_INT0(void) interrupt 0   
  110. {  
  111.          Speed=judge[4];  
  112.          dir=judge[3];  
  113.          TempData[0]=dofly_DuanMa[Speed/10];//分解显示信息,如要显示68,   
  114.          TempData[1]=dofly_DuanMa[Speed%10];//则68/10=6  68%10=8     
  115. }  
energyplants 发表于 2016-4-20 22:50 | 显示全部楼层
这个远程控制用的也是2.4G吧,还是用的WiFi?
天灵灵地灵灵 发表于 2016-4-21 13:44 | 显示全部楼层
对于简单的应用可以直接通过查表法,把所有可能全部列出来,这样效率非常高。
capturesthe 发表于 2016-4-21 22:31 | 显示全部楼层
驱动步进电机的电路经常用哪个芯片?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

41

主题

354

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部