嵌入式寄存器操作-----C语言位操作的学习

原帖地址:http://blog.csdn.net/zeroubuntu/article/details/19617871

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. a |= 1<<x         //第x位写1  
  2. a &=~(1<<x)        //第x位写0  
  3. (a &(1<<x)) == a       //判断1,等号左边括号不能省略  
  4. (a& (1<<x))==0        //判断0  
  5. a>>n              //除法a/ 2^n  
  6. a<<n              //乘法a*2^n  


-----------------------------------------

学习嵌入式的过程中发现。C的位操作比较多,现根据资料整理如下。待以后查阅。


根据芯片手册配置寄存器的过程中,时常碰到要设置某一位或某几位的数据,根据情况置0或者置1。而对于该寄存器其他的位,我们不关心也不应该关心(谁知道其他位会不会有其他用途)。

这个时候,位操作是非常方便的。


寄存器的位操作主要是将特定位置0或者置1。一般情况是先擦除相应的位(就是置0),然后再置1。

1,如果只置为其中某一位为1

a &= ~(1<<x)               //将x位置0

b | = (1<<x)                 //将x位置1


2,如果一下置位多个位,下面的方法可以用

&=~0001 1100        //第2-4置0

| =0001 1100            //第2-4位置1

3,但是这个多位的用法犯了上面说过的问题,我们关心了其他位,因此,推荐的用法应该如下。

a &=~((1<<2) | (1<<3) | (1<<4))//将2-4置0

a|=(1<<2) | (1<<3) | (1<<4)//将2-4置1

这个代码初看起来比较上面的复杂和不便于阅读,但是实际情况不是如此,因为我们通常将(1<<2)这种代码定义为宏操作。具体可以看下面我贴出的代码。


4,如何判断寄存器某一位是0还是1。寄存器底层操作中,时常用到判断某个寄存器的状态,即读入某个寄存器的值。

a & (1<<x)  //与操作,如果相应位是0,则结果是0,如果相应位是1,则结果是1.

b | (0<<x)  //或操作,如果相应位是0,则结果是0,如果相应位是1,则结果是1.

这两个应该是没有区别的。

下面就是我根据TQ2440改写的按键LED程序,位操作使用宏定义。


----------------------------------------------------

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /*按键控制LED灯*/  
  2. /*观察原理图得到,GPB5,6,7,8分别连接led1,2,3,4;低电平点亮*/  
  3. /*按键1,2,3,4分别对应EINT1,4,2,0外部中断,低电平按下*/  
  4. /*这里我们不用中断,EINT0-4对应GPF0-4*/  
  5. /*思路:不断扫描GPF0-4(引脚输入使能),相应输出GPB5-8,各对应关系如下*/  
  6. /*GPB   LED     KEY     EINI    GPF*/  
  7. /*5     1       1       1       1*/  
  8. /*6     2       2       4       4*/  
  9. /*7     3       3       2       2*/  
  10. /*8     4       4       0       0*/  
  11. /*这里主要注意下学习位操作*/  
  12. #include<stdio.h>  
  13.   
  14. /*配置寄存器地址*/  
  15. /*GPBCON地址为(unsigned long*)0x56000010*/  
  16. /*所以GPBCON数据为(*(unsigned long*)0x56000010)*/  
  17. #define GPBCON   (*(volatile unsigned long*)0x56000010)  
  18. #define GPBDAT   (*(volatile unsigned long*)0x56000014)  
  19.   
  20. #define GPFCON   (*(volatile unsigned long*)0x56000050)  
  21. #define GPFDAT   (*(volatile unsigned long*)0x56000054)  
  22.   
  23. /*寄存器擦除某一位为0*/  
  24. /*这是16位寄存器,每一设置有2个二进制数位,因此一次擦除2位,3=0b11*/  
  25. #define GPB5_MSK    (3<<(5*2))        //位左移10位,[10.9]位为1,其余为0  
  26. #define GPB6_MSK    (3<<(6*2))  
  27. #define GPB7_MSK    (3<<(7*2))  
  28. #define GPB8_MSK    (3<<(8*2))  
  29.   
  30. #define GPF0_MSK    (3<<(0*2))  
  31. #define GPF1_MSK    (3<<(1*2))  
  32. #define GPF2_MSK    (3<<(2*2))  
  33. #define GPF4_MSK    (3<<(4*2))  
  34.   
  35. /*设置引脚为输入功能,相应位置00*/  
  36. #define GPF0_IN     (0<<(0*2))  
  37. #define GPF1_IN     (0<<(1*2))  
  38. #define GPF2_IN     (0<<(2*2))  
  39. #define GPF4_IN     (0<<(4*2))  
  40.   
  41. /*设置引脚为输出功能,相应位置01*/  
  42. #define GPB5_OUT    (1<<(5*2))  
  43. #define GPB6_OUT    (1<<(6*2))  
  44. #define GPB7_OUT    (1<<(7*2))  
  45. #define GPB8_OUT    (1<<(8*2))  
  46.   
  47.   
  48.   
  49.   
  50. int main(void)  
  51. {  
  52.     /*配置引脚功能,GPB[5,8]为输出,GPF[0,3]为输入*/  
  53.     GPBCON &=~(GPB5_MSK | GPB6_MSK | GPB7_MSK | GPB8_MSK);  
  54.     GPBCON |=GPB5_OUT | GPB6_OUT | GPB7_OUT | GPB8_OUT;  
  55.     GPFCON &=~(GPF0_MSK | GPF1_MSK | GPF2_MSK | GPF4_MSK);  
  56.     GPFCON |=GPF0_IN | GPF1_IN | GPF2_IN | GPF4_IN;  
  57.       
  58.     unsigned long key_date;  
  59.   
  60.     /*低电平表示按键按下*/  
  61.     while(1)  
  62.     {  
  63.         key_date=GPFDAT;  
  64.   
  65.         if(key_date & (1<<0))     //判断第0位是否为1,对应按键4,GPB8  
  66.             GPBDAT |=(1<<8);      //是1,按键未按下,相应LED置1,不点亮  
  67.         else  
  68.             GPBDAT &=~(1<<8);     //是0,按键按下,相应LED低电平,点亮  
  69.           
  70.   
  71.         if(key_date & (1<<1))     //GPF1,KEY1,LED1,GPB5  
  72.             GPBDAT |=(1<<5);        
  73.         else  
  74.             GPBDAT &=~(1<<5);  
  75.               
  76.         if(key_date & (1<<2))     //GPF2,KEY3,LED3,GPB57  
  77.             GPBDAT |=(1<<7);          
  78.         else  
  79.             GPBDAT &=~(1<<7);  
  80.           
  81.         if(key_date & (1<<4))     //GPF4,KE21,LED2,GPB6  
  82.             GPBDAT |=(1<<6);          
  83.         else  
  84.             GPBDAT &=~(1<<6);  
  85.     }  
  86. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值