微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 求大神教小弟怎么实现小车PMW调速,程序怎么写?

求大神教小弟怎么实现小车PMW调速,程序怎么写?

时间:10-02 整理:3721RD 点击:
求大神教小弟怎么实现小车PMW调速,程序怎么写?

买块STC12系列的单片机,然后官网下份手册研究下,很简单的,配置下就好了~

小车的驱动一般分为左右轮。而每个驱动包含开关,设为E1。E2。前进A1和A2,后退B1和B2,(1为左轮,2为右轮)En就是控制是使能。可理解为开关,当En为0时,轮子不动,届时我们只要控制好En的开关时间,比如频率,这样就可以达到控制车速的效果,可与定时器的软件结合调节占空比,这就是最简单的车速控制,我之前有做成功,希望对你有帮助。

                                                               

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int
sbit IRIN=P3^3;        // 红外线接口       
sbit PWM1 = P1^0;//直流电机1的使能端
sbit PWM2=P1^1;//直流电机2的使能端
sbit s1=P1^2;//控制端
sbit s2=P1^3;
sbit s3=P1^4;
sbit s4=P1^5;
sbit E=P2^7;                //1602使能引脚
sbit RW=P2^6;                //1602读写引脚       
sbit RS=P2^5;                //1602数据/命令选择引脚
uchar CYCLE;       //定义周期
uchar distemp;      //红外线控制数字
uchar IRCOM[7];           //红外线解码数组
uchar PWM_ON ;                        //定义低电平时间

void delay0(unsigned char x)        //x*0.14MS  供IR_IN子函数
{
unsigned char i;
  while(x--)
{
  for (i = 0; i<13; i++) {}
}
}

void delay()               //  大概为5US     供BUSY子函数
{
        _nop_();
        _nop_();
}
void Delay(uint del)           //供1602初使化函数
{
        uint i,j;
        for(i=0;i<del;i++)
        for(j=0;j<=148;j++)
        {
        }       
}  
void Busy()      //液晶1602忙状态
{
        bit busy_flag = 1;
        P0 = 0xff;
        RS = 0;
        delay();
        RW = 1;
        delay();
        E = 1;
        while(1)
        {
                busy_flag = (bit)(P0 & 0x80);
                if(busy_flag == 0)
                {
                        break;
                }
        }
        E = 0;
}
void wcmd(uchar del)    //写指令
{
        RS = 0;
        delay();
        RW = 0;
        delay();
        E = 0;
        delay();
        P0 = del;
        delay();
        E = 1;
        delay();
        E = 0;
}

void wdata(uchar del)  //写数据
{
        delay();
        RS = 1;
        delay();
        RW = 0;
        delay();
        E = 0;
        delay();
        P0 = del;
    delay();
        E = 1;
        delay();
        E = 0;
}

void L1602_init(void)   //1602初使化
{
        Delay(15);
        wcmd(0x38);
        Delay(5);
        wcmd(0x38);
        Delay(5);
        wcmd(0x38);
        wcmd(0x38);
        Busy();
        wcmd(0x08);
        Busy();       
        wcmd(0x01);
        Busy();
        wcmd(0x06);
        Busy();
        wcmd(0x0c);
}

void L1602_string(uchar hang,uchar lie,uchar *p)  //读数据
{
        uchar a;
        if(hang == 1)
        {
                a = 0x80;
        }
        if(hang == 2)
        {
                a = 0xc0;
        }
        a = a + lie - 1;
        while(1)
        {
                Busy();
                wcmd(a);
                Busy();
                wdata(*p);
                a++;
                p++;                       
                if((*p == '\0')||(a==0x90)||(a==0xd0))
                {
                        break;
                }
        }
}

void Time0(void)       //定时器初初化
{
        TMOD = 0x01;                  //定时器设置 1ms in 11.0592M crystal
        TH0 = 0xFC;
        TL0 = 0x66;            //定时1mS
        ET0 = 1;
        EA = 1;
        TR0 = 1;                                   //定时器打开
}
void out1()               //外部中断初始化
{
EA=1;
PX1=1;               //外部中断优先
EX1=1;              //开外部中断
ET1=1;              //启动外部中断
IT1=1;              //电平触发方式
}
/********************************/
/*      定时中断                */
/********************************/
void tim(void) interrupt 1 using 1
{
        static unsigned char count = 0;
        TH0 = 0xFC;
        TL0 = 0x66;              //定时1mS
        if(count == PWM_ON)
        {
                PWM1 = 1;            //直流电机转
                PWM2=1;
        }
        count++;
        if(count == CYCLE)
        {
                count = 0;
                PWM1 = 0;       //直流电机不转
                PWM2=0;
        }
}

main()
{
        uchar PWM_Num;           //定义档位
        Time0();
        out1();
        IRIN=1;
        CYCLE = 20;                //时间可以调整 这个是100步调整 周期100ms 8位PWM就是256步
        PWM1 = 0;
        PWM2=0;
    L1602_init();               //初始化LCD      
        while(1)
        {
                if(distemp==5)
                     {
                              PWM_Num++;              //红外按键按一次,就给直流电机换一个档位
                                  if(PWM_Num==4)
                                {
                                        PWM_Num=0;
                        }
                                switch(PWM_Num)
                                {
                                case 0:
                                                P0=0x06;       
                                                PWM_ON=0;
                                                break;
                                       case 1:
                                                P0=0x5B;               
                                                PWM_ON=1;
                                                break;
                                       case 2:
                                                P0=0x4F;       
                                                PWM_ON=2;
                                                break;
                                       case 3:
                                                P0=0x66;               
                                                PWM_ON=3;
                                                break;
                                 default:
                                                break;
                             }
         }
}
}
void IR_IN() interrupt 2 using 0         //外部中断服务程序
{
  unsigned char j,k,N=0;
     EX1 = 0;   
         delay0(15);
         if (IRIN==1)
     { EX1 =1;
           return;
          }
                           //确认IR信号出现
  while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
    {delay0(1);}
for (j=0;j<4;j++)         //收集四组数据
{
  for (k=0;k<8;k++)        //每组数据有8位
  {
   while (IRIN)            //等 IR 变为低电平,跳过4.5ms的前导高电平信号。
     {delay0(1);}
    while (!IRIN)          //等 IR 变为高电平
     {delay0(1);}
     while (IRIN)           //计算IR高电平时长
      {
    delay0(1);
    N++;           
    if (N>=30)
         { EX1=1;
         return;}                  //0.14ms计数过长自动离开。
      }                        //高电平计数完毕               
     IRCOM[j]=IRCOM[j] >> 1;                  //数据最高位补“0”
     if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;}  //数据最高位补“1”
     N=0;
  }   //end for k
}   //end for j
   
   if (IRCOM[2]!=~IRCOM[3])
   { EX1=1;
     return; }
          switch(IRCOM[2])
   {
                case 0x18:
                        distemp = 2;
                L1602_string(1, 1,"State : Forward        " );
            s1=1;
            s2=0;
            s3=1;
            s4=0;
                        break;
                case 0x08:
                        distemp = 4;
                L1602_string(1, 1,"State :  Left     " );
            s1=1;
            s2=1;
            s3=1;
            s4=0;
                        break;
                case 0x1c:
                        distemp = 5;
                L1602_string(2, 1,"Speed changing~     " );
                        break;
                case 0x5a:
                        distemp = 6;
                L1602_string(1, 1,"State : Right   " );
            s1=1;
            s2=0;
            s3=1;
            s4=1;
                        break;
                case 0x52:
                        distemp = 8;
                L1602_string(1, 1,"State : Back          ");
            s1=0;
            s2=1;
            s3=0;
            s4=1;
                        break;
                case 0x4a:
                        distemp = 9;
                L1602_string(1, 1,"State :Zizhuan         ");
            s1=1;
            s2=0;
            s3=0;
            s4=1;
                        break;
   }
     EX1 = 1;
}


我什么都不会想制作简单一点的蓝牙小车可以不?

http://bbs.elecfans.com/jishu_334768_1_1.html

                                                      不错                           

程序很详细,对我有用

上一篇:求助 无人机
下一篇:51单片机输出问题

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top