搜索
bottom↓
回复: 25

中断时部分子程序不执行是为什么?

[复制链接]

出0入0汤圆

发表于 2016-4-13 23:25:56 | 显示全部楼层 |阅读模式
程序的问题是当漫反射接收到信号,向单片机P3^2脚发出低电平时,86步进电机没有按照程序转动,有大神能告诉我是为什么?
源程序奉上
#include <reg52.h>
#include <intrins.h>   

#define uch unsigned char
#define uint unsigned int

sbit get = P3^2;//转盘得物信号
sbit ULR = P0^1;//脉冲脚
sbit DIR = P0^2;//方向脚
sbit OE = P0^3;//74LS573 锁存器芯片输出使能

int volue = 0;//转动标志位
char t; //86电机循环用变量

uch idata buf[8];  //接收字符串用的数组

//**********************正向旋转相序表*****************************
unsigned char code FFW[9]=
{0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09,0X00};  
//28 BYJ-48 小电机正转相序表
// 上履带电机
unsigned char code FFW1[9]=
{0x80,0xc0,0x40,0x60,0x20,0x30,0x10,0x90,0X00};
//下履带电机
//**********************履带步进电机正转******************************

void receive (uch idata * d) //串口接收数据子程序
{
        int i; // 循环用的局部变量
        while(RI == 0);
        //用while语句确定已经接收完一组数据
        for(i=0; i<10; i++)
        {
                d[i] = SBUF; //把数据缓冲器的值写到定义的数组里
        }
        if(d[0] == 1)
        {
                volue = 1;         //转盘用的86电机,转动角度标志//45°
        }
        if(d[0] == 2)
        {
                volue = 2;         //同上 //0°
        }
        RI = 0;        //软件复位,为下次串口接收做准备
}

void delay(void)   //软件生成误差 0us          //控制上履带电机频率
{
    unsigned char a,b,c;
    for(c=1;c>0;c--)
        for(b=2;b>0;b--)
            for(a=197;a>0;a--);
}

void mdelay(void)                //86电机的脉冲频率 //软件计算误差0us;
{
        unsigned char a,b;
          for(b=185;b>0;b--)
      for(a=12;a>0;a--);
}

void motor_ffw(unsigned int n)         //上履带电机正向转动程序
{
   uch i;          //循环用局部变量
   uint j;          //循环用局部变量
   for (j=0; j<8*64*n; j++)          //电机减速比1/64,消除转速比,8脉冲一圈,n为圈数
    {
      for (i=0; i<8; i++)
        {
                P1 = FFW[i];                //P1口高8位控制上履带电机正转
                 delay();
        }
    }
}

void  motor_ffw1(unsigned int n)  //上履带电机正向转动程序
{
   uch i;
   uint j;
   for (j=0; j<8*64*n; j++)
    {
      for (i=0; i<8; i++)
        {
                  P1 = FFW1[i];                  //P1口高8位控制下履带电机正转
                 delay();
        }
    }
}

void go()
{
        motor_ffw(20);                //上履带20圈
}

void go1()        //由于期间会被中断打断并重新触发所以基本可以无视圈数
{
        motor_ffw1(20);                //下履带20圈
}

void init()          //初始化
{         
        OE = 1; //高阻态       
        ULR = 1; //86电机脉冲初始化
        EX0=1;//允许外部中断0       
        IT0=1; //有信号时保持中断,信号撤除中断停止
        SCON = 0X50;  //  0工作方式2,允许接收
        TMOD = 0X20; //          定时器模式,T0,工作方式2       
        PCON = 0X80;  //  波特率翻倍
        TH1 = 0XF3;         //          定时器赋初值
        TH0 = 0XF3;        //          定时器赋初值
        ES = 1;         //          串口中断开启
        EA = 1;         //         总中断开启
        TR1 = 1; //         开启定时器中断
}

void move()        //86电机转动45度程序
{
        for(t=0; t<25; t++)
        {
                ULR = 1;
                mdelay();
                ULR = 0;
                mdelay();
        }
}

//*************************主程序*********************************
void main()
{  
        init();
        go();
}

void wvolue() interrupt 4 // 串口中断  即扫描枪扫描并确定角度程序
{
        receive(buf);
}

void turn() interrupt 0          //转盘转动并送物中断程序
{
        switch(volue)
        {
                case 1:
                {
                  OE = 0;//锁存器输出使能       
              DIR = 1;
                  move();
                  go1();
                  DIR = 0;
                  move();
                  volue = 0;
                  break;
                }
                case 2:
                {
                        OE = 0;//锁存器输出使能       
                        go1();
                        volue = 0;               
                        break;
                }
                default:
                {
                        OE = 0;//锁存器输出使能       
                        DIR = 0;
                        move();
                        go1();
                        DIR = 1;
                        move();
                        volue = 0;       
                        break;
                }
        }
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

 楼主| 发表于 2016-4-13 23:28:10 | 显示全部楼层
用同样的子程序,单独驱动86步进电机时,86是正常工作的。
而且同在一个中断里的24-BYJ-48在中断的情况下可以正常运行。证明子程序go1()是可以调用的。求大神指点

出0入0汤圆

 楼主| 发表于 2016-4-14 00:04:22 | 显示全部楼层
防沉自顶

出0入0汤圆

发表于 2016-4-14 00:50:23 | 显示全部楼层
看一下编译器的优化设置,先设为不优化再调试看看

出0入0汤圆

 楼主| 发表于 2016-4-14 08:51:36 | 显示全部楼层
dzrs0620 发表于 2016-4-14 00:50
看一下编译器的优化设置,先设为不优化再调试看看

不懂 什么是优化设置,在哪里啊

出0入0汤圆

 楼主| 发表于 2016-4-14 08:53:01 | 显示全部楼层
柯铭凯 发表于 2016-4-14 08:51
不懂 什么是优化设置,在哪里啊

我用keil写的

出0入8汤圆

发表于 2016-4-14 09:12:21 | 显示全部楼层
估计程序 写的有问题,被keil优化掉了。

出0入0汤圆

发表于 2016-4-14 09:32:52 | 显示全部楼层
int volue = 0;//转动标志位,改成 volatile int volue = 0;//转动标志位 然后再试试

出0入0汤圆

 楼主| 发表于 2016-4-14 09:47:12 | 显示全部楼层
浮生莫若闲 发表于 2016-4-14 09:32
int volue = 0;//转动标志位,改成 volatile int volue = 0;//转动标志位 然后再试试

谢谢前辈,我这就去试,这样改的意义是?

出0入0汤圆

 楼主| 发表于 2016-4-14 09:48:32 | 显示全部楼层
kebaojun305 发表于 2016-4-14 09:12
估计程序 写的有问题,被keil优化掉了。

但是前辈,编译的时候没有提示有错误啊,连漏洞也不提示,菜鸟说的不对您耐心点哈

出0入8汤圆

发表于 2016-4-14 10:00:38 | 显示全部楼层
#define uch unsigned char
#define uint unsigned int


这种写法,在某些情况下会出问题的,怎么不用typedef

出0入8汤圆

发表于 2016-4-14 10:01:24 | 显示全部楼层
柯铭凯 发表于 2016-4-14 09:47
谢谢前辈,我这就去试,这样改的意义是?

你好好理解下 volatile  这个关键字的含义。 网上很容易搜到的。

出0入8汤圆

发表于 2016-4-14 10:02:03 | 显示全部楼层
柯铭凯 发表于 2016-4-14 09:48
但是前辈,编译的时候没有提示有错误啊,连漏洞也不提示,菜鸟说的不对您耐心点哈 ...

提示错误是 语法错误,和程序逻辑没有啥关系。

出0入8汤圆

发表于 2016-4-14 10:05:52 | 显示全部楼层
优化设置在这里  C51 选项卡下面的 Code Optimization-> Level   图中的优化等级是 "8:Reuse Common Entry Code"

本帖子中包含更多资源

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

x

出0入0汤圆

发表于 2016-4-14 10:28:58 | 显示全部楼层
拿示波器看一下脉冲信号,看看有没有输出,先排除是硬件的问题

出0入0汤圆

发表于 2016-4-14 10:41:33 | 显示全部楼层
中断里面调用这么多函数?

出0入0汤圆

 楼主| 发表于 2016-4-14 12:53:23 | 显示全部楼层
kebaojun305 发表于 2016-4-14 10:05
优化设置在这里  C51 选项卡下面的 Code Optimization-> Level   图中的优化等级是 "8:Reuse Common Entry  ...

前辈,请问优化等级应该怎么改?或者说改成哪个选项?

出0入0汤圆

 楼主| 发表于 2016-4-14 13:11:14 | 显示全部楼层
albert.hu 发表于 2016-4-14 10:28
拿示波器看一下脉冲信号,看看有没有输出,先排除是硬件的问题

脉冲试过了,没有问题的

出0入0汤圆

发表于 2016-4-14 13:15:54 | 显示全部楼层
是不是没定义中断函数(在中断向量表里面)

出0入8汤圆

发表于 2016-4-14 14:13:35 | 显示全部楼层
柯铭凯 发表于 2016-4-14 12:53
前辈,请问优化等级应该怎么改?或者说改成哪个选项?

前辈不敢当,那个数字越小,优化程度越低。  0是不优化。

出0入0汤圆

 楼主| 发表于 2016-4-14 14:57:04 | 显示全部楼层
kebaojun305 发表于 2016-4-14 14:13
前辈不敢当,那个数字越小,优化程度越低。  0是不优化。

前辈,试了,不顶用,还是不转

出0入8汤圆

发表于 2016-4-14 16:08:27 | 显示全部楼层
柯铭凯 发表于 2016-4-14 14:57
前辈,试了,不顶用,还是不转

那估计有可能是你写的程序有问题。

出0入0汤圆

 楼主| 发表于 2016-4-16 02:48:47 | 显示全部楼层
86电机子程序move()不调用的问题我已经解决了,附上源码。

出0入0汤圆

 楼主| 发表于 2016-4-16 02:49:06 | 显示全部楼层
#include <reg52.h>
#include <intrins.h>   

#define uch unsigned char
#define uint unsigned int

sbit ULR = P0^0;//脉冲脚
sbit DIR = P0^1;//方向脚
sbit OE = P0^2;//74LS573 锁存器芯片输出使能
sbit GET = P3^3;

int volue = 0;//转动标志位

uch idata buf[8];  //接收字符串用的数组

//**********************正向旋转相序表*****************************
unsigned char code FFW[9]=
{0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09,0X00};  
//28 BYJ-48 小电机正转相序表
// 上履带电机
unsigned char code FFW1[9]=
{0x80,0xc0,0x40,0x60,0x20,0x30,0x10,0x90,0X00};                  
//下履带电机
//**********************履带步进电机正转******************************
void delay20ms(void)   //误差 0us  //86电机的脉冲频率
{
    unsigned char a,b;                 
    for(b=215;b>0;b--)
        for(a=45;a>0;a--);
}

void move()        //86电机转动45度程序
{
        char t = 0; //86电机循环用变量
        OE = 0;
        for(t=0; t<25; t++)
        {
                ULR = 1;
                delay20ms();
                ULR = 0;
                delay20ms();
        }
}

void receive (uch idata * d) //串口接收数据子程序
{
        if(RI == 0);
        //用while语句确定已经接收完一组数据
        d[0] = SBUF; //把数据缓冲器的值写到定义的数组里
        if(d[0] == '1')
        {
                volue = 1;         //转盘用的86电机,转动角度标志//45°
        }
        if(d[0] == '2')
        {
                volue = 2;         //同上 //0°
        }
        else
        {
                volue = 0;
        }
        RI = 0;        //软件复位,为下次串口接收做准备
}

void delay(void)   //误差 0us   1ms
{
    unsigned char a,b;
    for(b=199;b>0;b--)
        for(a=1;a>0;a--);
}

void motor_ffw(unsigned int n)         //上履带电机正向转动程序
{
   uch i;          //循环用局部变量
   uint j;          //循环用局部变量
   for (j=0; j<8*64*n; j++)          //电机减速比1/64,消除转速比,8脉冲一圈,n为圈数
    {
      for (i=0; i<8; i++)
        {
                P1 = FFW[i];                //P1口高8位控制上履带电机正转
                 delay();
        }
    }
}

void  motor_ffw1(unsigned int n)  //上履带电机正向转动程序
{
   uch i;
   uint j;
   for (j=0; j<8*64*n; j++)
    {
      for (i=0; i<8; i++)
        {
                  P1 = FFW1[i];                  //P1口高8位控制下履带电机正转
                 delay();
        }
    }
}

void go()
{
        motor_ffw(1);                //上履带20圈
}

void go1()        //由于期间会被中断打断并重新触发所以基本可以无视圈数
{
        motor_ffw1(1);                //下履带20圈
}

void init()          //初始化
{         
        OE = 1; //高阻态       
        DIR = 0;
        EX1=1;//允许外部中断0       
        IT1=1; //有信号时保持中断,信号撤除中断停止
        EX0 = 1;
        IT0 = 1;
        SCON = 0X50;  //  0工作方式2,允许接收
        TMOD = 0X20; //          定时器模式,T1,工作方式2       
        PCON = 0X80;  //  波特率翻倍
        TH1 = 0XF3;         //          定时器赋初值
        TL1 = 0XF3;        //          定时器赋初值
        ES = 1;         //          串口中断开启
        EA = 1;         //         总中断开启
        TR1 = 1; //         开启定时器中断
}



//*************************主程序*********************************
void main()
{  
        ULR = 1; //86电机脉冲初始化
        while(1)
        {
                init();
                go();
        }
}

void wvolue() interrupt 4 // 串口中断  即扫描枪扫描并确定角度程序
{
        receive(buf);
}

void turn() interrupt 2          //转盘转动并送物中断程序
{
        switch(volue)
        {
                case 1:
                {
              DIR = 1;
                  move();
                  while(GET == 0)
                  {
                          go1();
                  }
                  DIR = 0;
                  move();
                  volue = 0;
                  break;
                }
                case 2:
                {
                    while(GET == 0)
                        {
                           go1();
                        }
                        volue = 0;               
                        break;
                }
                default:
                {
                        OE = 0;       
                        DIR = 0;
                        move();
                        while(GET == 0)
                    {
                      go1();
                    }
                        DIR = 1;
                        move();
                        volue = 0;
                        break;               
                }
        }

}


void try() interrupt 0          //转盘转动并送物中断程序
{
        move();
}

出0入0汤圆

 楼主| 发表于 2016-4-16 02:52:50 | 显示全部楼层
柯铭凯 发表于 2016-4-16 02:49
#include
#include   

具体原因我也没整明白,但是中断一开启只是执行了改变方向,并置高了ULR,然后P0^0再也不动作,百思不得其解之下,用中断0单独触发了move();结果正常,然后再次触发中断1时,move就正常调用了,具体原因不详。但是我改低了频率,目测和频率无关,因为改了频率之后还是不行,是直到使用了中断0单独触发之后才可以的,有大神能解读一下这种神秘现象?

出0入0汤圆

 楼主| 发表于 2016-4-16 02:53:27 | 显示全部楼层
PS不是优化问题,把优化降低后,连小电机都带不动了。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 03:17

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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