zoukankan      html  css  js  c++  java
  • 单片机远程控制步进电机、LED灯和蜂鸣器

    通过採用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; //定义步进电机连接port
    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);
    }
    
    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[i]; //取显示数据,段码
           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;
    	 }
    	
    }
    
    /*------------------------------------------------
                        串口初始化
    ------------------------------------------------*/
    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表示低
                         //电平时间,这个循环中低电平时长从1累加到CYCLE(周期)的值,即600次
    
       	              	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
    	  
    }

    C#端:


    namespace 单片机
    {
        public partial class frm : Form
        {
            public frm()
            {
                InitializeComponent();
    
            }
    
            private SerialPort com;
    
            //通信协议
           /// <summary>
           /// FF FE 00(电机) 00(方向) 00(速度) 00(停止) FD FC
           /// </summary>
           /// <param name="sender"></param>
           /// <param name="e"></param>
    
            private void btn_LED_Click(object sender, EventArgs e)
            {
                com = new SerialPort();
                com.BaudRate = 9600;
                com.PortName = "COM4";
                com.DataBits = 8;
                com.Open();
                Byte[] data = new Byte[8];
                data[0] = 0xFF;
                data[1] = 0xFE;
                if(rb_R.Checked==true)
                {
                    data[2] = 0x00;
                    if (rb_clock.Checked == true)
                    {
                        data[3] = 0x00;
                    }
                    else if (rb_anclock.Checked == true)
                    {
                        data[3] = 0x01;
                    }
                    if (cmb_speed.Text.ToString() == "停止")
                    {
                        data[4] = 0x00;
                        data[5] = 0x00;
                    }
                    else
                    {
                        data[4] = Byte.Parse(cmb_speed.Text);
                        data[5] = 0x01;
                    }
                }
                else if (rb_LED.Checked == true)
                {
                    data[2] = 0x01;
                    uint num = 255;
                    if (checkBox1.Checked == true)
                    {
                        num = num & 254;
                    }
                    if (checkBox2.Checked == true)
                    {
                        num = num & 253;
                    }
                    if (checkBox3.Checked == true)
                    {
                        num = num & 251;
                    }
                    if (checkBox4.Checked == true)
                    {
                        num = num & 247;
                    }
                    if (checkBox5.Checked == true)
                    {
                        num = num & 239;
    
                    }
                    if (checkBox6.Checked == true)
                    {
                        num = num & 223;
                    }
                    if (checkBox7.Checked == true)
                    {
                        num = num & 191;
                    }
                    if (checkBox8.Checked == true)
                    {
                        num = num & 127;
                    }
    
                    byte[] c = System.BitConverter.GetBytes(num);
                    data[3] = c[0];
    
                    if (led_s.Text.ToString() == "启用")
                        data[2] = 0x02;
                    data[4] = 0x00;
                    data[5] = 0x00;
                }
             
                data[6] = 0xFD;
                data[7] = 0xFC;
                com.Write(data, 0, 8);
                com.Close(); 
            }
        }
    }



  • 相关阅读:
    Serverless
    使用excelJS实现excel文件转json文件
    使用excelJS实现json文件转excel文件
    git rebase 和 git merge的异同
    JS 箭头函数与普通函数的区别
    JS 节流函数(throttle)与防抖函数(debounce)
    http协议解析
    前端必会的js知识总结整理
    前端必会css整理
    推荐几个有趣的在线调试工具
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7172006.html
Copyright © 2011-2022 走看看