2015.4.20_DSP学习1,C语言结构复习

(1)复习C语言中的位域、共同体、结构体;
(2)使用位定义、共同体、结构体来对DSP的寄存器进行操作;(理解.h文件的作用)
(3)对存储器进行管理;(理解.cmd文件)
 
一、位域、共同体与结构体
关于数组、结构体、共同体用一个比较好的解释是这么说的:
数组是同类型数据的集合;
结构体是不同类型数据的集合;
共同体是不同类型共用存储单元。
1.位域
  (1)为了节省内存空间,有些数据的存储只需要内存中的一位或几位二进制位,位域提供了这一功能。
       位域的定义事实上就是一个结构体
       struct weiyu
       {int a:3;
        int b:5;
        int c:8;}
       表明定义了一个位域结构weiyu,它有三个位域a、b、c,位域a占3个二进制位,b占5个二进制位,c占8个
       二进制位。
      (这里还有一个问题就是在定义位域前面有一个int,这样看来,这三个位域岂不是占了6个字节?事实上
        是,编译器会将其中的某几个位域捆绑起来按int做对齐,详细情况请参加见
        http://hi.baidu.com/xiao1dian/item/7cfa8e0e9d0e51cc905718ed
        http://blog.sina.com.cn/s/blog_66ec4d660100j3wi.html)
(2)位域的几点说明:
       定义顺序从低位到高位,即从右到左;
       一个位域只能存在一个字节中,不能横跨两个字节,否则需中间插入空位域来补齐一字节;
       位域长度不大于一个字节长度;
       位域可以没有名,这时用来做补齐用;
       如struct weiyu
       {int a:4;
        int :2;(这两位不用)
        int c:8;};
(3)定义位域实例及使用
       struct weiyu weiyu1;//声明了一个weiyu型变量weiyu1
       weiyu1.a=2;
       weiyu1.b=1;
      weiyu.c=0;(如果放进去的数字大于你所规定的位域长度,会出现不正确的结果,注意,规定一个位域有
                  x位,那么只能放进去2^(x-1)位的数字,因为还有一位要做符号位用)
 
2.共同体
       当需要把不同类型的变量存放到同一段内存单元,或对同一段内存单元的数据按不同类型处理,则需要
       使用“共用体”数据结构。把一个整型变量、一个字符型变量、一个实型变量放在同一个地址开始的内
       存单元中。
           共用体的定义形式:
       union 共用体名
       {
         成员列表;
       } 变量列表;
       例如  union data
             {char a;
              int b;
              float c;};
              union data data1;
              data1.a='2'
              data1.b=20;
              data1.c=1.2;
        data1的a、b、c共享一段起始内存,以最后一次赋值为准,并且其长度以最长的成员长度为
        准。如上例中,共同体中最后一次赋值的变量值为1.2,前两次赋值已无意义。
        请参见http://blog.21ic.com/user1/7959/archives/2011/81841.html
 
 
二、使用位定义、共同体来对DSP寄存器进行操作
 1.位定义操作
        这里我们以ADC的控制寄存器1ADCTRL1为例来进行位操作定义:
        ADC寄存器的构造参见datasheet或者《手把手》293页,我们可以做位定义如下:
                        struct ADCTRL1_BITS{
                               Uint 16 rsvd:4;//最低4位为保留位;
                               Uint 16 SEQ_CASC:1;//级联序列发生器工作方式;
                               Uint 16 SEQ1_OVRD:1;//序列发生器忽略位;
                               Uint 16 CONT_RUN:1;//连续运行;
                               Uint 16 CPS:1;//内核时钟定标位;
                               Uint 16 ACQ_PS:4;//采集窗口大小;
                               Uint 16 SUSMOD:2;//仿真暂停方式;
                               Uint 16 RESET:1;//ADC软件复位;
                               Uint 16 rsvd2:1;//保留位,注意不能与前面的rsvd重名;};
        这样定义完之后,我们将它存放在.h头文件里头,这就是为什么我们在日常写程序中,只要写一句
        AdcRegs.ADCTRL1.bit.RESET=1,就可以软件复位整个ADC了,事实上,机器是并不知道我们所写的哪一个寄
        存器哪一位代表什么的,之所以它可以那么“智能”的找到这些寄存器的位置,就是因为我们在这里对它进
        行了位分配以及之后要提及的cmd定义,让这些寄存器名称和他们实实在在的物理地址对应了起来,所以这
        个过程可以看做是“起名字,分位子”的过程。
2.共同体操作
       为了方便对寄存器既可以按位进行操作,也可以整体进行操作,我们可以使用共同体,就是定义一个
       共同体,里面的成员既包括按位操作的属性,又包括整体操作的属性,具体做法如下:
                    union ADCTRL1_REG{
                     Unit 16 all;//all属性,表示可以对寄存器整体操作;
                     struct ADCTRL1_BITS bit;//bit属性,表示可以对寄存器按位操作;};
       上例中,我声明了一个共同体ADCTRL1,我继续声明一个共同体变量ADCTRL1_REG1即
                      union ADCTRL1_REG ADCTRL1_REG1;
       则我既可以通过按位访问访问它ADCTRL1_REG1.bit.SEQCASC=1;
           又可以通过整体对它进行赋值ADCTRL1_REG1.all=0x……;
       所以,我们在DSP的头文件中一般可以看到以下的定义形式:(我们以CPU定时器的头文件对TCR寄存器的定义
       来看一下实际中头文件是如何定义出来的:
                           struct  TCR_BITS {          // bits  description
                             Uint16    rsvd1:4;       // 3:0   reserved
                             Uint16    TSS:1;         // 4     Timer Start/Stop
                             Uint16    TRB:1;         // 5     Timer reload
                             Uint16    rsvd2:4;       // 9:6   reserved
                             Uint16    SOFT:1;        // 10    Emulation modes
                             Uint16    FREE:1;        // 11
                             Uint16    rsvd3:2;       // 12:13 reserved
                             Uint16    TIE:1;         // 14    Output enable
                             Uint16    TIF:1;         // 15    Interrupt flag
                             };
                      union TCR_REG {
                             Uint16           all;
                             struct TCR_BITS  bit;
                             };
       可以看到,位定义之后跟着就在后面定义了一个结构体,是为了方便对寄存器进行按位和整体操作。
 
3.结构体操作
      某个功能模块,比如ADC的寄存器往往不止一个,有很多,我们可以创建一个结构体来对它进行管理,比如,
       我要创建一个结构体ADC_REGS,来对ADC所有的寄存器来进行管理,我就可以这样做:
       struct ADC_REGS {
                        union ADCTRL1_REG      ADCTRL1;       // ADC Control 1
                        union ADCTRL2_REG      ADCTRL2;       // ADC Control 2
                        union ADCMAXCONV_REG   ADCMAXCONV;    // Max conversions
                        union ADCCHSELSEQ1_REG ADCCHSELSEQ1;  // Channel select sequencing control 1
                        union ADCCHSELSEQ2_REG ADCCHSELSEQ2;  // Channel select sequencing control 2
                        union ADCCHSELSEQ3_REG ADCCHSELSEQ3;  // Channel select sequencing control 3
                        union ADCCHSELSEQ4_REG ADCCHSELSEQ4;  // Channel select sequencing control 4
                        union ADCASEQSR_REG    ADCASEQSR;     // Autosequence status register
                        Uint16                 ADCRESULT0;    // Conversion Result Buffer 0
                        Uint16                 ADCRESULT1;    // Conversion Result Buffer 1
                        Uint16                 ADCRESULT2;    // Conversion Result Buffer 2
                        Uint16                 ADCRESULT3;    // Conversion Result Buffer 3
                        Uint16                 ADCRESULT4;    // Conversion Result Buffer 4
                        Uint16                 ADCRESULT5;    // Conversion Result Buffer 5
                        Uint16                 ADCRESULT6;    // Conversion Result Buffer 6
                        Uint16                 ADCRESULT7;    // Conversion Result Buffer 7
                        Uint16                 ADCRESULT8;    // Conversion Result Buffer 8
                        Uint16                 ADCRESULT9;    // Conversion Result Buffer 9
                        Uint16                 ADCRESULT10;   // Conversion Result Buffer 10
                        Uint16                 ADCRESULT11;   // Conversion Result Buffer 11
                        Uint16                 ADCRESULT12;   // Conversion Result Buffer 12
                        Uint16                 ADCRESULT13;   // Conversion Result Buffer 13
                        Uint16                 ADCRESULT14;   // Conversion Result Buffer 14
                        Uint16                 ADCRESULT15;   // Conversion Result Buffer 15
                        union ADCTRL3_REG      ADCTRL3;       // ADC Control 3  
                        union ADCST_REG        ADCST;         // ADC Status Register
                        Uint16       rsvd1;
                        Uint16                 rsvd2;
                        union ADCREFSEL_REG    ADCREFSEL;     // Reference Select Register
                        union ADCOFFTRIM_REG   ADCOFFTRIM;    // Offset Trim Register
                        };
           可以看出,将所有的uint16成员和union成员全部放在了一起,构成了ADC_REGS的结构体,注意到这里
           面,union成员是既可以进行按位操作,又可以进行整体操作的,而uint16成员只能进行整体操作。
 
           综上所述,我们可以看出构建.h文件是一个自下而上的构建过程:
           1.先进行位定义,对某一个寄存器每一个位进行名称定义,然后这些位构成了某一个特定的寄
           存器;
           2.构成的特定的寄存器,又与寄存器整体定义(uint 16 all)一起构成了共同体,这样可以方便
           对寄存器进行整体操作和按位操作;
           3.一个功能模块内所有的寄存器(无论它被定义成共同体还是未定义过的),都通过结构体一
           起构成了一个特定模块。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值