cityfuture 发表于 2013-12-27 12:33:44

stc12c5a 调用同一个函数,为何谁在后面谁有效,

本帖最后由 cityfuture 于 2013-12-27 13:40 编辑

switch(EncoderProcess()){
            case E_RIGHT: inc();break;
                       
            case E_LEFT: dec();break;
                                                                       }

switch(EncoderProcess1()){
            case E_RIGHT: inc();break;
                       
            case E_LEFT: dec();break;
                                                                      }
这个两个switch 哪个放在后面,哪个有效,放在前面的无效,这样是什么原因?去掉其中的一个剩下的有效

                  void inc()
{
num++;
if (num > 99){
num=0;
}
}





                   void dec()
{
num--;
if (num < -20){
num=0;
}
}

hbw_819 发表于 2013-12-27 12:48:14

你没有把整个程序放上来,不知道你的程序是怎么走的啊~额~~请楼主最好贴全程序吧~

tlsmf 发表于 2013-12-27 12:53:02

我也遇到过这个问题,不知道为什么。就是在主程序当中调用子程序或者是执行几条语句,每当配置定时器1的时候有时就是有几行程序不执行,注释掉配置定时器程序或者把那几行程序换个位置就执行了。

a8212723 发表于 2013-12-27 13:17:35

是不是被优化掉了 ?你用的是keil么?可以更改下它的优化级别试一试

a8212723 发表于 2013-12-27 13:18:27

在num的定义前加个volatile关键字试一试

cityfuture 发表于 2013-12-27 13:38:43

hbw_819 发表于 2013-12-27 12:48
你没有把整个程序放上来,不知道你的程序是怎么走的啊~额~~请楼主最好贴全程序吧~ ...

sbit PINC = P1^0; //定义IO
sbit PIND = P1^2;
sbit PINA = P3^5; //定义IO
sbit PINB = P3^6;
#define uchar unsigned char
#define uint unsigned int
#define cycle 1
#define NULL0 0
#define E_RIGHT 0x0e
#define E_LEFT 0x0f
uchar WheelNow,WheelOld,RightCount,LeftCount;
volatile int num=0;

uchar WheelRight()
{
LeftCount=0;
RightCount++;
if (RightCount>=cycle){
RightCount=0;
return(E_RIGHT);
} else return(NULL0);
}



uchar WheelLeft()
{
RightCount=0;
LeftCount++;
if (LeftCount>=cycle){
LeftCount=0;
return(E_LEFT);
} else return(NULL0);
}



uchar EncoderProcess()
{
uchar keytmp;
PINA = 1;
PINB = 1;
WheelNow=WheelNow<<1;
if (PINA==1) WheelNow=WheelNow+1; // 读 PINA
WheelNow=WheelNow<<1;
if (PINB==1) WheelNow=WheelNow+1;
WheelNow=WheelNow & 0x03;
if (WheelNow==0x00) return(NULL0);
keytmp=WheelNow;
keytmp ^=WheelOld;
if (keytmp==0) return(NULL0);
if (WheelOld==0x01 && WheelNow==0x02){ //
WheelOld=WheelNow;
return(WheelLeft()); //
}
else if (WheelOld==0x02 && WheelNow==0x01){ //否
WheelOld=WheelNow;
return(WheelRight()); //
}
WheelOld=WheelNow; //
return(NULL0); //

uchar EncoderProcess1()
{
uchar keytmp;
PINC = 1;
PIND = 1;
WheelNow=WheelNow<<1;
if (PINC==1) WheelNow=WheelNow+1;
WheelNow=WheelNow<<1;
if (PIND==1) WheelNow=WheelNow+1;
WheelNow=WheelNow & 0x03;
if (WheelNow==0x00) return(NULL0);
keytmp=WheelNow;
keytmp ^=WheelOld;
if (keytmp==0) return(NULL0);
if (WheelOld==0x01 && WheelNow==0x02){
WheelOld=WheelNow;
return(WheelLeft());
}
else if (WheelOld==0x02 && WheelNow==0x01){ /
WheelOld=WheelNow;
return(WheelRight()); //
}
WheelOld=WheelNow; //
return(NULL0); //
}

lcw_swust 发表于 2013-12-27 15:47:13

楼主用的两个旋转编码器吧?
WheelNow,WheelOld,也应该分别定义两个。
还要注意写法:
if (WheelOld==0x01 && WheelNow==0x02)最好是改成if ((WheelOld==0x01) && (WheelNow==0x02))

cityfuture 发表于 2013-12-28 13:03:15

lcw_swust 发表于 2013-12-27 15:47
楼主用的两个旋转编码器吧?
WheelNow,WheelOld,也应该分别定义两个。
还要注意写法:


全部变量名函数重新定义后可以使用,但出现了其他问题
if(i==5000)
                {
                   //DisplayListChar(0, 1, "wrong 02");

                        ;

                     }

       if(i==10000){

                        itoa(num, net);
                          DisplayListChar(8, 1, "    ");
                        DisplayListChar(0, 0, "tem now");
                       DisplayListChar(0, 1, "tem set");
                        DisplayListChar(8, 1, net);

                       }
                程序结构如上,while(1)
{i++;}每2000循环一次

       switch(EncoderProcess()){
            case E_RIGHT: inc();break;
                       
            case E_LEFT: dec();break;
                                                                       }
               

   switch(EncoderProcess1()){
             case E_RIGHT: inc1();break;
                       
             case E_LEFT: dec1();break;

                                                                       }
一个写在上面i==5000时,一个写在i=10000,写在i=5000的会出现转很多圈检测一步的情况,i=10000处正常
都写在i=5000处,全个无法运行
都写在i=1000处,两个都可以正常运行
               

lcw_swust 发表于 2013-12-28 13:27:58

cityfuture 发表于 2013-12-28 13:03
全部变量名函数重新定义后可以使用,但出现了其他问题
if(i==5000)
                {


可以上个完整程序么?你这样子说得我看不太懂。

一匹狼 发表于 2013-12-28 14:13:43

lcw_swust 发表于 2013-12-27 15:47
楼主用的两个旋转编码器吧?
WheelNow,WheelOld,也应该分别定义两个。
还要注意写法:


这个不影响,注意优先级就行了,不太喜欢画蛇添足

lcw_swust 发表于 2013-12-28 14:22:06

一匹狼 发表于 2013-12-28 14:13
这个不影响,注意优先级就行了,不太喜欢画蛇添足

你看完程序了吗?
假如在调用EncoderProcess()之后,WheelOld=1,再进入EncoderProcess1()函数时WheelOld是多少?

一匹狼 发表于 2013-12-28 15:18:40

lcw_swust 发表于 2013-12-28 14:22
你看完程序了吗?
假如在调用EncoderProcess()之后,WheelOld=1,再进入EncoderProcess1()函数时WheelOld ...

见注释
uchar EncoderProcess1()                //若WheelOld=1,WheelNow=1
{
        uchar keytmp;                       
        PINC = 1;
        PIND = 1;
        WheelNow=WheelNow<<1;        //WheelOld=1,WheelNow=2
        if (PINC==1)
                WheelNow=WheelNow+1;//WheelOld=1,WheelNow=3
        WheelNow=WheelNow<<1;        //WheelOld=1,WheelNow=6
        if (PIND==1)
                WheelNow=WheelNow+1;//WheelOld=1,WheelNow=7
        WheelNow=WheelNow & 0x03;//WheelOld=1,WheelNow=3
        if (WheelNow==0x00)
                return(NULL0);
        keytmp=WheelNow;                //keytmp=3
        keytmp ^=WheelOld;        //keytmp=2
        if (keytmp==0)
                return(NULL0);
        if (WheelOld==0x01 && WheelNow==0x02)
        {
                WheelOld=WheelNow;
                return(WheelLeft());
        }
        else if (WheelOld==0x02 && WheelNow==0x01)
        {
                WheelOld=WheelNow;
                return(WheelRight());
        }
        WheelOld=WheelNow;                 //WheelOld=3
        return(NULL0);
}

一匹狼 发表于 2013-12-28 15:23:00

本帖最后由 一匹狼 于 2013-12-28 15:28 编辑

cityfuture 发表于 2013-12-27 13:38
sbit PINC = P1^0; //定义IO
sbit PIND = P1^2;
sbit PINA = P3^5; //定义IO


EncoderProcess函数调用结束处忘了括号},c51中函数可嵌套调用但不能嵌套定义

lcw_swust 发表于 2013-12-28 16:02:59

本帖最后由 lcw_swust 于 2013-12-28 16:05 编辑

一匹狼 发表于 2013-12-28 15:18
见注释

看来你是看了程序的,但是你没弄懂作者的目的:
旋转编码器有两个脚接到IO口,假设当正转时两脚的电平变化是11-10-00-01-11,当反转时电平为11-01-00-10-11,所以需要判断电平变化的顺序才知道编码器是正转还是反转。
EncoderProcess()读取PINA、PINB的电平,进入函数时,WheelOld应为上次调用EncoderProcess()的WheelNow,然后由当前的WheelNow与之前的WheelNow确定转动放向。
EncoderProcess1()读取PINC、PIND的电平,这就是另一个编码器了,进入函数时,WheelOld应为上次调用EncoderProcess1()的WheelNow,应当与EncoderProcess()无关,
所以说楼主的程序错了。

一匹狼 发表于 2013-12-28 16:57:43

lcw_swust 发表于 2013-12-28 16:02
看来你是看了程序的,但是你没弄懂作者的目的:
旋转编码器有两个脚接到IO口,假设当正转时两脚的电平变 ...

嗯,我明白了,这两个旋转编码器相互独立,互不影响,所以WheelNow,WheelOld应该分别定义两个。
也许是我没说清楚吧
注意写法:
if (WheelOld==0x01 && WheelNow==0x02)最好是改成if ((WheelOld==0x01) && (WheelNow==0x02))
我的意思是写法无关紧要,‘&&’ 优先级比‘==’低,括号应该是没有必要添加
谢谢哈~当时确实没怎么认真理解作者意图
我还想请教下:WheelRight应该是正转吧,所以        if (WheelOld==0x01 && WheelNow==0x02)                //01 11
        {
                WheelOld=WheelNow;
                return(WheelLeft());
        }是不是应该改成调用WheelRight();我对旋转编码器不太了解,进来涨涨知识{:smile:}

lcw_swust 发表于 2013-12-28 17:26:23

本帖最后由 lcw_swust 于 2013-12-28 17:30 编辑

一匹狼 发表于 2013-12-28 16:57
嗯,我明白了,这两个旋转编码器相互独立,互不影响,所以WheelNow,WheelOld应该分别定义两个。
也许是我 ...

唉,说来惭愧,那么多的运算符,我就只记得*/的优先级大于+-,所以说为了避免引起误解,总喜欢加括号。
上面我所说的正反转的编码只是随便举个例子,究竟是不是正转也得看实际的电路以及参照物。
鼠标的滚轮就是个旋转编码器,有兴趣可以拆来玩玩。
如果把鼠标旋转180度使用,那么正转是不是变成反转了?

一匹狼 发表于 2013-12-28 17:32:41

lcw_swust 发表于 2013-12-28 17:26
唉,说来惭愧,那么多的运算符,我就只记得*/的优先级大于+-,所以说为了避免引起误解,总喜欢加括号。
...

嗯,这倒也是,我有点钻牛角尖了。。。

bhy 发表于 2013-12-29 10:40:09

试着每个switch后,加上个
default: break

qllaoda1 发表于 2013-12-29 10:58:16

Keil会优化掉与输出无关的变量的,如果你用仿真的方式去看很可能啥都看不到,如果你想用单片机来学习C语言,不建议用仿真器,把结果用什么方式输出来看就是了。

li448475953 发表于 2013-12-29 11:29:41

EncoderProcess1()和上面那个函数的返回值是一样的所以出现上面的情况

dzdz 发表于 2013-12-29 12:40:52

读编码器就读好了,还要判断专项干什么?要驱动指示灯给用户看吗?

dzdz 发表于 2013-12-30 13:05:17

刚仔细看了前边那些代码,i=10000,i=5000,i=1000,都是为什么呢?都放在什么地方呢?看不懂,还是要全部贴上来的好,或者干脆把C文件贴上吧
对了,楼主用的是像电位器那种还是光电的那种?
页: [1]
查看完整版本: stc12c5a 调用同一个函数,为何谁在后面谁有效,