.
  • 作者:city7cc
  • 积分:4065
  • 等级:专家教授
  • 2019/1/8 17:42:34
  • 中国面包师贴吧-楼主(阅:3306/回:0)一种具有12路PWM直流电机的串口遥控机器人

    一种具有12路PWM直流电机的串口遥控机器人

    技术领域

        本实用新型涉及一种一种具有12路PWM直流电机的串口遥控机器人,尤其是一种可以用串口无线WIFI遥控的智能机器人。

    背景技术

    现有常规遥控机人按照无线电信号的遥控进行动作,也可以按照存储在寄存器里面的程序动作,但是动作电机较少,一般只有4路PWM直流电机,这对机器人的行动带来很大的不便。一种具有12路PWM直流电机的串口遥控机器人是一种具有12路PWM直流电机的机器人,操作者可以使用计算机串口WIFI信号对它的12路直流电机进行遥控,它也可以按照其控制电路中的24C04铁电存储器里面的数据,在STC11F60单片机的控制下进行动作。

    实用新型内容

    为了解决常规遥控机器人动作电机较少的缺点,一种具有12路PWM直流电机的串口遥控机器人提供了一种具有12路PWM直流电机进行串口WIFI信号遥控动作的机器人。它可以按照电路中的24C04铁电存储器里面的数据,在STC11F60单片机的控制下进行动作,也可以按照操作人员计算机串口WIFI信号的遥控进行动作。由于它具有12路PWM直流电机,所以它可以进行行走,抬手,伸手等多种动作。

    本实用新型解决其技术问题所采用的技术方案是:一种具有12路PWM直流电机的串口遥控机器人是一种可以被WIFI串口信号遥控的机器人。它依靠外壳下面装配的12路PWN直流电机在操作人员的计算机串口WIFI信号的遥控下进行的转动进行各种动作,它可以在电机的转动下进行移动,行走,抬手等等动作。同时,它也可以按照控制电路中的24C04铁电存储器里面的数据,在STC11F60单片机(1)的控制下进行电机的转动等动作。它的控制电路如图1所示。在图1中,STC11F60单片机(1)的P1中的P1.0, P1.1, P1.2, P1.3, P1.4, P1.5, P1.6,P1.7端口,P3 中的P3.2,P3.5, P3.6, P3.7端口在定时器TIME0产生12路PWM方波,上面总共12路IO口,每个IO口产生一路PWM信号,总共12路PWM控制方波信号。WIFI模块(2)连接在单片机STC11F60(1)的串口上面,它接收操作人员发出的数据,然后单片机STC11F60 (1)按照程序减少或增加PWM方波的占空比。同时单片机(1)按照铁电存储器24C04(3)中的数据控制上面的PWM方波信号。

    单片机STC11F60的控制程序是在keill4编译环境下,通过C语言编译并通过串口下载到单片机STC11F60。程序代码如下:

    /******************************************************************************

    *程序思路说明:                                                             *

    *                                                                           *

    *关于频率和占空比的确定,对于12M晶振,假定PWM输出频率为1KHZ,这样定时中断次数 *

    *设定为C=10,即0.01MS中断一次,则TH0=FF,TL0=F6;由于设定中断时间为0.01ms,这样可以设定占空比

    可从1-100变化。即0.01ms*100=1ms                               *

    ******************************************************************************/

    #include<regx51.h>

    #include<INTRINS.H>

    #define ucharunsigned char  

             #include <intrins.h>

    #define   OP_READ    0xa1       // 器件地址以及读取操作

    #define   OP_WRITE 0xa0     //器件地址以及写入操作

    #define   MAX_ADDR 0x7f     //AT24C02最大地址

    /*****************************************************************************

    * TH0和TL0是计数器0的高8位和低8位计数器,计算办法:TL0=(65536-C)%256;         *

    *TH0=(65536-C)/256,其中C为所要计数的次数即多长时间产生一次中断;TMOD是计数器*

    * 工作模式选择,0X01表示选用模式1,它有16位计数器,最大计数脉冲为65536,最长时 *

    * 间为1ms*65536=65.536ms                                                     *

    ******************************************************************************/

    #defineV_TH0  0XFF                  

    #defineV_TL0  0XF6                  

    #define V_TMOD0X01                  

    #defineV_TH1  0XFF                  

    #defineV_TL1  0XF6                  

    #defineV_TH2  0XFF                  

    #defineV_TL2  0XF6  

    unsigned charcode dis_code[] = {0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff};

                  // 写入到AT24C01的数据串

    sbit SDA = P3^4;

    sbit SCL = P3^3;

    void start();

    void stop();

    unsigned charshin();

    bitshout(unsigned char write_data);

    unsigned charread_random(unsigned char random_addr);

    void write_byte(unsigned char addr, unsigned char write_data);

    voidfill_byte(unsigned char fill_data);

    voiddelayms(unsigned char ms);

    voidinit_sys(void);            /*系统初始化函数*/

    voidDelay5Ms(void);

    unsigned charZKB1,ZKB2,ZKB3,ZKB4,ZKB5,ZKB6,ZKB7,ZKB8,ZKB9,ZKB10,ZKB11,ZKB12,ZKB13,ZKB14,ZKB15,ZKB16,ZKB17,ZKB18;

    unsigned charZKB19,ZKB20,ZKB21,ZKB22,ZKB23,ZKB24,ZKB25,ZKB26,ZKB27,ZKB28,ZKB29,ZKB30,ZKB31,ZKB32;

       unsigned char key_s, key_v, tmp,tmp1;

    char codestr[]={0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff,0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff,0x7e,0xbd,0xdb,0xe7,0xdb,0xbd,0x7e,0xff};

    void send_str();

    bit    scan_key();

    void proc_key();

    voiddelayms(unsigned char ms);

    voidsend_char(unsigned char txd);

           unsignedchar i;

       unsigned char p;

           unsigned char p1=0x00,p2,p3,p4;

    void main (void)

    {

    init_sys();

    ZKB1=40;            /*占空比初始值设定*/

      ZKB2=70;            /*占空比初始值设定*/

      ZKB3=20;            /*占空比初始值设定*/

      ZKB4=70;            /*占空比初始值设定*/

         ZKB5=30;            /*占空比初始值设定*/

      ZKB6=70;            /*占空比初始值设定*/

        ZKB7=80;            /*占空比初始值设定*/

      ZKB8=70;           /*占空比初始值设定*/

         ZKB9=50;            /*占空比初始值设定*/

      ZKB10=70;            /*占空比初始值设定*/

                 ZKB11=40;            /*占空比初始值设定*/

      ZKB12=40;            /*占空比初始值设定*/

         ZKB13=40;            /*占空比初始值设定*/

      ZKB14=70;            /*占空比初始值设定*/

        ZKB15=60;            /*占空比初始值设定*/

      ZKB16=70;            /*占空比初始值设定*/

         ZKB17=40;            /*占空比初始值设定*/

      ZKB18=70;            /*占空比初始值设定*/

             ZKB19=20;            /*占空比初始值设定*/

      ZKB20=70;            /*占空比初始值设定*/

         ZKB21=30;            /*占空比初始值设定*/

      ZKB22=70;            /*占空比初始值设定*/

        ZKB23=80;            /*占空比初始值设定*/

      ZKB24=70;            /*占空比初始值设定*/

         ZKB25=50;            /*占空比初始值设定*/

      ZKB26=70;            /*占空比初始值设定*/

                 ZKB27=40;            /*占空比初始值设定*/

      ZKB28=40;            /*占空比初始值设定*/

         ZKB29=40;            /*占空比初始值设定*/

      ZKB30=70;            /*占空比初始值设定*/

        ZKB31=60;            /*占空比初始值设定*/

      ZKB32=70;            /*占空比初始值设定*/

       SDA = 1;

       SCL = 1;

    // fill_byte(0x00);     // 全部填充0xff

      while(1)

      {      

           if(RI)                   //是否有数据到来

           {

              RI = 0;

              tmp = SBUF;              // 暂存接收到的数据

           //  tmp1=SBUF++;

              // dis_code[i]=SBUF;

                     // 数据传送到P0口

           //  str[1]=SBUF;

                 write_byte(0X00, tmp);

              //  write_byte(0X00,str[1]);

                  //  write_byte(0X01,tmp1);

               P0 = read_random(0X00);  // 循环读取24Cxx内容,并输出到P0口

           //  P2=  read_random(0X01);

                p1=  read_random(0X00);  

                   //  p2=   read_random(0X01);  

           //delayms(250);

              send_char(tmp);          // 回传接收到的数据

                   // send_str()    ;

           }

           tmp1 = str[i];

           write_byte(0X01, tmp1);

           i++;                  // 下一个字符

              P2 = read_random(0X01);  // 循环读取24Cxx内容,并输出到P0口  

           if (!P0_0) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_0)

             {

             ZKB1--;

           //  ZKB1=90;

             }

          }

            if (!P0_1) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_1)

             {

             ZKB1++;

             // ZKB1=20;

            }

         }

             if (!P0_2) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_2)

             {

             ZKB2--;

           //  ZKB1=90;

             }

          }

             if (!P0_3) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_3)

             {

             ZKB2++;

             // ZKB1=20;

            }

         }

             if (!P0_4) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_4)

             {

             ZKB3--;

           //  ZKB1=90;

             }

          }

            if (!P0_5) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_5)

             {

             ZKB3++;

             // ZKB1=20;

            }

         }

                if (!P0_6) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_6)

             {

             ZKB4--;

           //  ZKB1=90;

             }

          }

            if (!P0_7) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_7)

             {

             ZKB4++;

             // ZKB1=20;

            }

         }

                        if (!P2_0) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P2_0)

             {

             ZKB5--;

           //  ZKB1=90;

             }

          }

            if (!P2_1) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P2_1)

             {

             ZKB5++;

             // ZKB1=20;

            }

         }

          // if (!SBUF) //如果按了-键,减少占空比

         // {

          // Delay5Ms();

          // if (SBUF=0x02)

           // {

           // ZKB1--;

            // }

         // }

    /*对占空比值限定范围*/

    //if (ZKB1>99)ZKB1=1;

    //if (ZKB1<1)ZKB1=99;

      }

    }

    /******************************************************

    *函数功能:对系统进行初始化,包括定时器初始化和变量初始化*/

    voidinit_sys(void)            /*系统初始化函数*/

    {

      /*定时器TIME0初始化*/

      //TMOD=V_TMOD;

      TH0=V_TH0;

      TL0=V_TL0;

      TR0=1;

      ET0=1;

      EA=1;

           /*定时器TIME1初始化*/

           TMOD= 0x20;         // 定时器1工作于8位自动重载模式, 用于产生波特率

       TH1 = 0xFD;              //波特率9600

       TL1 = 0xFD;

       SCON = 0x50;         //设定串行口工作方式

       PCON &= 0xef;        // 波特率不倍增

       TR1 = 1;             //启动定时器1

    // IE = 0x0;            //禁止任何中断

    //  TH2=V_TH2;

    // TL2=V_TL2;

    // TR2=1;

    // ET2=1;

      //EA=1;

    }

    //延时

    voidDelay5Ms(void)

    {

    unsigned intTempCyc = 1000;

    while(TempCyc--);

    }

    /*中断函数*/

    void timer0(void)interrupt 1 using 2

    {

    static ucharclick=0;                  /*中断次数计数器变量*/

    TH0=V_TH0;                                    /*恢复定时器初始值*/

    TL0=V_TL0;

    ++click;

    if(click>=100) click=0;

    if(click<=ZKB1)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

      P1_0=0;

    else

      P1_0=1;

    if(click<=ZKB2)                        

      P1_1=0;

    else

      P1_1=1;

    if(click<=ZKB3)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

      P1_2=0;

    else

      P1_2=1;

    if(click<=ZKB4)                        

      P1_3=0;

    else

      P1_3=1;

       if (click<=ZKB5)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

      P1_4=0;

    else

      P1_4=1;

    if(click<=ZKB6)                        

      P1_5=0;

    else

      P1_5=1;

       if (click<=ZKB7)      /*当小于占空比值时输出低电平,高于时是高电平,从而实

    现占空比的调整*/

      P1_6=0;

    else

      P1_6=1;

    if(click<=ZKB8)                        

      P1_7=0;

    else

      P1_7=1;

    // if (click<=ZKB9)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

      //P2_0=0;

    //else

    // P2_0=1;

    //if(click<=ZKB10)                        

      //P2_1=0;

    //else

      //P2_1=1;

    //if(click<=ZKB11)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

    // P2_2=0;

    //else

    // P2_2=1;

    //if(click<=ZKB12)                        

      //P2_3=0;

    //else

      //P2_3=1;

       //  if(click<=ZKB13)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

      //P2_4=0;

    //else

    // P2_4=1;

    //if(click<=ZKB14)                        

    // P2_5=0;

    //else

      //P2_5=1;

        //if(click<=ZKB15)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

    // P2_6=0;

    //else

      //P2_6=1;

    //if(click<=ZKB16)                        

      //P2_7=0;

    //else

    // P2_7=1;      

        //if (click<=ZKB17)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

    // P3_0=0;

    //else

      //P3_0=1;

    //if(click<=ZKB18)                        

    // P3_1=0;

    //else

      //P3_1=1;

            if (click<=ZKB19)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空

    比的调整*/

      P3_2=0;

    else

      P3_2=1;

    //if(click<=ZKB20)                        

      //P3_3=0;

    //else

      //P3_3=1;

       //      if(click<=ZKB21)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

    // P3_4=0;

    //else

    // P3_4=1;

    if(click<=ZKB22)                        

      P3_5=0;

    else

      P3_5=1;

    if(click<=ZKB23)     /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

      P3_6=0;

    else

      P3_6=1;

    if(click<=ZKB24)                        

      P3_7=0;

    else

      P3_7=1;

    }

    voidsend_char(unsigned char txd)

    // 传送一个字符

    {

       SBUF = txd;

       while(!TI);              //等特数据传送

       TI = 0;                  //清除数据传送标志

    }

    void send_str()

    // 传送字串

    {

       unsigned char i = 0;

       while(str[i] != '\0')

       {

           SBUF = str[i];

           while(!TI);              // 等特数据传送

           TI = 0;                  // 清除数据传送标志

           i++;                 //下一个字符

       }  

    }  

    void start()

    // 开始位

    {

       SDA = 1;

       SCL = 1;

       _nop_();

       _nop_();

       SDA = 0;

       _nop_();

       _nop_();

       _nop_();

       _nop_();

       SCL = 0;

    }

    void stop()

    // 停止位

    {

       SDA = 0;

       _nop_();

       _nop_();

       SCL = 1;

       _nop_();

       _nop_();

       _nop_();

       _nop_();

       SDA = 1;

    }

    unsigned charshin()

    // 从AT24Cxx移入数据到MCU

    {

       unsigned char i,read_data;

       for(i = 0; i < 8; i++)

       {

           SCL = 1;

           read_data <<= 1;

           read_data |= (unsigned char)SDA;

           SCL = 0;

       }

       return(read_data);

    }

    bitshout(unsigned char write_data)

    // 从MCU移出数据到AT24Cxx

    {

       unsigned char i;

       bit ack_bit;

       for(i = 0; i < 8; i++)      // 循环移入8个位

       {

           SDA = (bit)(write_data & 0x80);

           _nop_();

           SCL = 1;

           _nop_();

           _nop_();

           SCL = 0;

           write_data <<= 1;

       }

       SDA = 1;          //读取应答

       _nop_();

       _nop_();

       SCL = 1;

       _nop_();

       _nop_();

       _nop_();

       _nop_();

       ack_bit = SDA;

       SCL = 0;

       return ack_bit;          // 返回AT24Cxx应答位

    }

    voidwrite_byte(unsigned char addr, unsigned char write_data)

    // 在指定地址addr处写入数据write_data

    {

       start();

       shout(OP_WRITE);

       shout(addr);

       shout(write_data);

       stop();

       delayms(10);      //写入周期

    }

    voidfill_byte(unsigned char fill_data)

    // 填充数据fill_data到EEPROM内

    {

       unsigned char i;

       for(i = 0; i < MAX_ADDR; i++)

       {

           write_byte(i, fill_data);

       }

    }

    unsigned charread_current()

    // 在当前地址读取

    {

       unsigned char read_data;

       start();

       shout(OP_READ);

       read_data = shin();

       stop();

       return read_data;

    }

    unsigned charread_random(unsigned char random_addr)

    // 在指定地址读取

    {

       start();

       shout(OP_WRITE);

       shout(random_addr);

       return(read_current());

    }

    voiddelayms(unsigned char ms)

    // 延时子程序

    {

       unsigned char i;

       while(ms--)

       {

           for(i = 0; i < 120; i++);

       }

    }

    上述程序中,单片机STC11F60串口只能接收到一个字节的16进制数,所以每次必须发送一个字节的16进制数,这样单片机才能接收。程序中的下面内容:

    if(RI)                  // 是否有数据到来

           {

              RI = 0;

              tmp = SBUF;              // 暂存接收到的数据

           //  tmp1=SBUF++;

              // dis_code[i]=SBUF;

                     // 数据传送到P0口

           //  str[1]=SBUF;

                 write_byte(0X00, tmp);

              //  write_byte(0X00,str[1]);

                  //  write_byte(0X01,tmp1);

               P0 = read_random(0X00);  // 循环读取24Cxx内容,并输出到P0口

           //  P2=  read_random(0X01);

                p1=  read_random(0X00);  

                   //  p2=   read_random(0X01);  

           //delayms(250);

              send_char(tmp);          // 回传接收到的数据

                   // send_str()    ;

           }

    这段代码实现的内容是将串口接收的一个字节数据存储到24C04中的0X00寄存器中,并输出到单片机的P0端口,并赋值给p1,最后有将接收到的数据从串口发送出去。

    tmp1 = str[i];

           write_byte(0X01, tmp1);

           i++;                 //下一个字符

              P2 = read_random(0X01);  // 循环读取24Cxx内容,并输出到P0口  

    这段代码实现的功能是将str[i]数组赋值给tmp1,并写入到24C04的0X01寄存器中,并输出到单片机的P2端口。

      if (!P0_0) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_0)

             {

             ZKB1--;

           //  ZKB1=90;

             }

          }

            if (!P0_1) //如果按了+键,增加占空比

          {

           Delay5Ms();

           if (!P0_1)

             {

             ZKB1++;

             // ZKB1=20;

            }

         }

    这段代码实现的功能是将P1_0端口的PWM方波的占空比减小或增大。

    void timer0(void)interrupt 1 using 2

    {

    static ucharclick=0;                  /*中断次数计数器变量*/

    TH0=V_TH0;                                    /*恢复定时器初始值*/

    TL0=V_TL0;

    ++click;

    if(click>=100) click=0;

    if(click<=ZKB1)      /*当小于占空比值时输出低电平,高于时是高电平,从而实现占空比的调整*/

      P1_0=0;

    else

      P1_0=1;

    这段代码的功能是利用定时器TIME0产生PWM方波。

    voidinit_sys(void)            /*系统初始化函数*/

    {

      /*定时器TIME0初始化*/

      //TMOD=V_TMOD;

      TH0=V_TH0;

      TL0=V_TL0;

      TR0=1;

      ET0=1;

      EA=1;

           /*定时器TIME1初始化*/

           TMOD= 0x20;         // 定时器1工作于8位自动重载模式, 用于产生波特率

       TH1 = 0xFD;              //波特率9600

       TL1 = 0xFD;

       SCON = 0x50;         //设定串行口工作方式

       PCON &= 0xef;        // 波特率不倍增

       TR1 = 1;             //启动定时器1

    // IE = 0x0;            //禁止任何中断

    //  TH2=V_TH2;

    // TL2=V_TL2;

    // TR2=1;

    // ET2=1;

      //EA=1;

    }

    这段代码的功能是利用初始化定时器TIME1,进行串口数据接收或发送。

    上述的一种具有12路PWM直流电机的串口遥控机器人,所述的是一种具有12路PWM直流电机的串口WIFI遥控机器人。

    附图说明

    下面结合附图和实施例对本实用新型进一步说明。

    图1为本实用电路图。

    图1中,1.单片机STC11F60,2.WIFI模块,3.24C04存储器,4.12路PWM直流电机。

    具体实施方式

    图1中,单片机STC11F60(1)的P3.0,P3.1端口连接WIFI模块,单片机STC11F60(1)的P3.4,P3.4端口连接24C04存储器。STC11F60单片机(1)的P1中的P1.0, P1.1, P1.2, P1.3, P1.4, P1.5, P1.6,P1.7端口,P3 中的P3.2, P3.5, P3.6, P3.7端口,上面总共12路IO口,每个IO口连接一路直流电机。

    图1中,单片机STC11F60(1)从串口接收或发送数据到WIFI模块(2),单片机STC11F60从24C04中读取或写入数据。STC11F60单片机(1)的P1中的P1.0, P1.1, P1.2, P1.3, P1.4, P1.5, P1.6,P1.7端口,P3 中的P3.2, P3.5, P3.6,P3.7端口,上面总共12路IO口,每个IO口产生一路PWM信号,并连接一路直流电机。

    图1



    发帖须知:

    1,发帖请遵守《计算机信息网络国际联网安全保护管理办法》、《互联网信息服务管理办法》、 《互联网电子公告服务管理规定》、《维护互联网安全的决定》等法律法规。

    2,请对您的言论负责,我们将保留您的上网记录和发帖信息。

    3,在此发帖表示认同我们的条款,我们有权利对您的言论进行审核、删除或者采取其他在法律、地方法规等条款规定之内的管理操作。
    内容:
    验证: 验证码,看不清楚?请点击刷新验证码 * 匿名发表需要进行验证!
     
           
    中国面包师贴吧-中国烘焙师贴吧- 弹性深蓝色可爱版右侧悬浮qq在线客服代码
    在线咨询 x
    有什么可以帮到您
    点击咨询
    -粤ICP备13040473号-2