数码之家

 找回密码
 立即注册
搜索
查看: 3916|回复: 14

[C51] 跪求大神解惑 用STC12C5A60S2编写的程序不能正常运行

[复制链接]
发表于 2020-10-5 11:43:37 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
用STC12C5A60S2编写的程序不能正常运行,进入for中正反转循环就跳不出来,数码管也不亮了,其他红外按键也没用了,还有就是PWM给电机调速只有CCAP1H的值在200至255中间有效,跪求大神解惑。
#include<STC12C5A60S2.H> //头文件
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int  
typedef uchar INT8U;
typedef uint INT16U;
sbit PWM_1=P1^4;               //PWM输出端口  
sbit A1=P1^5;   //定义直流电机正端口
sbit A2=P1^6;   //定义直流电机负端口
sbit IR  = P3^2;          //定义红外脉冲数据接口
sbit beep = P3^6;    //蜂鸣器的位置
sbit P2_0 = P2^0;    //数码管位选接口
sbit P2_1 = P2^1;
sbit P2_2 = P2^2;
sbit P2_3 = P2^3;
sbit S1=P2^5;      //限位开关1
sbit S2=P2^6;     //限位开关2
#define D_A1   {A1=1;A2=0;}  //电机正转
#define D_A2   {A1=0;A2=1;} //电机反转
#define D_AOFF  {A1=1;A2=1;}  //电机停
uint W=0;      //定义速度等级
uchar A=0;      //方向标记 0,1
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
                        0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e};
uchar IRtime;   //检测红外高电平持续时间(脉宽)
uchar IRcord[4];    //此数组用于储存分离出来的4个字节的数据(用户码2个字节+键值码2个字节)
uchar IRdata[33];   //此数组用于储存红外的33位数据(第一位为引导码用户码16+键值码16)
bit IRpro_ok, IRok;  //第一个用于红外接收4个字节完毕。IRok用为检测脉宽完毕

void delay(uint z)
{
uint x,y;
for(x = z; x > 0; x--)
  for(y = 112; y > 0 ; y--);
}
void time0() interrupt 1   //定义定时器0
{
IRtime++;      //检测脉宽,1次为278us
}
void int0() interrupt 0     //定义外部中断0
{
static uchar num;     // 声明静态变量
static bit startflag;  //开始储存脉宽标志位
if(startflag)     //开始接收脉宽检测
{
  if( (IRtime < 53) && (IRtime >= 32) )
   num= 0;     
  IRdata[num] = IRtime;     
  IRtime = 0;     
  num++;      
  if(num== 33)      
  {
    IRok = 1;     
   num= 0;      
  }
}
else   
{
  IRtime = 0;      
  startflag = 1;   
}
}
void IRcordpro()        
{
uchar i, j, k, cord, value;
cord
k = 1;      
for(i = 0; i < 4; i++)
{
  for(j = 0; j < 8; j++)
  {
   cord = IRdata[k];     
   if(cord > 5)   
   value = value | 0x80;
   if(j < 7)
   {
    value = value >> 1;
   }
   k++;   
  }
  IRcord = value;   
  value = 0;      
}
IRpro_ok = 1;      
}

void init_pwm()
{
  CCON = 0;
CL = 0;
CH = 0;
CMOD = 0X00;
CCAPM1 =0x42;
CCAP1H=0x00;
CCAP1L=0x00;
CR=1;
   
}

  void pwm1_set (uchar a)
{
         CCAP1L= a;
         CCAP1H= a;
        
}

/**********************************************************************
      数码管显示
**********************************************************************/
void disp(void)
{
P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 0;     
P0=table[W%10];       //显示占空比个位
delay(1);      
P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 1;         
  
P2_0 = 1;P2_1 = 0;P2_2 = 1;P2_3 = 1;
P0=table[W/100];                    //显示占空比十位
delay(1);      
P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 1;     
        P2_0 = 1;P2_1 = 1;P2_2 = 0;P2_3 = 1;
P0=table[W/10%10];      //显示占空比百位
delay(1);      
P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 1;
P2_0 = 0;P2_1 = 1;P2_2 = 1;P2_3 = 1;
P0=table[A];         //显示方向
delay(1);     
P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 1;     
}
void san()
{
uchar i;

  while(1)
  {     
        
     for(i=0;i<2;i++)
     {
            if(S1==0)
         D_A1;   
            if(S2==0)
         D_A2;
      }
     if(i==2)
      {
         i=0;
      }
       D_AOFF;
       beep = 0; delay(100); beep = 1;
  
   }
}      
void qi()
{
uchar i;

  while(1)
  {     
        
for(i=0;i<6;i++)
  {
                    if(S1==0)
          D_A1;   
                    if(S2==0)
          D_A2;
  }
if(i==6)
{
           i=0;
         }
         D_AOFF;
         beep = 0; delay(100); beep = 1;
  
   }
}
void main()
{
init_pwm();
EA = 1;
TMOD |= 0x02;
TH0 = 0x00;  
TL0 = 0x00;
ET0 = 1;   
TR0 = 1;     
IT0 = 1;   
EX0 = 1;   
        disp();
pwm1_set (1);
         W = 220;
while(1)
{
  if(IRok)                     
  {   
   IRcordpro();
   IRok = 0;
   if(IRpro_ok)  
   {
          switch(IRcord[2])
       {
         case 0x45:   //按键1
                                         beep = 0; delay(15); beep = 1;
      san();  
         break;
         case 0x46:    //按键2
       beep = 0; delay(15); beep = 1;
                                         qi();
         break;
         case 0x47:    //按键3
       beep = 0; delay(15); beep = 1;
                                          D_AOFF;
         break;

        case 0x5a:    //按键 左 占空比控制 速度增加
       beep = 0; delay(15); beep = 1;     
                                          W+=5;
                                          pwm1_set(W);
                                          if(W > 255)                                 
                                          {  
                                             W=255;
                                           }
         break;
         case 0x08:   //按键 右 占空比控制 速度减小
         beep = 0; delay(15); beep = 1;
                                           W-=5;
                                           pwm1_set(W);
                                           if(W < 200)                                 
                                           {
                                               W=200;
                                            }
      
          break;
     
        }
    IRpro_ok = 0;
   }
  }

}
}

发表于 2020-10-5 19:31:14 | 显示全部楼层
好几个for循环,是哪个跳不出来?
循环跳不出来的原因,就是循环条件没有满足。仔细检查一下循环变量的相关的问题。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-5 20:46:13 | 显示全部楼层
ahyu99 发表于 2020-10-5 19:31
好几个for循环,是哪个跳不出来?
循环跳不出来的原因,就是循环条件没有满足。仔细检查一下循环变量的相关 ...

就是san()和qi()里面的for循环,两个是一样的,不管是按键1或者按键2按下运行后就全部失灵了,按键没用了,数码管不显示了,电机就在两个限位间不停正反转,不会按照设置次数停止
回复 支持 反对

使用道具 举报

发表于 2020-10-5 21:30:27 来自手机浏览器 | 显示全部楼层
这两个for循环里的while(1)删掉试试。

有这条语句存在,进去就别想再出来,除非你其他部分全放中断里,不过好像没这么干的:lol:
回复 支持 反对

使用道具 举报

发表于 2020-10-5 21:32:20 来自手机浏览器 | 显示全部楼层
说错了,不是for里的,是san和qi里的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-5 23:00:08 | 显示全部楼层
lzh_23 发表于 2020-10-5 21:32
说错了,不是for里的,是san和qi里的

删除试过了,删除后限位开关2也不起作用了,只会一直正转,现在关键是不会只运行for设置的几个来回就转到下面的停止并且蜂鸣器长响这一条上
回复 支持 反对

使用道具 举报

发表于 2020-10-6 16:51:44 | 显示全部楼层
本帖最后由 zj97czb 于 2020-10-6 17:12 编辑

你这问题还是多多,只符合你自己的想当然:
1 :这个问题简单,先它:还有就是PWM给电机调速只有CCAP1H的值在200至255中间有效。           
   case 0x08:   //按键 右 占空比控制 速度减小
         beep = 0; delay(15); beep = 1;
                                           W-=5;
                                           pwm1_set(W);
                                           if(W < 200)                                 
                                           {
                                               W=200;//你这里限制了它不能少于200
                                            }



2:不显示的问题:disp();要放在主循环里,如:
while(1)
        {
            disp();
                if(IRok)                     
                {   
                 IRcordpro();
        但最好还是开定时器1,来个10ms的定时,主要处理  disp();        

3:关于正反转次数和停不下来,while(1)是不能这样写的,但写成这样的可以的 while(数字--),
这个问题你没有说明具体的运作过程,帮不了你。反正你的程序san()、qi()这样不合适,在主程序中也就该和
disp()在一起,不能放在按键程序里。按键程序应该是按一次执行一次,不合适一直按着







回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-6 22:30:24 | 显示全部楼层
zj97czb 发表于 2020-10-6 16:51
你这问题还是多多,只符合你自己的想当然:
1 :这个问题简单,先它:还有就是PWM给电机调速只有CCAP1H的值 ...

多谢你的指教,因为是才接触单片机所以很多问题搞不明白。希望你能不吝赐教:
1:pwm设置最小值为200是因为我专门调试转速时,低于200转速就不再变化了,怎么都找不到原因,为了调速时方便所以才那样设置的。
2:数码管不显示disp() 我那个位置都放置过了都不行,只有把程序改为按下按键1为一直正转,就能正常显示,也能调速,只要一调用San() 子涵数就全不行了。
3:编程序的目的是电机在两个行程开关中间反复运行,有时需要3个来回然后停止,有时需要7个来回停止,还有需要更多的,所以需要设置快捷键,可惜设置两个就不能正常运行了。
回复 支持 反对

使用道具 举报

发表于 2020-10-7 13:49:18 | 显示全部楼层
本帖最后由 zj97czb 于 2020-10-7 13:54 编辑

调速软件设置应该没有问题,可能硬件有问题
下面是改好的,应该能用,毕竟没有硬件试验。

#include"STC12C5A60S2.H" //头文件
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int  
typedef uchar INT8U;
typedef uint INT16U;
sbit PWM_1=P1^4;               //PWM输出端口  
sbit A1=P1^5;   //定义直流电机正端口
sbit A2=P1^6;   //定义直流电机负端口
sbit IR  = P3^2;          //定义红外脉冲数据接口
sbit beep = P3^6;    //蜂鸣器的位置
sbit P2_0 = P2^0;    //数码管位选接口
sbit P2_1 = P2^1;
sbit P2_2 = P2^2;
sbit P2_3 = P2^3;
sbit S1=P2^5;      //限位开关1
sbit S2=P2^6;     //限位开关2
#define D_A1   {A1=1;A2=0;}  //电机正转
#define D_A2   {A1=0;A2=1;} //电机反转
#define D_AOFF  {A1=1;A2=1;}  //电机停
uint W=0;      //定义速度等级
uchar A=0;      //方向标记 0,1
uchar run;
bit run_ok;
uchar code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,
                                                                                                0x82,0xf8,0x80,0x90,
                                                                                                0x88,0x80,0xc6,0xc0,0x86,0x8e};
uchar IRtime;   //检测红外高电平持续时间(脉宽)
uchar IRcord[4];    //此数组用于储存分离出来的4个字节的数据(用户码2个字节+键值码2个字节)
uchar IRdata[33];   //此数组用于储存红外的33位数据(第一位为引导码用户码16+键值码16)
bit IRpro_ok, IRok;  //第一个用于红外接收4个字节完毕。IRok用为检测脉宽完毕

void delay(uint z)
{
        uint x,y;
        for(x = z; x > 0; x--)
                for(y = 112; y > 0 ; y--);
}


void time0() interrupt 1   //定义定时器0
{
        IRtime++;      //检测脉宽,1次为278us
}

void int0() interrupt 0     //定义外部中断0
{
        static uchar num;     // 声明静态变量
        static bit startflag;  //开始储存脉宽标志位
        if(startflag)     //开始接收脉宽检测
        {
                if( (IRtime < 53) && (IRtime >= 32) )
                 num= 0;     
                IRdata[num] = IRtime;     
                IRtime = 0;     
                num++;      
                if(num== 33)      
                {
                        IRok = 1;     
                 num= 0;      
                }
        }
        else   
        {
                IRtime = 0;      
                startflag = 1;   
        }
}

void IRcordpro()        
{
        uchar i, j, k, cord, value;
        //cord
        k = 1;      
        for(i = 0; i < 4; i++)
        {
                for(j = 0; j < 8; j++)
                {
                 cord = IRdata[k];     
                 if(cord > 5)   
                 value = value | 0x80;
                 if(j < 7)
                 {
                        value = value >> 1;
                 }
                 k++;   
                }
                IRcord = value;   
                value = 0;      
        }
        IRpro_ok = 1;      
}

void init_pwm()
{        
                CCON = 0;
        CL = 0;
        CH = 0;
        CMOD = 0X00;
        CCAPM1 =0x42;
        CCAP1H=0x00;
        CCAP1L=0x00;
        CR=1;
                        
}

  void pwm1_set (uchar a)
{
         CCAP1L= a;
         CCAP1H= a;

}

/**********************************************************************
      数码管显示
**********************************************************************/
void disp(void)
{
        P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 0;     
        P0=table[W%10];       //显示占空比个位
        delay(1);      
        P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 1;         
               
        P2_0 = 1;P2_1 = 0;P2_2 = 1;P2_3 = 1;
        P0=table[W/100];                    //显示占空比十位
        delay(1);      
        P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 1;
        
        P2_0 = 1;P2_1 = 1;P2_2 = 0;P2_3 = 1;
        P0=table[W/10%10];      //显示占空比百位
        delay(1);      
        P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 1;
        
        P2_0 = 0;P2_1 = 1;P2_2 = 1;P2_3 = 1;
        P0=table[run%10];         //显示次数
        delay(1);     
        P2_0 = 1;P2_1 = 1;P2_2 = 1;P2_3 = 1;     
}

void main()
{
        
        init_pwm();
        EA = 1;
        TMOD |= 0x02;
        TH0 = 0x00;  
        TL0 = 0x00;
        ET0 = 1;   
        TR0 = 1;     
        IT0 = 1;   
        EX0 = 1;   

        pwm1_set (1);
   W = 220;
        
        while(1)
               
        {
                disp();
               
               
                if(run>0)
                        
                {
                 if(S1==0)
                 {   
                         D_A1;
                         if(run_ok)
                         {
                                 run--;//往复次数
                           run_ok=0;
                         }
                        }
     if(S2==0)
                 {
                         D_A2;
                                run_ok=1;
                 }        
          }
                else
                {D_AOFF;run=0;run_ok=0;}
               
                if(IRok)                     
                {   
                 IRcordpro();
                 IRok = 0;
                 if(IRpro_ok)  
                 {
          switch(IRcord[2])
       {
         case 0x45:   //按键1
                    beep = 0; delay(15); beep = 1;
                                                                                run=2;D_A1;  
                                                                                break;
         case 0x46:    //按键2
                                                                                beep = 0; delay(15); beep = 1;
                    run=7;D_A1;
                                                                                break;
         case 0x47:    //按键3
                                                                                beep = 0; delay(15); beep = 1;
                    run=0;
                                                                                D_AOFF;
                                                                                break;

        case 0x5a:    //按键 左 占空比控制 速度增加
                                                                                beep = 0; delay(15); beep = 1;     
                                                                                W+=5;
                                                                                pwm1_set(W);
                                                                                if(W > 255)                                 
                                                                                {  
                                                                                         W=255;
                                                                                 }
                                                                                break;
         case 0x08:   //按键 右 占空比控制 速度减小
                                                                                beep = 0; delay(15); beep = 1;
                                                                                 W-=5;
                                                                                 pwm1_set(W);
                                                                                 if(W < 200)                                 
                                                                                 {
                                                                                                 W=200;
                                                                                        }

          break;

        }
    IRpro_ok = 0;
   }
  }

        }
}
回复 支持 反对

使用道具 举报

发表于 2020-10-7 17:22:37 | 显示全部楼层
子函数只有while(1)没有break怎么跳出来
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-10-7 21:50:09 | 显示全部楼层
zj97czb 发表于 2020-10-7 13:49
调速软件设置应该没有问题,可能硬件有问题
下面是改好的,应该能用,毕竟没有硬件试验。

谢谢你,现在不在家,等回家了试试。
回复 支持 反对

使用道具 举报

发表于 2020-10-9 12:39:35 来自手机浏览器 | 显示全部楼层
写个while(1),里边又不加break,这不就直接一直循环了。
回复 支持 反对

使用道具 举报

发表于 2020-10-9 15:43:44 | 显示全部楼层
while(1)这个不能随便用   2个就死定了哈哈哈
回复 支持 反对

使用道具 举报

发表于 2020-10-11 21:20:14 | 显示全部楼层
while(1)注定是死循环
回复 支持 反对

使用道具 举报

发表于 2020-10-21 10:17:47 | 显示全部楼层
  while(1)
是死循环,一直运行到世界末日!所以你要用
  while(限位开关==1)//常闭的限位开关 或 while(限位开关==0)//常开的限位开关
只有这样,在限位开关状态改变时才能退出循环

回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-5-23 10:53 , Processed in 0.171601 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表