本帖最后由 小营七郎 于 2013-12-25 13:05 编辑
对28335寄存器的控制能够使它实现相应的功能,一个功能就有很多个寄存器对于的寄存器组,对于28335这样复杂的处理器来说。
每个寄存器就有很多位,这里废话一句,很多个位乘以一个功能相对应的寄存器组的寄存器个数,就可以这是多么复杂的事情,好在复杂之中也是
有一定规律的,下面就慢慢说。
比如外设串行通信接口A就有SCICCR和SCICTL1,既通信控制寄存器和控制寄存器,(当然了,对于一个SCIA来说,要实现通信功能,肯定不止这两个寄存器,要不我们假设一个寄存器有16位,那最对2*16=32位,显然控制32个位这么简单的话人人都会了)而这两个寄存器在28335的存储区域是连续的,就是地址是连续的,比如SCICCR寄存器的地址为0x00007050,那么下一个地址0x00007051就是SCICTL1,对于28335来说每个地址对应一个存储单元,可能说到存储单元学过汇编语言的同学有的就会想存储单元和内存单元是不是相同的,他们本质都是存储数据的,只是汇编语言对PC机来说内存单元一般在CPU外部,(建议好好看看数电,多做点实验,这里不祥叙述)
这就很明朗了,每个占有16位的一个寄存器里面有可能单独一位也有可能连续几位合起来表达一个意思。所以对寄存器来说,必须操作一位或者几位才能表示出想要的功能,刚才说了,每一个功能都对应一个寄存器组,每个寄存器组有很多寄存器,他们是连续的以16位为一个地址分配在28335的存储空间里的。
接下来说说C语言位域的数据结构,所谓的位域就是把一个字节(这里因为一个寄存器占16位,所以是两个字节)中的二进制位划分为不同的区域,并说明每个区域的位数,而且每个域都有一个域名,使用的时候定义一个域名类型的变量,然后根据划分二进制的不同区域就可以单独对某一位或者某几位(当然这几位在划分的时候肯定要划分为同一区域,否则无法对其单独操作)进行操作。
struct weiyu {
int a:8;
int b:2;
int c:6;
};//定义一个位域
struct weiyu wei1;//wei1 为定义位域类型
1, 定义位区域必须从右向左,上面就是从0位开始依次向高位定义
2, 一个位域必须存储在同一个字节中,不能跨两个字节比如把16位从低到高分成3个域,a占4位,b占5位,c占3位,那么因为a+b=9>8所以b就只能在8到15这个字节类划分,不能划分在0到7这个字节,这样的话0-7这个字节肯定不会满,而是空了4-7位,这个时候就可以把4-7位划分为空域,就是程序访问不到的寄存器位。
3,位域的长度不能大于一个字节,所以一个域有9位或者更高是错误的。
4,位域可以位域名,比如 int :2;这就代表两位用作填充物或调整位置(这里不知道没有名的位域和空域有什么区别,还请经验丰富的大哥帮忙解释解释)
有了以上的基本知识后,我们来看看才开始说的两个寄存器,外设串行通信接口A的SCICCR和SCICTL1,以通信控制寄存器SCICCR为例子来说明刚才我们说的位域用法,
SCIA模块的所有寄存器都是8位的,当一个寄存器被访问时,寄存器数据位于低8位,高8位为0。0—2位为字符长度控制位,第3位为sci多处理模式控制位,第4位为SCI回送从测试使能位loopbrena 第5位为SCI极性使能位。第6位是奇偶极性使能位PARITY 第7位是SCI结束位的个数STOP-BITS,剩下的高8位是保留位
所以更具前面定义位域的方法,把通信控制寄存器SCICCR 写成以下位域的方式
struct SCICCR_BITS
{
Uint16 SCICHAR:3;
Uint16 ADDRIDLE_MODE:1;
Uint16 LOOPBKENA:1;
Uint16 PARITYENA: 1;
Uint16 PARITY :1;
Uint16 STOPBITS:1;
Uint16 rsvdl :8;
};
这下就很清楚了,如果我们要操作寄存器的话,就只需声明一个刚定义好的位域就可以了,struct SCICCR_BITS bit;
比如我们要对字符长度控制位,因为这个控制位是几个位控制一个功能的,而这几个位刚好有被定义为同一位域,所以只需在刚才声明的位域中直接操作,既
bit.SCICHAR = 7
|