打印

红外遥控直流电机转速问题

[复制链接]
2270|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
p422984186|  楼主 | 2013-7-18 10:12 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我想用51单片机IO模拟个PWM控制直流电机转速的的快慢,用红外实行调速,但直流电机始终不转

求大神 指出程序的错误。
主函数

void main()
{
    IRIN=1;                    //I/O口初始化
    BEEP=1;
    RELAY=1;

TCON = 0x01;                        //触发方式为脉冲负边沿触发
                TMOD |=0x10;                        //定时器1 工作方式 为16位
            TH1 = 0xfe;                                 //11.0592
            TL1 = 0x33;
                TR1=1;
                IE = 0x89;                             //允许总中断中断,使能 INT0 外部中断 T1中断
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
      
           while((flag_ad==1)&&(flag_stop!=1))
           {
                     pwm_control(speed);
           }
          
   }
/*************************************
红外中断

*************************************/
void IR_IN() interrupt 0 using 0
{
  unsigned char i,j,k,N=0;
     EX0 = 0;                     //关掉外部中断防止中断的再次发生进入检测引导码阶段(9ms的低电平4.5ms的高电平)
         delay(15);
         if (IRIN==1)
     { EX0 =1;                          //9ms的检测检测结束从新打开外部中断
           return;
          }
                           //确认IR信号出现
  while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
    {delay(1);}

for (j=0;j<4;j++)         //收集四组数据
{
          for (k=0;k<8;k++)        //每组数据有8位
          {
                   while (IRIN)            //等 IR 变为低电平,跳过4.5ms的引导高电平信号。
                     {delay(1);}
                    while (!IRIN)          //等 IR 变为高电平
                     {delay(1);}
                     while (IRIN)           //计算IR高电平时长(0和1的低电平的时长一样的,只要判断高电平时长超过0.56ms并小于1.12ms为1否则为0)
                      {
                            delay(1);
                            N++;           
                                if (N>=30)
                                         {
                                                 EX0=1;
                                                 return;
                                         }                  //0.14ms计数过长自动离开。
                      }                        //高电平计数完毕               
                     IRCOM[j]=IRCOM[j] >> 1;                  //数据最高位补“0”
                     if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;}  //高电平持续时间大于1.12ms则数据最高位补“1”
                     N=0;
          }
}
   
   if (IRCOM[2]!=~IRCOM[3])                  // 判断有没有误码(有责放弃没有判断键码)
   {
            EX0=1;
     return;
        }
         switch(IRCOM[2])
         {
            case 0x18:
                                        lcd_pos(0x49);
                                        for(i=0;i<=7;i++)
                                     lcd_wdat(jianma1[i]);
                                          flag_ad=1;
                                          flag_stop=0;
                                             break;                                                                                                                                                                                                         
       
                case 0x52:
                                         lcd_pos(0x49);
                                         for(i=9;i<=16;i++)                                                                   //停止
                                     lcd_wdat(jianma1[i]);
                                         PWM=0;PWM1=0;
                                         flag_stop=1;
                                                break;
       
                case 0x08:   lcd_pos(0x49);                                                                                //左转
                                         for(i=18;i<=25;i++)
                                     lcd_wdat(jianma1[i]);
                                          PWM=0;PWM1=1;delay1(20);PWM=0;PWM1=0;
                                           break;
               
                case 0x5a:         lcd_pos(0x49);                                                                                  //右转
                                         for(i=27;i<=35;i++)
                                     lcd_wdat(jianma1[i]);
                                          PWM=1;PWM1=0;delay1(20);PWM=0;PWM1=0;
                                           break;

                case 0x15:    lcd_pos(0x09) ;
                                          lcd_wdat(0x31);
                       
                                          speed=20;
                                          break;

                case 0x09:    lcd_pos(0x09);
                                          lcd_wdat(0x32);
                                          
                               
                                          speed=40;
                                          break;
       
                case 0x19:          lcd_pos(0x09);
                                          lcd_wdat(0x33);
                                         
                                          speed=60;
                                          break;

                case 0x0d:          lcd_pos(0x09);
                                          lcd_wdat(0x34);
                                       
                                          speed=80;
                                          break;
          }
          beep();
          EX0=1;
        }
/*************************************
[ t1 (0.5ms)中断] 中断中做 PWM 输出
  ------------1000/(0.02ms*250)=200Hz
*************************************/
void T1zd(void) interrupt 3                    //3 为定时器1的中断号  1 定时器0的中断号 0 外部中断1 2 外部中断2  4 串口中断
{
        TH1 = 0xfe;         //11.0592
        TL1 = 0x33;
         timer1++;
   
}
/**********************************************************/
void pwm_control (uchar k)
{                                                                                                 
  if(timer1>100) timer1=0;
  if(timer1<k)
  {        PWM=1;PWM1=1;}
  else
        { PWM=0;PWM1=0;}
}

/**********************************************************/
void delay(unsigned char x)    //x*0.14MS
{
unsigned char i;
  while(x--)
{
  for (i = 0; i<13; i++) {}
}
}

/**********************************************************/
void delay1(uint ms)
{
unsigned char y;
  while(ms--)
{
  for(y = 0; y<250; y++)
  {
   _nop_();
   _nop_();
   _nop_();
   _nop_();
  }
}
}
沙发
uet_cache| | 2013-7-18 11:27 | 只看该作者
晕了,你的主程序都没有大循环,一旦一开始执行的WHILE语句不满足,那你的程序跑哪去了。

使用特权

评论回复
评分
参与人数 1威望 +2 收起 理由
p422984186 + 2
板凳
huangfeng33| | 2013-7-18 15:51 | 只看该作者
呵呵,过来学习一下,最近也在弄直流电机控制.

使用特权

评论回复
地板
zeluo| | 2013-7-18 19:13 | 只看该作者
学习学习  直流电机的控制  这一块  还是需要好好钻研钻研的   顶一个   谢谢了  楼主

使用特权

评论回复
5
airwill| | 2013-7-19 12:50 | 只看该作者
直流电机始终不转

电压加上去了没有, 如果加了,  看样子电机有问题(或者电压不够), 加全电压上去看看还转不?

使用特权

评论回复
6
jlj3232655| | 2013-7-19 13:28 | 只看该作者
程序有可能有问题 也许电流太小电机驱动不起来

使用特权

评论回复
7
p422984186|  楼主 | 2013-7-22 14:41 | 只看该作者
已解决,谢谢各位

使用特权

评论回复
8
杨爱林林| | 2013-7-22 15:23 | 只看该作者
怎么解决的呀
楼主分享下

使用特权

评论回复
9
p422984186|  楼主 | 2013-7-23 18:46 | 只看该作者
#include <reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int

unsigned int timer1;
sbit PWM=P1^2;
sbit PWM1=P1^3;

uchar code jianma1[]="advance /stop    /left    /right   ";  
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
void delay(uchar x);  //x*0.14MS
void delay1(uint ms);

sbit IRIN = P3^2;         //红外接收器数据线
sbit BEEP = P1^5;         //蜂鸣器驱动线
sbit RELAY= P1^4;         //继电器驱动线

sbit LCD_RS = P2^6;            
sbit LCD_RW = P2^5;
sbit LCD_EN = P2^7;
uchar code  cdis1[ ] = {" Speed: "};
uchar code  cdis2[ ] = {"IR-CODE:"};
uchar IRCOM[7];
uchar speed;
uchar flag_stop;

void system_Ini()
{
    TMOD|= 0x10;                        //PWM  
        TCON = 0x01;                        //触发方式为脉冲负边沿触发
        TH1 = 0xfe;                         //11.0592
        TL1 = 0x33;
        TR1  = 1;
    IE =0x89;       
}


/*************************************
[ t1 (0.5ms)中断] 中断中做 PWM 输出
  ------------1000/(0.02ms*250)=200Hz
*************************************/
void T1zd(void) interrupt 3                    //3 为定时器1的中断号  1 定时器0的中断号 0 外部中断1 2 外部中断2  4 串口中断
{
        TH1 = 0xfe;         //11.0592
        TL1 = 0x33;
         timer1++;
   
}
/*******************************************************************/
/*                                                                 */
/*检查LCD忙状态                                                    */
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。      */
/*                                                                 */
/*******************************************************************/

bit lcd_busy()
{                          
    bit result;
    LCD_RS = 0;
    LCD_RW = 1;
    LCD_EN = 1;
    delayNOP();
    result = (bit)(P0&0x80);
    LCD_EN = 0;
    return(result);
}

/*******************************************************************/
/*                                                                 */
/*写指令数据到LCD                                                  */
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。                             */
/*                                                                 */
/*******************************************************************/

void lcd_wcmd(uchar cmd)

{                          
   while(lcd_busy());
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 0;
    _nop_();
    _nop_();
    P0 = cmd;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;  
}

/*******************************************************************/
/*                                                                 */
/*写显示数据到LCD                                                  */
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。                               */
/*                                                                 */
/*******************************************************************/

void lcd_wdat(uchar dat)
{                          
   while(lcd_busy());
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 0;
    P0 = dat;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;
}

/*******************************************************************/
/*                                                                 */
/*  LCD初始化设定                                                  */
/*                                                                 */
/*******************************************************************/

void lcd_init()
{
    delay1(15);                  
    lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);

    lcd_wcmd(0x0c);      //显示开,关光标
    delay1(5);
    lcd_wcmd(0x06);      //移动光标
    delay1(5);
    lcd_wcmd(0x01);      //清除LCD的显示内容
    delay1(5);
}

/*******************************************************************/
/*                                                                 */
/*  设定显示位置                                                   */
/*                                                                 */
/*******************************************************************/

void lcd_pos(uchar pos)
{                          
  lcd_wcmd(pos | 0x80);  //数据指针=80+地址变量
}
void  main()
{                uchar m;
            PWM=0;
                   PWM1=0;

  system_Ini();
       
   delay1(10);                 //延时
    lcd_init();
        lcd_pos(0);                //设置显示位置为第一行的第1个字符
          
     m = 0;
    while(cdis1[m] != '\0')
     {                         //显示字符
       lcd_wdat(cdis1[m]);
       m++;
     }

    lcd_pos(0x40);             //设置显示位置为第二行第1个字符
     m = 0;
    while(cdis2[m] != '\0')
     {
       lcd_wdat(cdis2[m]);      //显示字符
       m++;
     }                                        //初始化LCD      

  while(1)
  {
          if(flag_stop==1){ PWM=0;PWM1=0;}
        else
                {
    if(timer1>100) timer1=0;
            if(timer1<speed){ PWM=0;PWM1=0 ; }
   
              else        { PWM=1;PWM1=1;}
           }
       

   }


}

/*************************************
红外中断

*************************************/
void IR_IN() interrupt 0 using 0
{
  unsigned char i,j,k,N=0;
     EX0 = 0;                     //关掉外部中断防止中断的再次发生进入检测引导码阶段(9ms的低电平4.5ms的高电平)
         delay(15);
         if (IRIN==1)
     { EX0 =1;                          //9ms的检测检测结束从新打开外部中断
           return;
          }
                           //确认IR信号出现
  while (!IRIN)            //等IR变为高电平,跳过9ms的前导低电平信号。
    {delay(1);}

for (j=0;j<4;j++)         //收集四组数据
{
          for (k=0;k<8;k++)        //每组数据有8位
          {
                   while (IRIN)            //等 IR 变为低电平,跳过4.5ms的引导高电平信号。
                     {delay(1);}
                    while (!IRIN)          //等 IR 变为高电平
                     {delay(1);}
                     while (IRIN)           //计算IR高电平时长(0和1的低电平的时长一样的,只要判断高电平时长超过0.56ms并小于1.12ms为1否则为0)
                      {
                            delay(1);
                            N++;           
                                if (N>=30)
                                         {
                                                 EX0=1;
                                                 return;
                                         }                  //0.14ms计数过长自动离开。
                      }                        //高电平计数完毕               
                     IRCOM[j]=IRCOM[j] >> 1;                  //数据最高位补“0”
                     if (N>=8) {IRCOM[j] = IRCOM[j] | 0x80;}  //高电平持续时间大于1.12ms则数据最高位补“1”
                     N=0;
          }
}
   
   if (IRCOM[2]!=~IRCOM[3])                  // 判断有没有误码(有责放弃没有判断键码)
   {
            EX0=1;
     return;
        }
         switch(IRCOM[2])
         {                          
                 case 0x15:   
                          lcd_pos(0x09) ;
                                          lcd_wdat(0x31);
                                          speed=20;
                                          break;

                case 0x09:    lcd_pos(0x09);
                                          lcd_wdat(0x32);
                                          speed=40;
                                          break;
       
                case 0x19:          lcd_pos(0x09);
                                          lcd_wdat(0x33);
                                          speed=60;
                                          break;

                case 0x0d:          lcd_pos(0x09);
                                          lcd_wdat(0x34);
                                          speed=80;
                                          break;
                   case 0x52:
                                         lcd_pos(0x49);
                                         for(i=9;i<=16;i++)                                                                   //停止
                                     lcd_wdat(jianma1[i]);
                                        // PWM=0;PWM1=0;
                                         flag_stop=1;
                                                break;
                 case 0x18:                                                                                                         //启动前进
                                                lcd_pos(0x49);
                                                for(i=0;i<=7;i++)
                                             lcd_wdat(jianma1[i]);
                                                //  flag_ad=1;
                                                  flag_stop=0;
                                                     break;
               
                 case 0x08:   lcd_pos(0x49);                                                                                //左转
                                         for(i=18;i<=25;i++)
                                     lcd_wdat(jianma1[i]);
                                          PWM=0;PWM1=1;delay1(20);PWM=0;PWM1=0;
                                           break;
               
                case 0x5a:         lcd_pos(0x49);                                                                                  //右转
                                         for(i=27;i<=35;i++)
                                     lcd_wdat(jianma1[i]);
                                          PWM=1;PWM1=0;delay1(20);PWM=0;PWM1=0;
                                           break;
                                                
                                                                
          }
           EX0=1;
        }

/**********************************************************/
void delay(unsigned char x)    //x*0.14MS
{
unsigned char i;
  while(x--)
{
  for (i = 0; i<13; i++) {}
}
}

/**********************************************************/
void delay1(uint ms)
{
unsigned char y;
  while(ms--)
{
  for(y = 0; y<250; y++)
  {
   _nop_();
   _nop_();
   _nop_();
   _nop_();
  }
}
}

使用特权

评论回复
10
乌月明星稀| | 2013-8-30 13:51 | 只看该作者
用示波器调这个很容易的。

使用特权

评论回复
11
1849097455| | 2013-9-14 15:44 | 只看该作者

使用特权

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

本版积分规则

11

主题

50

帖子

1

粉丝