ビットフィールドアクセスの共通化
汎用ポートのアクセスに、ビットフィールドを利用していたんだけど
ポートの番号とビットの番号(意味わかるかなあ?)を指定して
目的のデータビットにアクセスする処理を作ることになって。
(個人的には(せっかく?)定義されてるビットフィールドを
無駄にする気がしてしかたがないのだけれど。)
ーー(省略)ーー struct st_p1 { union { unsigned char BYTE; struct { unsigned char B7:1; unsigned char B6:1; unsigned char B5:1; unsigned char B4:1; unsigned char B3:1; unsigned char B2:1; unsigned char B1:1; unsigned char B0:1; } BIT; }DR; } ーー(省略)ーー #define P1(*(volatile struct st_p1 *)ポートのアドレス); #define P2(*(volatile struct st_p2 *)ポートのアドレス); #define P3(*(volatile struct st_p3 *)ポートのアドレス); ・ ーー(省略)ーー ・↑みたいな構造体を使ってアクセスしてたのを、 ポート番号、ビット番号を指定して共通の関数で アクセスするように変更するんだけど・・・
P1.DR.BIT.B1= ON、をSetPort(PORT1,BIT1,ON);こんな感じ?
問題はどうやって実現しようかなあ、というところで。
//const unsigned char *PortTbl[ ] = {
※コメントで間違いを指摘していただきましたが、よく考えたらconstつけちゃうと、参照先に書き込みができないですね?・・・orz
unsigned char * const PortTbl[ ] = {&(P1.DR.BYTE),
&(P2.DR.BYTE),
&(P3.DR.BYTE),
・
・
};const unsigned char BitCheck[ 8 ] = {
0x01,
0x02,
0x04,
0x08,
0x10,
0x20,
0x40,
0x80
};void SetPort( UI_8 port,UI_8 bit, B_8 data ){
UI_8 temp;
ーー(省略)ーー
temp = *PortTbl[port];
temp |= BitCheck[bit];
*PortTbl[port] = temp;
ーー(省略)ーー
return;
}
こんな感じのを考えてみたんだけど、どうだろう?
もっといい手があれば知りたいデス。
りきぞ~
まず、
>const unsigned char PortTbl[]={
これ、宣言間違えてますよね。
unsigned char * const PortTbl[]={
かな?
// const unsigned char * PortTbl[]={
// は誤り。
>temp = *PortTbl[port];
>temp |= BitCheck[bit];
>*PortTbl[port] = temp;
仮引数dataが使われていないようですがいいんでしょうか。
あとこれだとONにはできてもOFFにできないような…?
良い案が浮かびません(^^;
あらやん
おはようございます。
コメントどうもです。
>>const unsigned char PortTbl[]={
>これ、宣言間違えてますよね。
そうですね。間違えてるwww
>仮引数dataが使われていないようですがいいんでしょうか。
>あとこれだとONにはできてもOFFにできないような…?
えーと、その辺は「ーー(省略)ーー」がミソでw
ホントは、
temp = *PortTbl[port];
if(data == ON){
//ONの時
temp |= BitCheck[bit];
}
else{
//ON以外の時
temp |= (~BitCheck[bit]);
}
*PortTbl[port] = temp;
んー・・こんな感じだったかな?
りきぞ~
>//ON以外の時
>temp |= (~BitCheck[bit]);
これ正しくは
temp &= (~BitCheck[bit]);
ですかね。
私ならテーブル使わずに
if(data==ON){
temp |= (UI_8)(1u << bit);
}else{
temp &= ~(UI_8)(1u << bit);
}
同じ記述が2カ所にあるのが気に入らないですがこんな感じでしょうか。
# テーブル使った方が早いのかな?
あらやん
>temp &= (~BitCheck[bit]);
デスネ。昨日、別な人からも指摘されましたw
処理速度についてはよくわかりません~。
が、どっかでビットシフトだとステップ数が少し多いとか
聞いたような・・・
>同じ記述が2カ所にある
自分もあまり好きじゃないです(^-^;
りきぞ~
>const unsigned char *PortTbl[ ] = {
NGです。
>constつけちゃうと、参照先に書き込みができないですね?
そうです。
ポインタの参照先は非constで
ポインタのテーブル自体はconstであるべきです。
つまりconstの位置が問題です。ですから上で
>unsigned char * const PortTbl[]={
>かな?
>// const unsigned char * PortTbl[]={
>// は誤り。
と書いたんですが…(^^;
あらやん
>ポインタの参照先は非constで
>ポインタのテーブル自体はconstであるべきです。
>つまりconstの位置が問題です。
んー、それなんですが自分もそれを期待してたんですけどね?(まあ、間違えてますけど)
なんか、Tblって言ってるけど普通の配列なので
どっちについてても効果が一緒?みたいな話が出てて。
今のところ単純な静的変数の配列にしてあります(^^;)
ターゲットマイコン用のコンパイラが届いてから試そうかな、と思ってたんですけど・・あー、VCとか使ってやってみればいいのか。
りきぞ~
>どっちについてても効果が一緒?みたいな話が出てて。
そんなわけないです。
試しにVS2005で以下のコードを実行させてみましたが、
明らかに結果が異なります。
組込みの世界ではROM/RAMリソースの割り当てにも関わってくるので重要な事だと思います。
void Hoge(void)
{
unsigned char a, b, c;
const unsigned char * p1[]={&a,&b,&c};
unsigned char * const p2[]={&a,&b,&c};
p1[0] = &b; // OK
*p1[0] = 0; // コンパイルエラー
p2[0] = &b; // コンパイルエラー
*p2[0] = 0; // OK
}
あらやん
コメントどうもです。
(私も実際に試してみました、VC6ですが。)
>>どっちについてても効果が一緒?
なのは↓みたいな場合のことを言っていたようです。
const unsigned int *p;
unsigned int const *p;
これだと確かに同じですよね。
りきぞ~
>これだと確かに同じですよね。
ですね。
const unsigned int *p と宣言してあったら
「constなunsigned int型変数」への「ポインタp」であり
unsigned int const *pは
「unsigned int型のconst変数」への「ポインタp」って感じですかね。(同じ意味)
unsigned int * const p と宣言してあったら
「unsigned int変数」への「constポインタp」という意味ですので、
左から順番に読んで「*」を「~への」と訳すと割と判りやすいかもです(^^)
…そうでもないかも?w