I/Oレジスタアドレスを関数に引数として渡す方法

このQ&Aのポイント
  • C言語において、I/Oレジスタアドレスを関数に引数として渡す方法を知りたいです。
  • 現在Renesas製RXマイコンでポート制御のプログラムを作成しています。I/Oポートレジスタの入出力設定を行っていますが、レジスタアドレスを引数として関数に渡し、関数内でレジスタ値を書き換える方法を教えてください。
  • ポインタ型を使用して関数内でレジスタ値を書き換えようとしていますが、上手くいきません。初心者なので、解決方法を教えていただけると幸いです。
回答を見る
  • ベストアンサー

I/Oレジスタアドレスを関数に引数として渡すには?

C言語について質問があるので投稿させていただきました。 現在Renesas製 RXマイコンにてポート制御のプログラムを作成しています。 そこで一点分らない点がありましたのでご教授いただければ幸いです。 現在I/Oポートレジスタの入出力設定を行っています。 レジスタ値を書き換えるだけであれば下記の通りかと思います。 #define PORTA (*(volatile unsigned char *)0x0008C00A) PORTA = 0x01; レジスタアドレスを引数として関数に渡し関数内でレジスタ値を書き換えるにはどうすれば よろしいでしょうか。 void main(void) { setPinMode(PORTA); PORTA.PODR.BIT.B0 = 0x01; while(1); } void setPinMode(uint32_t* portNumber) { *portNumber = 0x01; } としていますが上手くいきません。 型がおかしい? ポインタってものが分かってない? など色々考えてはみたのですが何分初心者なので解決に至っておりません。 よろしければご教授の程よろしくお願いいたします。

noname#230109
noname#230109

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

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

組み込みだとちょっと違うところがあるかもしれませんが, 普通の C なら setPinMode(PORTA); はエラーにならないでしょう>#1. 実引数は (volatile な) unsigned char, 仮引数は uint32_t * と型は違いますが, ISO C では整数からポインタに変換できる (ただしその結果は未保証) ので, これに従う限りコンパイルは通ってしまいます. 親切なコンパイラなら警告くらいは出すかな? ただ, PORTA が unsigned char を期待するのに対し setPinMode が uint32_t を要求するのでこの関数自体が危険です. 例えば「8ビット幅のポートに 32ビットの値を書き込む」ようなことになったりするわけですが, このときハードウェア的にどう動くかはわかりません. とりあえず ・setPinMode(PORTA); を setPinMode(&PORTA); にする ・void setPinMode(uint32_t* portNumber) を void setPinMode(volatile unsigned char* portNumber) にする で動くかもしれません.

noname#230109
質問者

お礼

ありがとうございました。無事点灯しました。因みに教えていただいた内容でやってみたのですが上手くいかず悩んでいましたが結局レジスタアドレスが違うというミスも犯していました。

その他の回答 (1)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

いつも言ってることですが 「『うまくいかない』の具体的内容は?」 「まずは、エラーメッセージをよく読みましょう」 PORTAの定義がそのままなら (*(volatile unsigned char *)0x0008C00A) というのは 0x0008C00A という数値を (volatile unsigned char *)型(volatileな unsigned char へのポインタ)と解釈 →それに * がついているので、ポインタが指す場所にあるデータ(volatileな unsigned char へのポインタが指す場所なので、volatileな unsigned char 型)になります。 void setPinMode(uint32_t* portNumber) に対して setPinMode(PORTA); // PORTAはunsigned char型) とすれば、もちろん、型が一致しません。 ・型をそろえる ・渡したいのはポインタ ・PORTAは実体であって、ポインタではない というあたりを落ち着いて考えれば解決できるはずです。 > ポインタってものが分かってない? そう思っているのなら、まずは、ポインタをマスターしましょう

noname#230109
質問者

お礼

>「まずは、エラーメッセージをよく読みましょう」 cubesuite+にてプログラムを作っているのですがエラーは出ていませんでした。 型を揃えていませんでした。 結局力不足で回答までたどり着けなかったので別の方法にて実装しました。 ありがとうございました。

関連するQ&A

  • Micom Car Rally に向けて製作をしているのですがI/Oレジスタ定義が理解できません。

    /************************************************************************/ /* H8/3048F-ONE 内蔵周辺機能 初期化 */ /************************************************************************/ void init( void ) { /* I/Oポートの入出力設定 */ PADDR = 0x5e; /* EEP-ROM,エンコーダ */ h8_3048.h /****************************************************************************/ /* H8/3048F-ONE用内蔵周辺機能のI/Oレジスタ定義 Ver1.03 */ /* 2006.04 マイコンカーラリー実行委員会 */ /****************************************************************************/ #define PADDR (*(volatile unsigned char*)0xfffd1) #define PADR (*(volatile unsigned char*)0xfffd3) (*(volatile unsigned char*)0xfffd1)はどういう意味なのでしょうか? PADRがなんなのかも分かりません。 どなたか、どうかご教授お願いします。

  • secが・・確認お願いできませんか?

    秒数が出ないのですがどこが違うのでしょうか? #define TCNT0 (*(volatile unsigned int *)0xffff68) #define GRA0 (*(volatile unsigned int *)0xffff6a) #define GRB0 (*(volatile unsigned int *)0xffff6c) #define TCR0 (*(volatile unsigned char *)0xffff64) #define TIOR0 (*(volatile unsigned char *)0xffff65) #define TIER0 (*(volatile unsigned char *)0xffff66) #define TSR0 (*(volatile unsigned char *)0xffff67) #define TSTR (*(volatile unsigned char *)0xffff60) #define ITU_CLOCK8 3 #define ITU_CLEAR_GRA 32 #define ITU_IE_IMFA 1 #define DI asm( "orc.b #0xc0,ccr" ) #define EI asm( "andc.b #0x3f,ccr" ) void start_itu0(); void int_imia0(void) __attribute__ ((interrupt_handler)); int cnt = 0, sec = 0, min = 0, hour = 0; char str[] = "timer 00:00:00"; int main(void) { lcd_init(); lcd_puts(str); start_itu0(); EI; for(;;) { if (cnt >=100) { cnt = 0; sec++; if (sec >=60) { sec = 0; min++; if (min >= 60) { min = 0; hour++; if (hour >= 24) hour = 0; } str[6] = '0' + hour /10; str[7] = '0' + hour %10; str[9] = '0' + min /10; str[10] = '0' + min %10; str[12] = '0' + sec /10; str[13] = '0' + sec %10; lcd_home(); lcd_puts(str); } } } return 0; }

  • H8S/2552Fにおけるプログラミング

    現在イエローソフト社のH8S/2552F USB-IF CPUボードを用いて,I/Oポートから32bitトルグスイッチの状態を出力しようとしています。それらのデータをシフトしつつ外部SRAMに送り、さらに32bitのデータとしてPCに取り込みたいと考えているのですが、その方法がわかりません。 以下に現状のプログラムを載せさせて頂きました。(間違いがあるのは十分承知です…) どなたか教えて下さい。よろしくお願い致します。 #define PORT4 (*((volatile unsigned char *)0xFFFFB3)) #define PORT9 (*((volatile unsigned char *)0xFFFFB8)) #define PORTH (*((volatile unsigned char *)0xFFFA14)) #define PORTJ (*((volatile unsigned char *)0xFFFA15)) unsigned long in_switch(void) {     return (PORTJ <<24);     return (PORTH <<16);     return (PORT9 <<8 );     return (PORTJ | PORTH | PORT9 | PORT4) ; } void main() {    puts("トグルスイッチテストプログラム");    while (1) {          unsigned long data;          printf("リターンキーで現在のスイッチ状態を表示します。");          fgetc(stdin); //リターンキー入力待ち          data = in_switch();//スイッチの状態を入力          printf("現在のスイッチ状態=%d(H'%02X)\n", data, data); //スイッチ状態表示 } }

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

    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; } というプログラムを作ったのですが、フローチャートがどのようになるのかがわからないです。またプログラムが間違っていたら教えてください。

  • ArduinoのI2Cで書き込み

    Arduino(Lazurite)を用いてINA231というICとI2Cで通信するプログラムを作成しています.マスタがArduino,スレーブがINA231です. INA231のレジスタアドレスの値を読み取ることはできましたが,レジスタの値を書き換えることが出来ません. 書き込み用の関数は以下のsetINA231になります. void setINA231(char SlaveAddress,const unsigned char *WriteData,char s){ Wire.begin(); Wire.beginTransmission(SlaveAddress); Wire.write(WriteData,s); Serial.write_byte(Wire.endTransmission(true)); } 上記関数を使用して,例えばスレーブアドレス0x40のレジスタアドレス0x00の値を0x4227に書き換えるように値を設定して関数を実行したところ,添付図の波形を取得出来,問題なく通信出来ているように感じます. どのようにすればI2Cでスレーブデバイスの値を書き換えることが出来ますでしょうか?何卒ご教授よろしくお願い致します.

  • valatile と多重代入の関連

    a=b=c=10; というような代入の方法がありますね。 これを多重代入と呼ぶかどうか知らないのですが、仮にそのように呼ぶことにします。 この多重代入の代入先がハードウエアのポートのようなとき、通常volatile修飾を付けます。 static volatile unsigned short *const REGS [] = { (volatile unsigned short*) BASE, (volatile unsigned short*) (BASE+0x20), (volatile unsigned short*) (BASE+0x40)}; のようだったとします。 上記のアドレスに *(REGS [0]) = *(REGS [1]) = *(REGS [2]) = 0; のように初期化を行ったとき、ある処理系では全てのアドレスに0を書き込み、 別な処理系では*(REGS [2])の内容をいったんリードし、それを*(REGS [1])に書き込みました。 どちらがC言語の仕様に忠実なのでしょうか? よろしくお願いいたします

  • 引数に二重配列のある関数について

    void calc(int *a,int b,int c){ a[0]=b+c; a[1]=b-c; } void main(void){ int x[2]; int y=2,z=5; calc(x,y,z); printf("x[0]=%d,x[1]=%d\n",x[0],x[1]); } 上のように引数が普通の配列の関数ならできるのですが, 引数が下のような多重配列になるとエラーが出てしまいできません。 void keisan(int **a,int b,int c){ a[0][0]=b+c; a[0][1]=b-c; a[1][0]=b*c; a[1][1]=b/c; } void main(void){ int x[2][2]; keisan(x,6,2); printf("x[0][0]=%d,x[0][1]=%d\n",x[0][0],x[0][1]); printf("x[1][0]=%d,x[1][1]=%d\n",x[1][0],x[1][1]); } 引数に多重配列を使った場合の関数の作り方について教えてください. お願いいたします.

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

    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; }

  • 関数の引数をvoid*でキャストする

    最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。 例えば、 func ( (void*) p ); こういうことです。 私の知っている知識では、 void* と 任意の型のポインタは キャストなしに相互に代入可能です。 関数の引数でも、キャストは要らないものだと思っていました。 そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・ 違うのでしょうか。処理系によるとか。 逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。 下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。 #include <stdio.h> #include <string.h> void byte_order(void *vp) { char char_array[4]; strncpy(char_array, vp, 4); printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]); } int main(void) { int a = 0x12345678; byte_order(&a); return 0; } このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。 また、C言語の質問であって、C++ではありません。

  • H8マイコン C言語でのプログラミング *((volatile unsigned char *)ってなんですか??

    現在、ある参考書に載っている、マイコンを用いてマザーボード上のLEDを点滅させるCのプログラムを勉強のために見ています。 その中に、 #define P5DDR (*(volatile unsigned char *)0xfffc8) という一行があるんですが、この中の*(volatile unsigned char *)という表現を見たことがなくて困っております。これは簡単に言うと、 #define P5DDR *0xfffc8 と、『P5DDRを0xfffc8のポインタで置き換える』と言い換えていいのでしょうか??

専門家に質問してみよう