ビットフィールドアクセスの共通化
汎用ポートのアクセスに、ビットフィールドを利用していたんだけど
ポートの番号とビットの番号(意味わかるかなあ?)を指定して
目的のデータビットにアクセスする処理を作ることになって。
(個人的には(せっかく?)定義されてるビットフィールドを
無駄にする気がしてしかたがないのだけれど。)
ーー(省略)ーー
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にできないような…?
良い案が浮かびません(^^;
Posted by りきぞ~ at 2007年10月24日 01:02 | 返信
おはようございます。
コメントどうもです。
>>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;
んー・・こんな感じだったかな?
Posted by あらやん at 2007年10月24日 06:24 | 返信
>//ON以外の時
>temp |= (~BitCheck[bit]);
これ正しくは
temp &= (~BitCheck[bit]);
ですかね。
私ならテーブル使わずに
if(data==ON){
temp |= (UI_8)(1u << bit);
}else{
temp &= ~(UI_8)(1u << bit);
}
同じ記述が2カ所にあるのが気に入らないですがこんな感じでしょうか。
# テーブル使った方が早いのかな?
Posted by りきぞ~ at 2007年10月25日 00:04 | 返信
>temp &= (~BitCheck[bit]);
デスネ。昨日、別な人からも指摘されましたw
処理速度についてはよくわかりません~。
が、どっかでビットシフトだとステップ数が少し多いとか
聞いたような・・・
>同じ記述が2カ所にある
自分もあまり好きじゃないです(^-^;
Posted by あらやん at 2007年10月25日 10:51 | 返信
>const unsigned char *PortTbl[ ] = {
NGです。
>constつけちゃうと、参照先に書き込みができないですね?
そうです。
ポインタの参照先は非constで
ポインタのテーブル自体はconstであるべきです。
つまりconstの位置が問題です。ですから上で
>unsigned char * const PortTbl[]={
>かな?
>// const unsigned char * PortTbl[]={
>// は誤り。
と書いたんですが…(^^;
Posted by りきぞ~ at 2007年10月25日 22:38 | 返信
>ポインタの参照先は非constで
>ポインタのテーブル自体はconstであるべきです。
>つまりconstの位置が問題です。
んー、それなんですが自分もそれを期待してたんですけどね?(まあ、間違えてますけど)
なんか、Tblって言ってるけど普通の配列なので
どっちについてても効果が一緒?みたいな話が出てて。
今のところ単純な静的変数の配列にしてあります(^^;)
ターゲットマイコン用のコンパイラが届いてから試そうかな、と思ってたんですけど・・あー、VCとか使ってやってみればいいのか。
Posted by あらやん at 2007年10月26日 06:39 | 返信
>どっちについてても効果が一緒?みたいな話が出てて。
そんなわけないです。
試しに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
}
Posted by りきぞ~ at 2007年10月26日 13:15 | 返信
コメントどうもです。
(私も実際に試してみました、VC6ですが。)
>>どっちについてても効果が一緒?
なのは↓みたいな場合のことを言っていたようです。
const unsigned int *p;
unsigned int const *p;
これだと確かに同じですよね。
Posted by あらやん at 2007年10月26日 15:59 | 返信
>これだと確かに同じですよね。
ですね。
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
Posted by りきぞ~ at 2007年10月26日 23:03 | 返信