在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口的那一个脚。如可以,又该如何定义呢?
以上两个问题主要是想解决判断单片机是那一个脚被置位,通过一个指针或数组来返回被置位的脚。
望各位大侠不另赐教。
KEIL里位变量是没有指针的...
呵呵
直接用位操作嘛...
呵呵,效率比指针还高
这是我作的一个完整的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键盘可正常使用,但专用键盘就什么键都不起作用了,还请各位高手们指点一下小弟。
的确,它也是够冗余。
其实没必要像你说的 把它们定义成数组。
因为实际上,位变量,,,假如非要搞的话,可能应该更像位段,而不是数组。(当然位段这个东西我只是知道,没用过。这里提一下而已)
你只要用 位操作就好了。
我据个例子,就上边这个,有判断是不是 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 编辑 ]