新闻  |   论坛  |   博客  |   在线研讨会
结构体和联合体(共用体)结合使用的优点
dianzixinxi | 2012-08-05 22:18:57    阅读:24854   发布文章

转发:一个结构和联合“妙用”分析

 在《NiosII那些事儿》串口实验中,有这样一段程序:

sopc.h

typedef struct  
  1. {  
  2. //接收寄存器  
  3. union  
  4. {  
  5.   struct  
  6.   {    
  7.     volatile unsigned long int RECEIVE_DATA        :8;    
  8.     volatile unsigned long int NC                  :24;    
  9.   }BITS;  
  10.   volatile unsigned long int WORD;  
  11. }RXDATA;  
  12.   
  13. //发送寄存器  
  14. union  
  15. {  
  16.   struct  
  17.   {  
  18.     volatile unsigned long int TRANSMIT_DATA        :8;  
  19.     volatile unsigned long int NC                  :24;  
  20.   }BITS;  
  21.   volatile unsigned long int WORD;  
  22. }TXDATA;  
  23.   
  24. //状态寄存器  
  25. union  
  26. {  
  27.   struct  
  28.   {  
  29.     volatile unsigned long int PE                  :1;  
  30.     volatile unsigned long int FE                  :1;  
  31.     volatile unsigned long int BRK                 :1;  
  32.     volatile unsigned long int ROE                 :1;  
  33.     volatile unsigned long int TOE                 :1;  
  34.     volatile unsigned long int TMT                 :1;  
  35.     volatile unsigned long int TRDY                :1;  
  36.     volatile unsigned long int RRDY                :1;  
  37.     volatile unsigned long int E                   :1;  
  38.     volatile unsigned long int NC                  :1;  
  39.     volatile unsigned long int DCTS                :1;  
  40.     volatile unsigned long int CTS                 :1;  
  41.     volatile unsigned long int EOP                 :1;  
  42.     volatile unsigned long int NC1                 :19;  
  43.     
  44.   }BITS;  
  45.   volatile unsigned long int WORD;  
  46. }STATUS;  
  47.   
  48. //控制寄存器  
  49. union  
  50. {  
  51.   struct  
  52.   {  
  53.     volatile unsigned long int IPE                  :1;  
  54.     volatile unsigned long int IFE                  :1;  
  55.     volatile unsigned long int IBRK                 :1;  
  56.     volatile unsigned long int IROE                 :1;  
  57.     volatile unsigned long int ITOE                 :1;  
  58.     volatile unsigned long int ITMT                 :1;  
  59.     volatile unsigned long int ITRDY                :1;  
  60.     volatile unsigned long int IRRDY                :1;  
  61.     volatile unsigned long int IE                   :1;  
  62.     volatile unsigned long int TRBK                 :1;  
  63.     volatile unsigned long int IDCTS                :1;  
  64.     volatile unsigned long int RTS                  :1;  
  65.     volatile unsigned long int IEOP                 :1;  
  66.     volatile unsigned long int NC                   :19;  
  67.     
  68.   }BITS;  
  69.   volatile unsigned long int WORD;  
  70. }CONTROL;  
  71.   
  72. //波特率分频器  
  73. union{  
  74.   struct  
  75.   {  
  76.     volatile unsigned long int BAUD_RATE_DIVISOR     :16;  
  77.     volatile unsigned long int NC                    :16;  
  78.   }BITS;  
  79.   
  80.   volatile unsigned long int WORD;  
  81. }DIVISOR;  
  82.   
  83. }UART_STR;  
  84. ......  
.......
typedef struct
{
//接收寄存器
union
{
  struct
  {  
    volatile unsigned long int RECEIVE_DATA        :8;  
    volatile unsigned long int NC                  :24;  
  }BITS;
  volatile unsigned long int WORD;
}RXDATA;

//发送寄存器
union
{
  struct
  {
    volatile unsigned long int TRANSMIT_DATA        :8;
    volatile unsigned long int NC                  :24;
  }BITS;
  volatile unsigned long int WORD;
}TXDATA;

//状态寄存器
union
{
  struct
  {
    volatile unsigned long int PE                  :1;
    volatile unsigned long int FE                  :1;
    volatile unsigned long int BRK                 :1;
    volatile unsigned long int ROE                 :1;
    volatile unsigned long int TOE                 :1;
    volatile unsigned long int TMT                 :1;
    volatile unsigned long int TRDY                :1;
    volatile unsigned long int RRDY                :1;
    volatile unsigned long int E                   :1;
    volatile unsigned long int NC                  :1;
    volatile unsigned long int DCTS                :1;
    volatile unsigned long int CTS                 :1;
    volatile unsigned long int EOP                 :1;
    volatile unsigned long int NC1                 :19;
  
  }BITS;
  volatile unsigned long int WORD;
}STATUS;

//控制寄存器
union
{
  struct
  {
    volatile unsigned long int IPE                  :1;
    volatile unsigned long int IFE                  :1;
    volatile unsigned long int IBRK                 :1;
    volatile unsigned long int IROE                 :1;
    volatile unsigned long int ITOE                 :1;
    volatile unsigned long int ITMT                 :1;
    volatile unsigned long int ITRDY                :1;
    volatile unsigned long int IRRDY                :1;
    volatile unsigned long int IE                   :1;
    volatile unsigned long int TRBK                 :1;
    volatile unsigned long int IDCTS                :1;
    volatile unsigned long int RTS                  :1;
    volatile unsigned long int IEOP                 :1;
    volatile unsigned long int NC                   :19;
  
  }BITS;
  volatile unsigned long int WORD;
}CONTROL;

//波特率分频器
union{
  struct
  {
    volatile unsigned long int BAUD_RATE_DIVISOR     :16;
    volatile unsigned long int NC                    :16;
  }BITS;

  volatile unsigned long int WORD;
}DIVISOR;

}UART_STR;
......


这个程序用得很巧妙,看起来十分复杂。

【原理】

(1) 联合体中的成员共用一个内存,初始化操作对第一个成员进行;

(2) 位段将一个类型变量拆分为不同的位,从而对同一个类型定义的变量可以方便的进行位操作,相当于给位取别名

【分析】

(1) 首先建立了一个类型名为UART_STR的结构体,注意typedef的使用;

(2) 该结构体中包含了5个联合体,分别为RXDATA、TXDATA、STATUS、CONTROL、DIVISOR;

(3) 每个联合体中包含了一个使用位段的BITS和一个WORD,注意都是4字节,32bit

由【原理1】可知,BITS和WORD共用了一个内存,所以每个联合体只占了1个unsigned int,即4字节,对BITS操作时,WORD的取值也会改变,反之亦然。一方面节省了内存空间,另一方面,对BITS进行操作和对WORD操作是相当的,好像是给变量取了个别名。对BITS操作可以方便的实现各个位的操作,而WORD可以实现整体的操作。

【举例】

uart.c

(1) 利用BITS对单个位进行操作

 static int uart_send_byte(unsigned char data)  
  1. {  
  2.   UART->TXDATA.BITS.TRANSMIT_DATA=data;  
  3.   while(!UART->STATUS.BITS.TRDY);  
  4.   return 0;  
  5. }  
static int uart_send_byte(unsigned char data)
{
  UART->TXDATA.BITS.TRANSMIT_DATA=data;
  while(!UART->STATUS.BITS.TRDY);
  return 0;
}


(2) 利用WORD对整体进行操作

[html] view plaincopyprint?
  1. static int set_baudrate(unsigned int baudrate)  
  2. {  
  3.   UART->DIVISOR.WORD=(unsigned int)(ALT_CPU_FREQ/baudrate+0.5);  
  4.   return 0;  
  5. }  
static int set_baudrate(unsigned int baudrate)
{
  UART->DIVISOR.WORD=(unsigned int)(ALT_CPU_FREQ/baudrate+0.5);
  return 0;
}


 【位段】

位段的使用方便了对各位进行操作。但位段也有难以移植的缺陷。以32位机器为例。在PC机上,位段的储存顺序是从右向左存储的。而Macintosh上却是自左向右存储的。这就会造成一些问题。现有一个16位的结构。分别用BITS(位段结构,如示例)和WORD(unsigned int)表示。在PC机上进行操作时,BITS和WORD均存储在最低16位。但在Macintosh上,BITS被装入高16位,而WORD被装入低16位。这时,对BITS和WORD操作就不是等效的。

引用地址:http://blog.csdn.net/tandesir/article/details/7103975

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
我希望和大家交朋友,也希望大家都认识我呵呵。
推荐文章
最近访客