矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 2556|回复: 11

老师帮忙看个程序

[复制链接]
     
发表于 2018-7-13 00:28:58 | 显示全部楼层 |阅读模式
本帖最后由 ycx2002 于 2018-7-13 01:20 编辑

#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit PINA=P1^0;                   //旋转编码开关脚位
sbit PINB=P1^1;                  //旋转编码开关脚位
sbit P2_1=P2^1;    //数码管
sbit P2_2=P2^2;    //数码管
sbit P2_3=P2^3;    //数码管
uchar x;
unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,
                                                        0x99,0x92,0x82,
                                0xf8,0x80,0x90};
void Delayms(uchar xms)
{
        uchar i,j;
        for(i=xms;i>0;i--)
        for(j=110;j>0;j--);
}
void Display(uchar temp)
{
   uchar bai,shi,ge;
        bai=temp/100;   
        shi=temp%100/10;
        ge=temp%10;  

   P0=(table[bai]);
   P2_1 = 0;
   Delayms(5);
   P2_1 = 1;

   P0=table[shi];
   P2_2 = 0;
   Delayms(5);
   P2_2 = 1;

   P0=table[ge];
   P2_3 = 0;
   Delayms(5);
   P2_3 = 1;
   
}

/******************************************************************************/
void encoder()
{
       
static bit flag=0,turn_right=0,turn_left=0;
       
       

        if((PINA)&&(PINB))
                flag=1;
        if(PINA!=PINB)
        {
                turn_left=PINA;   
                turn_right=PINB;   
        }
        if(flag)
        {
                if((PINA==0)&&(PINB==0))
                {       
                        flag=0;
                        if(turn_left==0)
                                x--;
                        if(turn_right==0)
                                x++;
                }
        }

}

void main()
{
       
        while(1)
        {
                encoder();
                Display(x);
        }
}


这是个51旋转编码开关的程序,编码开关检测程序用到了静态局部变量,问题就出在这里,如果不用静态局部变量直接声明位变量bit flag=0,turn_right=0,turn_left=0;按照原理也是说的通的,因为每次执行到这部分right和left都被重新赋值了:
       
if(PINA!=PINB)
        {
                turn_left=PINA;   
                turn_right=PINB;   
        }
用仿真芯片是可以通过的!
但实际放到板子上测试只显示零,调节旋转开关也没反应。但是在检测函数里使用static bit 或把bit flag=0,turn_right=0,turn_left=0;设置为全局变量就一切正常了。关于静态局部变量的意义我也知道,为什么会这样?
请老师详细解惑。。。。感谢!
     
发表于 2018-7-13 09:30:28 | 显示全部楼层
旋转编码开关脚加上拉了吗
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-7-13 11:05:08 | 显示全部楼层
xuyaqi 发表于 2018-7-13 09:30
旋转编码开关脚加上拉了吗

加了,忽略硬件问题。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-7-13 11:11:39 | 显示全部楼层
本帖最后由 ycx2002 于 2018-7-13 11:17 编辑
简燕 发表于 2018-7-13 10:17
if(flag)                                                   // (PINA==1)&&(PINB==1)
        {
     ...


即使检测函数刚开始时用普通的定义位变量bit flag=0;程序执行之初未旋转编码开关之前检测两个脚位都是高电平时flag被赋值了啊
if((PINA)&&(PINB))
                flag=1;

flag=1后,在接下来的运算中是有效的啊
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-7-13 12:09:36 | 显示全部楼层
简燕 发表于 2018-7-13 11:17
如果用sbit flag=0,可以把程序变形一下:

if((PINA==1)&&(PINB==1))   

我觉得逻辑顺序还是不错的,操作旋转编码开关是一个动态过程,旋转之前AB都是高电平,flag被致1'接着根据旋转方向储存AB电平,当转到AB都是低电平的时候开始判断之前储存的AB电平确定旋转方向该加还是该减。flag被清零,完成一个周期
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-7-13 12:38:45 | 显示全部楼层
这个程序刚开始时是判断编码开关旋转时的一个工作周期,AB都是高电平无疑,接着将flag置1。随着旋转的继续开始判断并储存AB的状态。然后继续旋转直到AB都是低电平是根据之前储存AB的状态确定旋转方向,最后flag清0。最后旋转至AB都为高电平,一个周期结束。
问题来了,如果在这个子函数内将flag,A,B都用一个普通的位变量而不用静态局部变量static bit按我的理解也是可以的,因为这几个位变量是在这个子函数内完成判断和运算的,函数内是合理有效的。但实际下到板子里是不行的。但是把这三个位变量设计为静态局部变量或者是全局变量就没问题,可以正常操作。
回复 支持 反对

使用道具 举报

     
发表于 2018-7-13 12:47:37 来自手机 | 显示全部楼层
你真的懂局部变量的意思?
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-7-13 13:01:39 | 显示全部楼层
isyido 发表于 2018-7-13 12:47
你真的懂局部变量的意思?

自己看书以及在网络上面看到些,并不全面,刚学,请指教
回复 支持 反对

使用道具 举报

     
发表于 2018-7-13 13:40:40 | 显示全部楼层
检查一下硬件接线~~~~~~
回复 支持 反对

使用道具 举报

     
发表于 2018-7-13 15:48:19 | 显示全部楼层
本帖最后由 壹法拉 于 2018-7-13 16:28 编辑

我认为3搂分析的对;
感觉逻辑判断可能有点问题;


void encoder()
{
        
static bit flag=0,turn_right=0,turn_left=0;
        
        

        if((PINA)&&(PINB))
                flag=1;
        if(PINA!=PINB)
        {
                turn_left=PINA;   
                turn_right=PINB;   
        }
      

//走到这里时 如果 flag=1; PINA PINB 都是高电平,下面的几句都不可能执行;
//turn_left 和 turn_right 是局部变量,函数结束后,变量就没了;
//但是当你把 turn_left 和 turn_right 都设成全局变量或静态变量时,这些变量的值会被“记住”;
//下次走到这里时,只有当 flag=1,且立刻PINA PINB 都为0时,才可以执行下面那几句了;
// 按你现在的逻辑,下面的代码是几乎永远不能被执行的;也许去掉 if(flag) 这层判断就行了;

if(flag)
        {
                if((PINA==0)&&(PINB==0))
                {        
                        flag=0;
                        if(turn_left==0)
                                x--;
                        if(turn_right==0)
                                x++;
                }
        }

}



回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-7-14 02:00:58 | 显示全部楼层
简燕 发表于 2018-7-13 13:38
我不知道你用的什么仿真环境如果是纯软件的,对程序本身是可以的,但对CPU外部的时序逻辑,就得就事论事.
...

谢谢您的解答,似乎有些明白了。
回复 支持 反对

使用道具 举报

     
 楼主| 发表于 2018-7-14 02:01:46 | 显示全部楼层
壹法拉 发表于 2018-7-13 15:48
我认为3搂分析的对;
感觉逻辑判断可能有点问题;

感谢您的回复,谢谢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2024-3-29 05:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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