1
寄存器地址的定义:
#define UART_BASE_ADRS
(0x10000000)
#define UART_RHR *(volatile unsigned char *)(UART_BASE_ADRS +
0)
#define UART_THR *(volatile unsigned char *)(UART_BASE_ADRS +
0)
2 寄存器读写操作:
UART_THR = ch;
ch =
UART_RHR;
也可采用定义带参数宏实现
#define
WRITE_REG(addr, ch) *(volatile unsigned char *)(addr) = ch
#define
READ_REG(addr, ch) ch = *(volatile unsigned char *)(addr)
3 对寄存器相应位的操作方法:
定义寄存器
#define UART_LCR *(volatile unsigned char
*)(UART_BASE_ADRS + 3)
定义寄存器相应位的值
#define
CHAR_LEN_5 0x00
#define
CHAR_LEN_6 0x01
#define
CHAR_LEN_7 0x02
#define
CHAR_LEN_8
0x03
#define
LCR_STB 0x04
#define
ONE_STOP 0x00
#define
LCR_PEN 0x08
#define
PARITY_NONE 0x00
#define
LCR_EPS 0x10
#define
LCR_SP 0x20
#define
LCR_SBRK 0x40
#define
LCR_DLAB 0x80
定义寄存器相应位的值另一种方法
#define CHAR_LEN_5 0<<0
#define
CHAR_LEN_6 1<<0
#define
CHAR_LEN_7 1<<1
#define
CHAR_LEN_8
(1<<0)|(1<<1)
#define
LCR_STB 1<<2
#define
ONE_STOP 0<<2
#define
LCR_PEN 1<<3
#define
PARITY_NONE 0<<3
#define
LCR_EPS 1<<4
#define
LCR_SP 1<<5
#define
LCR_SBRK 1<<6
#define
LCR_DLAB 1<<7
对寄存器操作只需对相应位或赋值
UART_LCR = CHAR_LEN_8 | ONE_STOP |
PARITY_NONE;
4 对寄存器某一位置位与清零
对某一寄存器第7位置位
XX_CRTL |= 1<<7;
XX_CRTL
&= ~(1<<7);
UART_LCR |=
LCR_DLAB;
UART_LCR
&=
~(LCR_DLAB);
5 判断寄存器某一位是否置位或为0的方法
#define
UART_LSR *(volatile unsigned char *)(UART_BASE_ADRS +
5)
#define
LSR_DR
1<<0
当UART_LSR的第0位为1时结束循环
while (!(UART_LSR & LSR_DR))
补充:我自己做的试验
rNFCONF = 0;
rNFCONF |= (1 <<
1)|(1 <<
0); //rNFCONF = 0x3
rNFCONF |= (1
<<
2); //rNFCONF
= 0x7
rNFCONF |=
~(1 << 3); //rNFCONF = 0xFFFFFFF7
rNFCONF
=0xFFFFFFFF;
//rNFCONF = 0xFFFFFFFF
rNFCONF &=
~(1<<0);
//rNFCONF = 0xFFFFFFFE
rNFCONF =
0xFFFFFFFF;
//rNFCONF = 0xFFFFFFFF
rNFCONF &=
~(0<<1);
//rNFCONF = 0xFFFFFFFF
我这个天生愚钝的人,一直对这个搞的不是太明白,今天狠心把它搞个透彻。共有两种操作符,“&” 、“|”和“<<”。在程序中的操作形式有两种形式,一种是赋值、另一种就是对寄存器的位操作了。
赋值就是使用的“=”,而对寄存器的单独位操作就是使用“&=”和“|=”两种。
unsigned
int i;
首先说赋值操作,i
= ( 1 << 0) | ( 1
<< 1); 执行完成后就是 i =
3;和i以前的值没有任何的关系。但是在表达式中 使用|(0 <<
2),对结果是没有任何影响的。查看汇编程序前,一直以为是使用的另一个寄存器和当前的寄存器进行的与或操作,实际上编译器已经将处理成了 movl
0x03,exb 大概这样的形式。编译器已经将右值提前计算出来了。
另一种是i
= (~(1 << 1))&(~(1
<< 0)); i=0xfffffffc;
可以看出这两种操作的区别是一个是置位,另一个是清位,而两者的操作数是有区别的,分别对0x0和0xffffffff操作,不知道为什么。简单的记忆好了。
改变位的操作,分为清位和置位。在一行表达式中不要同时出现两种操作,它们是互斥的。
置位:i
|= (1 << 0)| (1
<< 1); 将第0位和第1位分别进行了置1的操作。
清位:
i &= (~(1 <<
1))&(~(1 << 0));
将第0位和第1位分别进行了置零
对于那种一个功能包含两个数据位的寄存器,我们可以使用这种方式同时更改两位:
i
|= (3 << (0*2))| (3
<< (1*2)); 或者 i |= (3
<< 0)| (3
<< 2); i = 0x0f
i
&= (~(3 <<
(0*2)))&(~(3 <<
(1*2));
也可以使用
i = 0xAA;
j = i;
j &= (~(0x03
<< 0)) & (~(0x03
<< 2));
j |= (0x01
<< 0) | (0x01
<< 2);
i = j;
这种形式可以保证只改变自己需要改变的寄存器。
简化写法为i = ( i
& (~(0x03 << 0))) |
(0x01 << 0);
或者直接写为 i = (i &
0xFFFFFFFC)| ();
下面来个更直接的 (_raw_readl(s3c2410_GPFCON) & (~(3
<< 8)) | (1
<< 8))
原文地址:http://futongrui.blog.sohu.com/137729731.html
加载中,请稍候......