×
单片机 > 单片机程序设计 > 详情

PICC编程的位操作示例程序

发布时间:2020-06-16 发布时间:
|
由于PIC 处理器对位操作是最高效的,所以把一些BOOL 变量放在一个内存的位中,既可以达到运算 速度快,又可以达到最大限度节省空间的目的。在C 中的位操作有多种选择。  
*********************************************  
如:char x;x=x|0B00001000; /*对X 的4 位置1。*/  
char x;x=x&0B11011111; /*对X 的5 位清0。*/  
把上面的变成公式则是:  
#define bitset(var,bitno)(var |=1< #define bitclr(var,bitno)(var &=~(1< 则上面的操作就是:char x;bitset(x,4)  
char x;bitclr(x,5)  
*************************************************但上述的方法有缺点,就是对每一位的含义不直观,最好是能在代码中能直观看出每一位代表的意思,这样就能提高编程效率,避免出错。如果我们想用X 的0-2 位分别表示温度、电压、电流的BOOL 值可以如下:  
unsigned char x @ 0x20; /*象汇编那样把X 变量定义到一个固定内存中。*/  
bit temperature@ (unsigned)&x*8+0; /*温度*/  
bit voltage@ (unsigned)&x*8+1; /*电压*/  
bit current@ (unsigned)&x*8+2; /*电流*/  
这样定义后X 的位就有一个形象化的名字,不再是枯燥的1、2、3、4 等数字了。可以对X 全局修改,也可以对每一位进行操作:  
char=255;  
temperature=0;  
if(voltage)......  
*****************************************************************  
还有一个方法是用C 的struct 结构来定义:  
如:  
struct cypok{  
temperature:1; /*温度*/  
voltage:1; /*电压*/  
current:1; /*电流*/  
none:4;  
}x @ 0x20;  
这样就可以用  
x.temperature=0;  
if(x.current)....  
等操作了。  
**********************************************************上面的方法在一些简单的设计中很有效,但对于复杂的设计中就比较吃力。如象在多路工业控制上。前端需要分别收集多路的多路信号,然后再设定控制多路的多路输出。如:有2 路控制,每一路的前端信号有温度、电压、电流。后端控制有电机、喇叭、继电器、LED。如果用汇编来实现的话,是很头疼的事情,用C 来实现是很轻松的事情,这里也涉及到一点C 的内存管理(其实C 的最大优点就是内存管理)。采用如下结构:  
union cypok{  
struct out{  
motor:1; /*电机*/  
relay:1; /*继电器*/  
speaker:1; /*喇叭*/  
led1:1; /*指示灯*/  
led2:1; /*指示灯*/  
}out;  
struct in{  
none:5;  
temperature:1; /*温度*/  
voltage:1; /*电压*/  
current:1; /*电流*/  
}in;  
char x;  
};  
union cypok an1;  
union cypok an2;  
上面的结构有什么好处呢?  
细分了信号的路an1 和an2;  
细分了每一路的信号的类型(是前端信号in 还是后端信号out):  
an1.in ;  
an1.out;  
an2.in;  
an2.out;  
然后又细分了每一路信号的具体含义,如:  
an1.in.temperature;  
an1.out.motor;  
an2.in.voltage;  
an2.out.led2;等  
这样的结构很直观的在2 个内存中就表示了2 路信号。并且可以极其方便的扩充。如添加更多路的信号,只需要添加:  
union cypok an3;  
union cypok an4;  
从上面就可以看出用C 的巨大好处一:用位操作来做一些标志位,也就是BOOL变量.可以简单如下定义:  
bit a,b,c;  
PICC会自动安排一个内存,并在此内存中自动安排一位来对应a,b,c.由于我们只是用它们来简单的 表示一些0,1信息,所以我们不需要详细的知道它们的地址\位究竟是多少,只管拿来就用好了.  
二:要是需要用一个地址固定的变量来位操作,可以参照PIC.H里面定义寄存器.  
如:用25H内存来定义8个位变量.  
static volatile unsigned char myvar @ 0x25;  
static volatile bit b7 @ (unsigned)&myvar*8+7;  
static volatile bit b6 @ (unsigned)&myvar*8+6;  
static volatile bit b5 @ (unsigned)&myvar*8+5;  
static volatile bit b4 @ (unsigned)&myvar*8+4;  
static volatile bit b3 @ (unsigned)&myvar*8+3;  
static volatile bit b2 @ (unsigned)&myvar*8+2;  
static volatile bit b1 @ (unsigned)&myvar*8+1;  
static volatile bit b0 @ (unsigned)&myvar*8+0;  
这样即可以对MYVAR操作,也可以对B0--B7直接位操作.但不好的是,此招在低档片子,如C5X系列上可能会出问题.还有就是表达起来复杂,你不觉得输入代码受累么?呵呵  
三:这也是一些常用手法:  
#define testbit(var, bit) ((var) & (1 < #define setbit(var, bit) ((var) |= (1 << (bit))) //把某一位置1  
#define clrbit(var, bit) ((var) &= ~(1 << (bit))) //把某一位清0  
付上一段代码,可以用MPLAB调试观察  
#include  
#define testbit(var, bit) ((var) & (1 < #define setbit(var, bit) ((var) |= (1 << (bit)))  
#define clrbit(var, bit) ((var) &= ~(1 << (bit)))  
char a,b;  
void main(){  
char myvar;  
myvar=0B10101010;  
a=testbit(myvar,0);  
setbit(myvar,0);  
a=testbit(myvar,0);  
clrbit(myvar,5);  
b=testbit(myvar,5);  
if(!testbit(myvar,3))  
a=255;  
else  
a=100;  
while(1){;}  
}  
四:用标准C的共用体来表示:  
#include  
union var{  
unsigned char byte;  
struct {  
unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;  
} bits;  
};  
char a,b;  
void main(){  
static union var myvar;  
myvar.byte=0B10101010;  
a=myvar.bits.b0;  
b=myvar.bits.b1;  
if(myvar.bits.b7)  
a=255;  
else  
a=100;  
while(1){;}  
}  
五:用指针转换来表示:  
#include  
typedef struct {  
unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;  
} bits; //先定义一个变量的位  
#define mybit0 (((bits *)&myvar)->b0) //取myvar 的地址(&myvar)强制转换成bits 类型的指针  
#define mybit1 (((bits *)&myvar)->b1)  
#define mybit2 (((bits *)&myvar)->b2)  
#define mybit3 (((bits *)&myvar)->b3)  
#define mybit4 (((bits *)&myvar)->b4)  
#define mybit5 (((bits *)&myvar)->b5)  
#define mybit6 (((bits *)&myvar)->b6)  
#define mybit7 (((bits *)&myvar)->b7)  
char myvar;  
char a,b;  
void main(){  
myvar=0B10101010;  
a=mybit0;  
b=mybit1;  
if(mybit7)  
a=255;  
else  
a=100;  
while(1){;}  
}  
六:五的方法还是烦琐,可以用粘贴符号的形式来简化它.  
#include  
typedef struct {  
unsigned b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;  
} bits;  
#define _paste(a,b) a##b  
#define bitof(var,num) (((bits *)&(var))->_paste(b,num))  
char myvar;  
char a,b;  
void main(){  
a=bitof(myvar,0);  
b=bitof(myvar,1);  
if(bitof(myvar,7))  
a=255;  
else  
a=100;  
while(1){;}  
}  
有必要说说#define _paste(a,b) a##b 的意思:  
此语句是粘贴符号的意思,表示把b 符号粘贴到a 符号之后.  
例子中是  
a=bitof(myvar,0);--->(((bits *)&(myvar))->_paste(b,0))--->(((bits *)&(var))->b0)可以看出来,_paste(b,0)的作用是把0 粘贴到了b 后面,成了b0 符号.  
总结:C语言的优势是能直接对低层硬件操作,代码可以非常非常接近汇编,上面几个例子的位操作代码是100%的达到汇编的程度的.另一个优势是可读性高,代码灵活.上面的几个位操作方法任由你选,你不必担心会产生多余的代码量出来. 
关键字:PIC  C编程的  位操作 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
基于arm的指纹识别门禁系统是如何设计的