レジスタビット読み書き、構造体ビットドメイン定義、ビットドメイン操作、ビット操作
記事はhttp://book.51cto.com/art/201012/237939.htm,个人意见:C言语构造体位域操作レジスタは参考までに、使わなくてもいいです~
1.2.3ビットドメイン構造体の追加
1)ビットドメイン定義の追加
レジスタ内のビットドメインに直接アクセスする必要があることがよくあります.C 281 x C/C++ヘッダファイルおよび外付け例に係るビットドメイン構造体の方法は、多数のシート上の外付けレジスタにビットドメイン定義を提供する.例えば、CPUタイマ(CPU−timer)の各レジスタについて、1つのビットドメイン構造体タイプを定義することができる.CPUタイマ(CPU-timer)制御レジスタのビットドメイン定義は以下の通りである.
次に、ビットドメイン構造体によって定義された各メンバーまたは16ビットまたは32ビットレジスタの値にアクセスするために、共通体によって宣言される.例えば、タイマの制御レジスタ共通体は以下のようになる.
各レジスタのビットドメイン構造体タイプと共通体の定義が確立されると、CPUタイマ(CPU-timer)のレジスタ構造体タイプでは、各メンバーは、共通体定義を用いて書き換えることができる.
これで、CpuTimerレジスタのあるビットにCコードでビットドメインの方法でアクセスするか、レジスタ全体にアクセスすることができます.
ビットドメイン構造体を使用する方法には、次の利点があります.
(1)ユーザがマスク値を決定する必要がなく、ビットドメインを操作することができる.
(2)CCSビューウィンドウでレジスタとビットドメインの値を見ることができる.
(3)CCSを使用する場合、エディタは既存の構造体/ビットドメインメンバーのリストを選択します.この機能は、レジスタやビットドメイン名ファイルを参照することなく、コードの作成を容易にするCCSが自動的に完了します.
マスク値とは、ビットマスク(ビットマスクコード)であり、以下のコードセグメントにおいて定数TCR_MASKは、ビットマスクであり、大きなフィールドの特殊なビットをセットまたはクリアするための定数値である.
2)ビットドメインを使用する場合、「リード-修正-ライト」の注意事項レジスタ内の単一ビットドメインに対してライト操作を行うと、ハードウェアはリード-修正-ライト操作、すなわちレジスタ内の内容を読み出し、単一ビットドメインの値を修正し、レジスタ全体をライトバックする.上記の操作は、F 28 x上の1サイクルで完了する.ライトバック動作が発生すると、レジスタ内の他のビットは、読み出し時に読み出された同じ数値に書き込まれる.共通体定義を使用していないレジスタもあります.この方法でアクセスすることを推奨しないため、次のような例外もあります.
(1)イベント管理フラグレジスタなどの書き込み1クリアビットを有するレジスタ;
(2)いつでもレジスタにアクセスするには,番犬制御レジスタのようなビットを特殊な方法で書き込み操作しなければならないレジスタである.
ビットドメイン構造体とコモン定義レジスタがなく、*.bitまたは*.all名を使用してアクセスしません.たとえば、次のようにします.
3)コード長の考慮
ビットドメイン定義アクセスレジスタを使用すると、コードを読みやすく、修正しやすく、メンテナンスしやすくなります.この方法は、レジスタ内の個々のドメインへのアクセスやクエリーが必要な場合にも有効です.ただし、1つのレジスタに一定数のアクセスを行う場合、*.bitビットドメイン定義形式を使用してアクセスすると、*.all形式を使用してレジスタを書き込むよりも多くのコードが必要になることに注意してください.たとえば、次のようにします.
上記の方法により、可読性が非常に強く、修正が容易なコードを得ることができる.足りないのはコードが少し長いことです.ユーザがコードの長さにもっと関心を持っている場合は、*.all構造を使用してレジスタを一度に書き込みます.
1.2.4共用体構造体位域の応用例
【例】countは16ビットの符号なし整数カウンタであり、最大カウントは16進0 xffffであり、このカウント値を16進半バイトで分解することが要求される.
上記の例では、通常、シフトの方法で解くが、共通体構造体のビットドメインを用いる方法では、シフト演算を必要としない.以下、CCSがヘッダファイルで多く使用されている共通体構造体ビットドメインについて注記する.
まず、コモンボディ構造のボリュームドメインを定義します.
unionは、2つのメンバーを含む共通体タイプを定義します.1つは16ビットの符号なし整数変数iであり、もう1つは4つの半バイト変数(low,mid 0,mid 1,high)を含む構造体タイプです.同じメモリセルを占有し、i(Count.i)に値を割り当てることで、構造体の4つの変数の値を割り当てることができます.
上記のプログラムでは、共通体タイプと構造体タイプを定義するとともに、共通体と構造体タイプ名を定義せずに、この2つのタイプ変数の定義を直接完了しました.すなわち、HalfByteは、定義された構造体タイプを有する変数であり、Countは、定義された共通体タイプを有する変数である.共用体と構造体の関係を理解すると,以下の付与命令が明らかになる.
Count.i = cont;//コモンボディタイプメンバーiへの付与
共用体構造体定義により、共用体タイプメンバiに値を付与すると、構造体タイプ変数HalfByteとiが同一のメモリセルを占有するため、HalfByteの各メンバへの付与も完了する.
C言語の共通体構造体ビットドメイン定義は,レジスタビットドメインへのアクセスを完了する.アクセスされるビットドメインのメモリ内の特定の位置はコンパイラによって手配され、プログラマは注目する必要はありません.
次は、読者の参考になるレジスタビットドメインにアクセスする例です.
まず共通体構造体ビットドメイン定義を確立し,あるレジスタの16ビットを最低位から最高位にそれぞれ
Bit 1,Bit 2,...,Bit 16と定義する.
上記の定義があれば、ビットまたはビットにアクセスするのは簡単です.例えば、Bit 4、Bit 8、Bit 12およびBit 16を1にするには、2つの方法があります.
方法1:
方法2:
1.2.3ビットドメイン構造体の追加
1)ビットドメイン定義の追加
レジスタ内のビットドメインに直接アクセスする必要があることがよくあります.C 281 x C/C++ヘッダファイルおよび外付け例に係るビットドメイン構造体の方法は、多数のシート上の外付けレジスタにビットドメイン定義を提供する.例えば、CPUタイマ(CPU−timer)の各レジスタについて、1つのビットドメイン構造体タイプを定義することができる.CPUタイマ(CPU-timer)制御レジスタのビットドメイン定義は以下の通りである.
//*****************************************************************************
//DSP281x_headers\include\DSP281x_CpuTimers.h CPU
//*****************************************************************************
struct TCR_BITS // TCR_BITS ( )
{ Uint16 rsvd1:4; //3:0 , , 。 4
Uint16 TSS:1; //4 / , 5
Uint16 TRB:1; //5 , 6
Uint16 rsvd2:4; //9:6 , 7 10
Uint16 SOFT:1; //10 , 11
Uint16 FREE:1; //11 , 12
Uint16 rsvd3:2; //12:13 , 13 14
Uint16 TIE:1; //14 , 15
Uint16 TIF:1; //15 , 16
};
次に、ビットドメイン構造体によって定義された各メンバーまたは16ビットまたは32ビットレジスタの値にアクセスするために、共通体によって宣言される.例えば、タイマの制御レジスタ共通体は以下のようになる.
//*****************************************************************************
//DSP281x_headers\include\DSP281x_CpuTimers.h CPU
//*****************************************************************************
union TCR_REG // TCR_REG( )
{ Uint16 all;
struct TCR_BITS bit; //bit TCR_BITS
};
//all bit , 16 ,
各レジスタのビットドメイン構造体タイプと共通体の定義が確立されると、CPUタイマ(CPU-timer)のレジスタ構造体タイプでは、各メンバーは、共通体定義を用いて書き換えることができる.
//*****************************************************************************
//DSP281x_headers\include\DSP281x_CpuTimers.h CPU
//*****************************************************************************
struct CPUTIMER_REGS
{ union TIM_GROUP TIM; // ,TIM TIM_GROUP
//
union PRD_GROUP PRD; //
union TCR_REG TCR; //
Uint16 rsvd1; //
union TPR_REG TPR; //
union TPRH_REG TPRH; //
};
これで、CpuTimerレジスタのあるビットにCコードでビットドメインの方法でアクセスするか、レジスタ全体にアクセスすることができます.
//*****************************************************************************
//
//*****************************************************************************
CpuTimer0Regs.TCR.bit.TSS = 1; //
CpuTimer0Regs.TCR.all = TSS_MASK; //
ビットドメイン構造体を使用する方法には、次の利点があります.
(1)ユーザがマスク値を決定する必要がなく、ビットドメインを操作することができる.
(2)CCSビューウィンドウでレジスタとビットドメインの値を見ることができる.
(3)CCSを使用する場合、エディタは既存の構造体/ビットドメインメンバーのリストを選択します.この機能は、レジスタやビットドメイン名ファイルを参照することなく、コードの作成を容易にするCCSが自動的に完了します.
マスク値とは、ビットマスク(ビットマスクコード)であり、以下のコードセグメントにおいて定数TCR_MASKは、ビットマスクであり、大きなフィールドの特殊なビットをセットまたはクリアするための定数値である.
#define TCR_MASK 0x0010
…
CpuTimer0Regs.TCR.all = TCR_MASK;
2)ビットドメインを使用する場合、「リード-修正-ライト」の注意事項レジスタ内の単一ビットドメインに対してライト操作を行うと、ハードウェアはリード-修正-ライト操作、すなわちレジスタ内の内容を読み出し、単一ビットドメインの値を修正し、レジスタ全体をライトバックする.上記の操作は、F 28 x上の1サイクルで完了する.ライトバック動作が発生すると、レジスタ内の他のビットは、読み出し時に読み出された同じ数値に書き込まれる.共通体定義を使用していないレジスタもあります.この方法でアクセスすることを推奨しないため、次のような例外もあります.
(1)イベント管理フラグレジスタなどの書き込み1クリアビットを有するレジスタ;
(2)いつでもレジスタにアクセスするには,番犬制御レジスタのようなビットを特殊な方法で書き込み操作しなければならないレジスタである.
ビットドメイン構造体とコモン定義レジスタがなく、*.bitまたは*.all名を使用してアクセスしません.たとえば、次のようにします.
//*****************************************************************************
//
//*****************************************************************************
SysCtrlRegs.WDCR = 0x0068;
3)コード長の考慮
ビットドメイン定義アクセスレジスタを使用すると、コードを読みやすく、修正しやすく、メンテナンスしやすくなります.この方法は、レジスタ内の個々のドメインへのアクセスやクエリーが必要な場合にも有効です.ただし、1つのレジスタに一定数のアクセスを行う場合、*.bitビットドメイン定義形式を使用してアクセスすると、*.all形式を使用してレジスタを書き込むよりも多くのコードが必要になることに注意してください.たとえば、次のようにします.
//*****************************************************************************
//
//*****************************************************************************
CpuTimer0Regs.TCR.bit.TSS = 1; //1 =
CpuTimer0Regs.TCR.bit.TRB = 1; //1 =
CpuTimer0Regs.TCR.bit.SOFT = 1; // SOFT=1 FREE=1 ,
CpuTimer2Regs.TCR.bit.FREE = 1;
CpuTimer2Regs.TCR.bit.TIE = 1; //1 =
上記の方法により、可読性が非常に強く、修正が容易なコードを得ることができる.足りないのはコードが少し長いことです.ユーザがコードの長さにもっと関心を持っている場合は、*.all構造を使用してレジスタを一度に書き込みます.
CpuTimer0Regs.TCR.all = TCR_MASK; //TCR_MASK #define
1.2.4共用体構造体位域の応用例
【例】countは16ビットの符号なし整数カウンタであり、最大カウントは16進0 xffffであり、このカウント値を16進半バイトで分解することが要求される.
上記の例では、通常、シフトの方法で解くが、共通体構造体のビットドメインを用いる方法では、シフト演算を必要としない.以下、CCSがヘッダファイルで多く使用されている共通体構造体ビットドメインについて注記する.
まず、コモンボディ構造のボリュームドメインを定義します.
Uint16 cont,g,s,b,q; //16
cont=0xfedc; // cont
…
union //
{ Uint16 i; // i 16
struct //
{
Uint16 low:4; // 4 。 4 , 4
Uint16 mid0:4;
Uint16 mid1:4;
Uint16 high:4; // 4
}HalfByte; //HalfByte
}Count; //Count
unionは、2つのメンバーを含む共通体タイプを定義します.1つは16ビットの符号なし整数変数iであり、もう1つは4つの半バイト変数(low,mid 0,mid 1,high)を含む構造体タイプです.同じメモリセルを占有し、i(Count.i)に値を割り当てることで、構造体の4つの変数の値を割り当てることができます.
上記のプログラムでは、共通体タイプと構造体タイプを定義するとともに、共通体と構造体タイプ名を定義せずに、この2つのタイプ変数の定義を直接完了しました.すなわち、HalfByteは、定義された構造体タイプを有する変数であり、Countは、定義された共通体タイプを有する変数である.共用体と構造体の関係を理解すると,以下の付与命令が明らかになる.
Count.i = cont;//コモンボディタイプメンバーiへの付与
g = Count.HalfByte.low; // cont 0~3 g,g=0x000c
s = Count.HalfByte.mid0; // cont 4~7 s,s=0x000d
b = Count.HalfByte.mid1; // cont 8~11 b,b=0x000e
q = Count.HalfByte.high; // cont 12~15 q,q=0x000f
共用体構造体定義により、共用体タイプメンバiに値を付与すると、構造体タイプ変数HalfByteとiが同一のメモリセルを占有するため、HalfByteの各メンバへの付与も完了する.
C言語の共通体構造体ビットドメイン定義は,レジスタビットドメインへのアクセスを完了する.アクセスされるビットドメインのメモリ内の特定の位置はコンパイラによって手配され、プログラマは注目する必要はありません.
次は、読者の参考になるレジスタビットドメインにアクセスする例です.
まず共通体構造体ビットドメイン定義を確立し,あるレジスタの16ビットを最低位から最高位にそれぞれ
Bit 1,Bit 2,...,Bit 16と定義する.
union //
{ Uint16 all; // all 16
struct //
{
Uint16 Bit1:1; //0 Bit1 0 , 1
Uint16 Bit2:1; //1
Uint16 Bit3:1; //2
Uint16 Bit4:1; //3
Uint16 Bit5:1; //4
Uint16 Bit6:1; //5
Uint16 Bit7:1; //6
Uint16 Bit8:1; //7
Uint16 Bit9:1; //8
Uint16 Bit10:1; //9
Uint16 Bit11:1; //10
Uint16 Bit12:1; //11
Uint16 Bit13:1; //12
Uint16 Bit14:1; //13
Uint16 Bit15:1; //14
Uint16 Bit16:1; //15
}bit; //bit
}CtrlBit; //CtrlBit
上記の定義があれば、ビットまたはビットにアクセスするのは簡単です.例えば、Bit 4、Bit 8、Bit 12およびBit 16を1にするには、2つの方法があります.
方法1:
CtrlBit.bit.Bit4 = 1;
CtrlBit.bit.Bit8 = 1;
CtrlBit.bit.Bit12 = 1;
CtrlBit.bit.Bit16 = 1;
方法2:
CtrlBit.all = 0x8888;