[求助]C51中对P口如何对sbit变量进行指针赋值?

lyn689   2007-10-15 15:41 楼主
在C51中定义了如下的语句:
sbit P10 = P1^0;
在后面的模块中需要引用P10,此时可否定义一个指针指向P10?可以的话又该如何定义?

另:
在程序中有如下定义:
sbit P30 = P3^0;
sbit P31 = P3^1;
sbit P32 = P3^2;
sbit P33 = P3^3;
sbit P34 = P3^4;
sbit P35 = P3^5;
在程序中能否将上面的P30~P35放入一个数组中,这样就可以用一个for来判断返回的是P3口的那一个脚。如可以,又该如何定义呢?

以上两个问题主要是想解决判断单片机是那一个脚被置位,通过一个指针或数组来返回被置位的脚。
望各位大侠不另赐教。

回复评论 (3)

KEIL里位变量是没有指针的...

呵呵

直接用位操作嘛...

呵呵,效率比指针还高
点赞  2007-10-15 21:21

这是我作的一个完整的6×5的键盘扫描程序,时针线接于P1的第6脚,数据线接于P1的第7脚,P1的第5脚用来使能或屏蔽同接于此路上的PC键盘。
电路设计中,P1口与P3口在无按键按下时都为高电平,当有按键按下时,将P3口逐位置0,搜寻P1口,当搜寻到有置0的P1脚时,则就可判断是哪一个按键被按下。
这个程序只能判断只有一个按键被按下的情况,因此使用此程序的设备不存在多个按键同时按下与双击的情况出现,因此已可满足设计要求,并在设备下调试成功。但代码有点沉余,请指点在下一二。
------------------------------
/*--------------
NAME = keyscan.c
--------------*/

#include "reg52.h"

sbit DATA = P1^7;//数据线
sbit CLK = P1^6;//时钟线
sbit INHIBIT = P1^5;//PC键盘使能控制,为1则屏蔽
sbit P10 = P1^0;
sbit P11 = P1^1;
sbit P12 = P1^2;
sbit P13 = P1^3;
sbit P14 = P1^4;

sbit P30 = P3^0;
sbit P31 = P3^1;
sbit P32 = P3^2;
sbit P33 = P3^3;
sbit P34 = P3^4;
sbit P35 = P3^5;

sfr P1M0 = 0x91;
sfr P1M1 = 0x92;
sfr P3M0 = 0xB1;
sfr P3M1 = 0xB2;

#define uchar unsigned char
#define uint unsigned int

uchar p1 = 0x00;

unsigned char search ();
void send (uchar);
void delay_us (uint);
void delay_ms (uint);

uchar E0_flag=0;//功能键标识

void main ()
{
   uchar keys = 0x00;

   P1M0 = P1M1 = P3M0 = P3M1 = 0x00;

   INHIBIT = 0;//使能PC键盘
   CLK = 1;
   DATA = 1;       

   while(1)
   {
      keys = search();
               
      if (keys != 0x00)//判断是否有键被按下
      {
         if (E0_flag)//判断是否为功能键,功能键与非功能键的通断码不同,发送时的处理也就不同。
         {
            send (0xE0);
            send (keys);
            while (p1 != 0x1F)//等待按键放开,放开则发送断码。
            {
               p1 = P1;
               p1 &= 0x1F;
            }
            send (0xE0);
            send (0xF0);
            send (keys);
            E0_flag=0;
            P3 = 0xFF;
            p1 = 0;
         }
         else//非功能发送程序。
         {
            send (keys);
            while (p1 != 0x1F)
            {
               p1 = P1;
               p1 &= 0x1F;
            }
            send (0xF0);
            send (keys);
            P3 = 0xFF;
            p1 = 0;
         }
         keys = 0x00;
      }
   }
}


unsigned char search ()
{
   uchar temp;

   P3 = 0xFF;//先将P3全部置1,再逐个判断

   P30 = 0;//逐位判断,先将P30置0,再判断哪一个P1脚被置0,则得出哪一个按键被按下
   delay_ms(2900);
   temp = P1;
   temp &= 0x1F;
   switch (temp)
   {
      case 0x1E://P10置0
         return 0x2E;//返回被按下的键的通码
         break;
      case 0x1D://P11置0
         return 0x45;
         break;
      case 0x1B://P12置0
         return 0x49;
         break;
      case 0x17://P13置0
         return 0x5A;
         break;
      case 0x0F://P14置0
         return 0x00;//此位没有安排按键,因此若为此位则返回0,这在以后扩展中使用
         break;
      default :
         P30 = 1;
         break;
   }

   P31 = 0;
   delay_ms(2900);
   temp = P1;
   temp &= 0x1F;
   switch (temp)
   {
      case 0x1E:
         return 0x25;
         break;
      case 0x1D:
         return 0x46;
         break;
      case 0x1B:
         P31 = 1;
         return 0x00;
         break;
      case 0x17:
         E0_flag = 1;//此键为功能键,则将功能键标识置1
         return 0x7A;
         break;
      case 0x0F:
         P31 = 1;
         return 0x00;
         break;
      default:
         P31 = 1;
         break;
   }

   P32 = 0;
   delay_ms(2900);
   temp = P1;
   temp &= 0x1F;
   switch (temp)
   {
      case 0x1E:
         P32 = 1;
         return 0x26;
         break;
      case 0x1D:
         P32 = 1;
         return 0x3E;
         break;
      case 0x1B:
         P32 = 1;
         return 0x09;
         break;
      case 0x17:
         P32 = 1;
         E0_flag = 1;
         return 0x7D;
         break;
      case 0x0F:
         P32 = 1;
         E0_flag = 1;
         return 0x74;
         break;
      default:
         P32 = 1;
         break;
   }

   P33 = 0;
   delay_ms(2900);
   temp = P1;
   temp &= 0x1F;
   switch (temp)
   {
      case 0x1E:
         P33 = 1;
         return 0x1E;
         break;
      case 0x1D:
         P33 = 1;
         return 0x3D;
         break;
      case 0x1B:
         P33 = 1;
         return 0x0A;
         break;
      case 0x17:
         P33 = 1;
         return 0x66;
         break;
      case 0x0F:
         P33 = 1;
         E0_flag = 1;
         return 0x6B;
         break;
      default:
         P33 = 1;
         break;
   }

   P34 = 0;
   delay_ms(2900);
   temp = P1;
   temp &= 0x1F;
   switch (temp)
   {
      case 0x1E:
         P34 = 1;
         return 0x16;
         break;
      case 0x1D:
         P34 = 1;
         return 0x36;
         break;
      case 0x1B:
         P34 = 1;
         return 0x03;
         break;
      case 0x17:
         P34 = 1;
         return 0x79;
         break;
      case 0x0F:
         P34 = 1;
         E0_flag = 1;
         return 0x72;
         break;
      default:
         P34 = 1;
         break;
   }

   P35 = 0;
   delay_ms(2900);
   temp = P1;
   temp &= 0x1F;
   switch (temp)
   {
      case 0x1E:
         P35 = 1;
         return 0x76;
         break;
      case 0x1D:
         P35 = 1;
         return 0x0D;
         break;
      case 0x1B:
         P35 = 1;
         return 0x05;
         break;
      case 0x17:
         P35 = 1;
         return 0x7B;
         break;
      case 0x0F:
         P35 = 1;
         E0_flag = 1;
         return 0x75;
         break;
      default:
         P35 = 1;
         break;
   }

   return 0x00;
}

void send (uchar x)
{
   uchar i,temp,char_temp;
   bit flag_check = 1;
   INHIBIT = 1;
   delay_ms(2900);
   temp = x;

   for ( i = 0; i < 8; i++ )
   {
      char_temp = temp & 0x01;
      if ( char_temp == 0x01 )
      {
         flag_check = !flag_check;
                }
      temp = temp >> 1;
   }

   CLK = 1;
   while ( !CLK )
   {
      ;
   }
   CLK = 1;
   DATA = 1;
   if ( CLK == 1 )
   {
      delay_us (2);
   }
   if ( CLK ==1 && DATA ==1 )
   {
      DATA = 0;
      delay_us (2);
      CLK = 0;
      delay_us (5);
      temp = x;
      for ( i = 0; i < 8; i++ )
      {
         CLK = 1;
         delay_us (2);
         char_temp = temp & 0x01;
         if ( char_temp == 0x01 )
         {
            DATA = 1;
         }
         else
         {
            DATA = 0;
         }
         delay_us (2);
         CLK = 0;
         delay_us (5);
         temp = temp >> 1;
      }
      CLK = 1;
      delay_us (2);
      DATA = flag_check;
      delay_us (5);
      CLK = 0;
      delay_us (2);
      CLK = 1;
      delay_us (2);
      DATA = 1;
      delay_us (2);
      CLK = 0;
      delay_us(2);
      CLK = 1;
      delay_us(5);

      INHIBIT = 0;
   }
}



void delay_us (uint Time)//1=14.4us,2=20us,3=27us,4=34.2us,5=40us
{
   uint j;

   for(j=Time;j>0;j--);
}

void delay_ms (uint Time)//1=1ms,2900=20ms,303=3ms
{
   uint i,j;

   for(j=Time;j>0;j--);
   {
      for(i=206;i>0;i--);
   }
}
---------------------------------------

此电路设计上是PC键盘与专用的键盘可同时使用,用单片机的第P1^5脚平屏蔽PC键盘,此程序在设备上使用时,PC键盘与专用键盘都能使用,且PC键盘还可热拨插,但用到PC机上时就不行了。我将PC键盘与专用键盘同时接入,这样PC机就可通过PC键盘来进行启动时的识别,系统启动后,PC键盘可正常使用,但专用键盘就什么键都不起作用了,还请各位高手们指点一下小弟。
点赞  2007-10-16 11:36
的确,它也是够冗余。 其实没必要像你说的 把它们定义成数组。 因为实际上,位变量,,,假如非要搞的话,可能应该更像位段,而不是数组。(当然位段这个东西我只是知道,没用过。这里提一下而已) 你只要用 位操作就好了。 我据个例子,就上边这个,有判断是不是 0X1E 0X1D 0X1B 0X17这个。 1E : 00011110 1D: 00011101 1B: 00011011 17: 00010111
 所以,只要依次 temp & (1<<i) i = 0,1,2,3
位操作专门用来 比较 屏蔽 保留某些位。

位操作这种方式下,不见得都得用1移位,还可以更灵活,就看你要比较什么内容,比如你说的数组,估计你也是很喜欢利用数组的,另一种方式是,你直接把 1E 1D 1B 17按顺序放在数组里,直接比较也行。
不过,可以不用数组,当然用移位代替更好,一个是速度更快,另一个是少用存储空间。
[ 本帖最后由 辛昕 于 2012-3-31 15:33 编辑 ]
强者为尊,弱者,死无葬身之地
点赞  2012-3-31 15:29
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复