• ベストアンサー

共用体のアドレスを取得したい

SH7047のプログラムです。 何をしたいのかと言うと、P_PORTD.PDDRL.BIT.PD4DR等を関数の中で変化させたいのです。 うまく行かない理由はおそらく「P_PORTD.PDDRL.BIT.PD4DRのアドレスは渡すことが出来ない」だとおもいます。 まぁそれも当然な話だと思うのですが、どうにかならないでしょうか? 個人的には「unsigned short* port」→「bit* port」の様に出来れば理想的なのですが。 何か良い方法を教えてください。よろしくお願いします。 #define P_PORTD (*(volatile struct st_portd *)0xFFFF83A2)/* PORTD Address */ struct st_portd { /* struct PORTD */ union { /* PDDRL */ unsigned short WORD; /* Word Access */ struct { /* Bit Access */ unsigned short :7; /* */ unsigned short PD8DR:1; /* PD8DR */ unsigned short PD7DR:1; /* PD7DR */ unsigned short PD6DR:1; /* PD6DR */ unsigned short PD5DR:1; /* PD5DR */ unsigned short PD4DR:1; /* PD4DR */ unsigned short PD3DR:1; /* PD3DR */ unsigned short PD2DR:1; /* PD2DR */ unsigned short PD1DR:1; /* PD1DR */ unsigned short PD0DR:1; /* PD0DR */ } BIT; /* */ } PDDRL; /* */ }; /* */ void main(void) { output(&P_PORTD.PDDRL.BIT.PD4DR,0xff); output(&P_PORTD.PDDRL.BIT.PD5DR,0xff); output(&P_PORTE.PEDRL.BIT.PE12DR,0xff); } void output(unsigned short* port,int data) { P_PORTE.PEIORL.WORD = 0x3fff; P_PORTE.PEDRL.WORD = data & 0xff; *port = 1; *port = 0; P_PORTE.PEIORL.WORD = 0x3f00; }

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

ビットフィールドへのポインタを得ることはできません。 現実的な解決方法としては、次のいずれかです。 1. ビットフィールドはやめ、ワードへのポインタとビット位置を引数として渡す。 2. 関数ではなくマクロにすることで参照渡しする。 ところで、(C++ではなく、Cの場合)ビットフィールドにunsigned short型を用いることは原則としてできません。処理系定義の型を使えることになっているので処理系が許せば使えますが、効率が上がるわけでもなく、移植性を捨てるほどのメリットはありません。

taunamlz
質問者

お礼

ありがとうございます。 1は考えていましたが、portが12個あるため、「ポートD,4番目」「ポートD,5番目」「ポートF,12番目」等と書くと後で大変そうだなぁと思って躊躇してました。、 2は初めて知りました。この方法には惹かれるものがあります。 >ビットフィールドにunsigned short型 unsignedが原則不可と言うのははじめて知りました。 これはコンパイラが自動的に生成したので、直すとなると数百行手で直さないといけないので、このまま使おうと思います。

その他の回答 (5)

回答No.6

No.3 さらに補足です。 この場合、マクロ展開なので output(P_PORTD.PDDRL.BIT.PD4DR,0xff); output(P_PORTD.PDDRL.BIT.PD5DR,0xff); output(P_PORTE.PEDRL.BIT.PE12DR,0xff); とする必要があります。(&は不要)そのまま置き換わるだけなので。

回答No.5

No.4 補足です。 No.4 の例は、あくまでもマクロ展開なので(しかもちょっと安直に作ったので) if (i == 0) output(&P_PORTD.PDDRL.BIT.PD4DR,0xff); のように書くと意図したとおりの動きをしません。 普通にストレートな実行だけなら、OKですし、 if (i == 0) { output(&P_PORTD.PDDRL.BIT.PD4DR,0xff); } なら、多分、OKかなと。

taunamlz
質問者

お礼

昨日、ANo.1さんの回答を見た後に自分で作ってみました。 一応、確認用に使わせていただきました。 ありがとうございます。

回答No.4

マクロを使って書いてみました。 こんな感じで行けると思います。 (行末の \ はマクロの継続行なので、\ の直後で改行してください) #define output(port, data) P_PORTE.PEIORL.WORD = 0x3fff;\ P_PORTE.PEIORL.WORD = 0x3fff;\ P_PORTE.PEDRL.WORD = data & 0xff;\ *port = 1;\ *port = 0;\ P_PORTE.PEIORL.WORD = 0x3f00 これで、 output(&P_PORTD.PDDRL.BIT.PD4DR,0xff); output(&P_PORTD.PDDRL.BIT.PD5DR,0xff); output(&P_PORTE.PEDRL.BIT.PE12DR,0xff); という書き方で、いけるはずです。 ただし、マクロ展開するので、プログラムサイズは増えます。 実際に展開してみると、こんな感じになっていました。 (実際には、; の後で改行せずにずっと続きますが、意味的には同じです) P_PORTE.PEIORL.WORD = 0x3fff; P_PORTE.PEIORL.WORD = 0x3fff; P_PORTE.PEDRL.WORD = 0xff & 0xff; *&P_PORTD.PDDRL.BIT.PD4DR = 1; *&P_PORTD.PDDRL.BIT.PD4DR = 0; P_PORTE.PEIORL.WORD = 0x3f00; P_PORTE.PEIORL.WORD = 0x3fff; P_PORTE.PEIORL.WORD = 0x3fff; P_PORTE.PEDRL.WORD = 0xff & 0xff; *&P_PORTD.PDDRL.BIT.PD5DR = 1; *&P_PORTD.PDDRL.BIT.PD5DR = 0; P_PORTE.PEIORL.WORD = 0x3f00; P_PORTE.PEIORL.WORD = 0x3fff; P_PORTE.PEIORL.WORD = 0x3fff; P_PORTE.PEDRL.WORD = 0xff & 0xff; *&P_PORTE.PEDRL.BIT.PE12DR = 1; *&P_PORTE.PEDRL.BIT.PE12DR = 0; P_PORTE.PEIORL.WORD = 0x3f00; cpp で展開した様子を見ると、こんな感じになっています。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

あ~, 「ビットフィールドに unsigned short が使えない」というのは, 「unsigned がダメ」ということではなく「short がダメ」ということです. _Bool, signed int, unsigned int は規格上全ての処理系で使えます. その他の型は, 「処理系で許してもらえれば」使えます. でも, この手の処理で「処理系の違いによる互換性」ってあまり考えなくていいような気がする....

taunamlz
質問者

お礼

ありがとうございます。 基本的にint以外は使うなと言うことですね。 それだといろいろと問題が出てしまうので、おっしゃった様にあまり考えずに使いたいと思います。

回答No.2

質問の内容が良くわかりません。 関数output()の中でPD4DRをセットしたいなら なぜ output()の引数の型がstruct PORTD *型でないのでしょう。 たとえば void output( struct st_portd * d) { d->PDDRL.BIT.PD4DR = 1; } なら、簡単にできますよねぇ。不思議だ。

taunamlz
質問者

補足

PD4DRだけでは無いからです。 なので質問の時に output(&P_PORTD.PDDRL.BIT.PD4DR,0xff); output(&P_PORTD.PDDRL.BIT.PD5DR,0xff); output(&P_PORTE.PEDRL.BIT.PE12DR,0xff); と、3行書いてみました。 実際にはこれが12個あります。 なので、output()の中に「PD4DR」を書くわけには行きません。 また、ポートDとポートEの違いもあります。

関連するQ&A

  • フローチャートについて

    H8マイコンでスイッチS1(PORT4-4)が押された場合は、LED1(PORT5-0)、スイッチS2(PORT4-5)が押された場合は、LED2(PORT5-1)、スイッチS3(PORT4-6)が押された場合は、LED3(PORT5-2)、スイッチS4(PORT4-7)が押された場合は、LED4(PORT5-3)が、それぞれ点灯するようなプログラムをつくりました。 #define P4DDR (* (volatile unsigned char *) 0xfffc5) #define P4DR (* (volatile unsigned char *) 0xfffc7) #define P4PCR (* (volatile unsigned char *) 0xfffda) #define P5DDR (* (volatile unsigned char *) 0xfffc8) #define P5DR (* (volatile unsigned char *) 0xfffca) int main(void) { unsigned char sw,ssw; P4DDR = 0x00; /* P4全ビットを入力に設定 */ P4PCR = 0xff; /* P4 MOSプルアップをONにする */ P5DDR = 0xff; /* P5全ビットを出力に設定 */ while (1) { sw = ~P4DR; /* 入力を反転 */ ssw = sw >> 4; /* swを4ビット右にシフトしたものをsswに代入 */ P5DR = ssw; /* sswをP5に出力 */ } return 0; } というプログラムを作ったのですが、フローチャートがどのようになるのかがわからないです。またプログラムが間違っていたら教えてください。

  • 8個のビットを1バイトとして扱う方法

    1バイトをビット扱いする方法は、 union un_p1dr { unsigned char one_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 ; } ; #define pt_da_p1dr (*(volatile union un_p1dr *)0xffffd0) と宣言すれば、pt_da_p1dr.bit.b7 = 1 ;の様にビット扱いが出来ます。 この反対を行える宣言方法は、あるでしょうか? つまり、任意の1ビットを8ビット集め、プログラムでバイトにてアクセスしたいのですが・・・・ ARMなどは、ビットの扱いが容易に可能です。しかし、CPUの周辺関係事情より、バイトでのアクセスが 可能なように、ハード割り当てが出来ません。 従って、現在は、プログラムにて、ビットを集め、バイトにして、アクセスしています。 なにか良い宣言方法があれば、ご伝授していただけないでしょうか? 宜しくお願いいたします。

  • H8SX/1655のアドレスエラー

    HEWのプログラミングで、割り込みの勉強をしているんですが なかなかうまくいきません・・・ 割り込みを使わないで、実験回路のLEDをスイッチを押すことで つけることはできました。 が、割り込みを使うとアドレスエラーとなり実行できません。。。 割り込みのプログラムはこんな感じです。 // vector 66 External trap IRQ2 __interrupt(vect=66) void INT_IRQ2(void){ led_out[0] = 0x00; //LEDを消す if(P1.PORT.BIT.B0 == 0) //スイッチが押されたら { led_out[0] = led[0]; //押されている間、点灯する } P2.DR.BYTE = led_out[0]; } mainプログラムは、 #include "iodefine.h" #include <machine.h> const unsigned char led[8] = { //0 1 2 3 4 5 6 7 0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80 }; unsigned char led_out[8]; void main(void) { P2.DDR = 0xff;//ledを出力に設定 P1.DDR = 0x00;//全部入力に設定 INT_IRQ2(); set_imask_ccr(0); while(1) { } } 割り込みの設定がわるいのでしょうか? スイッチは、P1に接続してLEDはP2に接続しています・・・

  • Aki-h8/3052マイコンについて

    今Aki-h8/3052マイコンを勉強しているのですが、初心者のためうまくいかず質問をしました。知識がないと思われるような質問をしてしまいますが、よろしくお願いします。 次のようなプログラムを書き込んで、LEDを点滅させたいのですが点滅しません。原因がわからないので、教えていただける方がいたらよろしくお願いします。 #define P5DDR (*(volatile unsigned char*)0xffffc8) #define P5DR (*(volatile unsigned char*)0xffffca) void wait (long loop){ while(loop--); } int main(void){ P5DDR = 0xff; while(1){ P5DR = 0xff; wait(200000); P5DR = 0; wait(200000); } } ポートBを使用した場合うまくいくのですが、ポート5を使用するとうまくいきません。 コンパイラにはGDLを、書き込みにはH8Write Turboを使用しています。

  • H8/3048 マイコンボードについて

    初心者の質問ですみません。 今、H8/3048のマイコンを使っていろいろやってみようと思っています。 マザーボードにP1の出力をLEDで表示できるような回路を組み、スイッチを押すとLEDを光らせるようなプログラムを作成し、実際に光らせることはできたのですが、A/D変換機能が使えません。 プログラムはネット上のサンプルプログラムを参考にしたので間違ってはいないと思うのですが、うまく変換されません。 入力電圧はきちんとAN0に入ってますし、ICやソケット部も拡大鏡で確認しましたがショートしている様子もありません。 これは故障してしまったのでしょうか? 何かの拍子に何処かがショートしてAD変換機能のみが壊れるというような事はあるのでしょうか? 非常に困っています。 どなたか回答よろしくお願いいたします。 ちなみにこのようなプログラムです。 #include <3048.h> void main(void){ int ad_data; P1.DDR = 0xff; P4.DDR = 0x00; P4.PCR.BYTE = 0xff; AD.ADDRA = 0; P1.DR.BYTE = 0xff; AD.ADCSR.BYTE = 0x33; while(AD.ADCSR.BIT.ADF == 0){} while(1){ if(P4.DR.BIT.B4 == 0){ ad_data = AD.ADDRA>>8; } P1.DR.BYTE = ad_data & 0xFF; } }

  • 構造体のメモリの確保のされかた

    2つ質問があります。 1. #include <iostream> using namespace std; union Data { unsigned long val1_val2; struct { unsigned short val1; unsigned short val2; } value; }; int main(void) { Data data; data.val1_val2 = (40 /* val1 */ << (sizeof(data.value.val1) * 8)) + 10 /* val2 */; cout << "val1 = " << data.value.val1 << endl; cout << "val2 = " << data.value.val2 << endl; return 0; } 上記ソースコードを実行すると、「val1 = 10 val2 = 40」という結果がでます。val1は上位2バイトを指しているはずだと考えて書いたのですが、何が間違っているのでしょうか? 構造体は上に書いたメンバーを下位に割り当てていくのでしょうか? 2. 32ビットコンピューターでは構造体のサイズは4の倍数バイトになると聞いたのですが、VC++で struct s1{ char c; }; のサイズをsizeof演算子で見てみると、1バイトで struct s2{ unsigned bit: 1; }; のサイズは4バイトでした。 前者は本当に1バイトで扱われているのでしょうか? 以上2つよろしくお願いします。

  • 1bppファイルを8bpp(raw)に変換する。

    環境 Windows7 VS2008 SP1 1bppの画像を8bppに変換しようとしているのですが うまくいきません。自分ではこれで 合っていると思うのですが・・・ 何かアドバイスお願いしますm(__)m int Main1bppTo8bpp(WCHAR *filename,int width,int height) { //width,heightは8bppになったときの幅,高さを指定する。 FILE *fpt; _wfopen_s(&fpt,filename,L"rb"); if(fpt==0x00) { MessageBox(NULL,L"1bppTo8bpp Error",L"1bppTo8bpp Error",MB_OK); return -1; } else { unsigned char *layer,*Output; layer=(unsigned char*)calloc(((width/8)+1)*height*sizeof(unsigned char),sizeof(unsigned char)); Output=(unsigned char*)malloc(width*height); //読み込み fread(&layer[0],sizeof(unsigned char),((width/8)+1)*height,fpt); FILE *fpt_output; _wfopen_s(&fpt_output,L"1bppTo8bpp.raw",L"wb"); int i,j,flag=0x00; for(i=0;i<((width/8)+1)*height;i+=((width/8)+1)) { for(j=0;j<((width/8)+1);j++) { //8bit目 if((layer[i+j]&BIT8)==BIT8) { Output[i+j+flag]=0x00; } else { Output[i+j+flag]=0xff; } //7bit目 if((layer[i+j]&BIT7)==BIT7) { Output[i+j+flag+1]=0x00; } else { Output[i+j+flag+1]=0xff; } //6bit目 if((layer[i+j]&BIT6)==BIT6) { Output[i+j+flag+2]=0x00; } else { Output[i+j+flag+2]=0xff; } //5bit目 if((layer[i+j]&BIT5)==BIT5) { Output[i+j+flag+3]=0x00; } else { Output[i+j+flag+3]=0xff; } //4bit目 if((layer[i+j]&BIT4)==BIT4) { Output[i+j+flag+4]=0x00; } else { Output[i+j+flag+4]=0xff; } //3bit目 if((layer[i+j]&BIT3)==BIT3) { Output[i+j+flag+5]=0x00; } else { Output[i+j+flag+5]=0xff; } //2bit目 if((layer[i+j]&BIT2)==BIT2) { Output[i+j+flag+6]=0x00; } else { Output[i+j+flag+6]=0xff; } //1bit目 if((layer[i+j]&BIT1)==BIT1) { Output[i+j+flag+7]=0x00; } else { Output[i+j+flag+7]=0xff; } flag=flag+8; } flag=0x00; } //最終的な「fwrite」はここでする。 fwrite(&Output[0],sizeof(unsigned char),width*height,fpt_output); free(layer); free(Output); fclose(fpt); fclose(fpt_output); } return 0;

  • AKI-h8 3069f C言語 HEW マイコン DIPスイッチで LED ON_OFF プログラム 「組込みI/O制御演習」

    こんにちは。 標記開発環境でマイコンを制御しています。 下記ソースでDIPスイッチのONOFFでLEDを点灯させたいのですが うまくいきません。 多分 P4DR.BIT.B0 =~P5DR.BIT.B0; の部分の修正が必要かと思うのですが。 どなたかご存知の方よろしくお願いします。 //------------------ #include "iodefine.h" void main(void); #ifdef __cplusplus extern "C" { void abort(void); } #endif void main(void) { P5DDR = 0; P5PCR.BYTE = 0xff; P4DDR = 0xff; while(1) { P4DR.BIT.B0 =~P5DR.BIT.B0; } } #ifdef __cplusplus void abort(void) { } #endif

  • 構造体へのポインタ

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の 他の関数内での使用の仕方が全くわかりません。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list {  char keyword[MAX_KW_LEN];  struct list *next;   /* 次の list へのポインタ */ }; struct list *hashtable[HASHSIZE]; /* ハッシュテーブル */ /* キーワード ( Cの予約語 ) */ static char kw[NUM_KW][MAX_KW_LEN] = {   "auto", "break", "double",   "enum", "char", "continue", "extern", "float", "for", "int",   "long", "register", "short", "signed", "static",   "struct", "typedef", "union", "unsigned", "return",   "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) {  int hashval = 0;  while (*key != '\0')   hashval += *key++;  return (hashval % HASHSIZE); } void InitHTable(void) {  int i;  struct list *p, *q;  int hashval;  for (i = 0; i < NUM_KW; i++) {   printf("%d\n",i);   if ((FindKeyWord(kw[i])) == FALSE) { /* 登録されていなかったら */             /* メモリを割り付ける */    if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) {     fprintf(stderr, "メモリ不足です。\n");     exit(2);    }    strcpy((*p).keyword, kw[i]);    hashval = Hash(kw[i]);    /* ハッシュ値を求めて */        if (hashtable[hashval] == NULL) { /* 未登録なら */     hashtable[hashval] = p;  /* p の指すアドレスを登録 */     p->next = NULL;    /* リストの末尾に NULL を追加 */    }    else {        /* 既に登録していたら */     q = hashtable[hashval];     while (q->next != NULL) {  /* データがなくなるまで */      q = q->next;    /* リストをたどる */     }     q->next = p;     /* リストの末尾に p の指すアドレスを登録 */     p->next = NULL;    /* その末尾に NULL を追加 */    }   }  } } int FindKeyWord(char *key) {  struct list *p;  for (p = hashtable[Hash(key)]; p != NULL; p = p->next)   if (!strcmp(key, (*p).keyword))  /* 登録済みなら */    return (TRUE);     /* TRUE を返す */   return (FALSE);      /* 未登録ならFALSE を返す */ } void ListKeyWord(void) {  int i;  struct list *p;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; p = p->next) /* p が NULL でなければ */               /* ハッシュ値とキーワードを表示 */    printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } /* malloc( ) で割り付けたメモリを解放 */ void FreeKeyWord(void) {  int i;  struct list *p, *q;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; ) { /* p が NULL でなければ */    q = p->next;      /* p->next を保存 */    free(p);       /* メモリを解放 */    p = q;        /* p->next を p に代入 */   } } int main(void) {  char word[MAX_KW_LEN];  int i;  InitHTable( );  ListKeyWord( );  for (i = 0; i < 4; i++) {   printf("Cの予約語を入力して下さい ");   fgets(word, 128, stdin);   if ((FindKeyWord(word)) == TRUE)    printf("%s は登録済みです。\n", word);   else    printf("%s は未登録です。\n", word);  }  FreeKeyWord( ); }

  • プログラミング構造体について。

    include<stdio.h> #include<stdlib.h> #include<string.h> struct person{ char name[10]; int gender; int age; }; void printPersonList(struct person *person_p, int size); void outputPersonList(struct person *person_p, int size); double getAverageOfAge(struct person *person_p, int size); int countMales(struct person *person_p, int size); int countFemales(struct person *person_p, int size); int main(void){ struct person *person_p; int i, count, gender, age, maleCount, femaleCount; char name[20]; double average; printf("登録する人数を入力してください。\n"); scanf("%d", &count); person_p = (struct person*)malloc(sizeof(struct person)* count); for(i=0; i < count; i++){ printf("名前・性別(男性:0, 女性:1)・年齢をスペース区切りで入力してください。\n"); scanf("%s %d %d", name, &gender, &age); strcpy((person_p + i) -> name, name); (person_p + i) -> gender = gender; (person_p + i) -> age = age; } printPersonList(person_p, count); outputPersonList(person_p, count); average = getAverageOfAge(person_p, count); printf("平均年齢:%f\n", average); maleCount = countMales(person_p, count); femaleCount = countFemales(person_p, count); printf("男性:%d名, 女性:%d名\n", maleCount, femaleCount); free(person_p); return 1; } void printPersonList(struct person *person_p, int size){ int i; printf("登録リスト\n"); printf(" name | gender | age\n"); printf("----------+--------+-----\n"); for(i=0; i < size; i++){ printf("%10s | %1d | %2d\n", (person_p + i) -> name, (person_p + i) -> gender, (person_p + i) -> age); } } void outputPersonList(struct person *person_p, int size){ FILE *output; int i; if((output = fopen("meibo.c", "w")) == NULL){ printf("meibo.cを開けませんでした。\n"); return; } for(i=0; i < size; i++){ fprintf(output, "%s, %d, %d\n", (person_p + i) -> name, (person_p + i) -> gender, (person_p + i) -> age); } fclose(output); } 残り3つの関数をすべて定義する(それぞれ10行程度) getAverageOfAge, countMales, countFemales どう定義すればいいのか教えてください。お願いします。

専門家に質問してみよう