【C言語】関数間での配列データの受け渡しについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
きぃさま

【C言語】関数間での配列データの受け渡しについて

#1

投稿記事 by きぃさま » 7年前

現在、下記のサイトを参考に赤外線受信・送信リモコンを製作しています。
http://ur0.biz/GAU5
サイトに掲載されている通りにシリアルモニターから操作し、TVリモコンの信号を送受信したところ無事成功しました。
その為、次はPCとのシリアル通信を行わずに、基板上のボタンだけで送受信を行えるようにコードを変更しようと考えました。

元のコードでは、受信したデータをrecvSignal関数内でdata[]に格納してシリアルモニターに表示しています。
そして、モニターに表示された数字をユーザーがコピペして送信ボタンを押すことで、sendSignal関数内のdata[]に数値が格納され、データを送信することができます。

PCとのシリアル通信(シリアルモニタでの操作)を使わない場合、recvSignal関数とsendSignal関数間でdata[]の値をやりとりする必要があると考えました。
そこで、下記のようなコードに変更してみました。

シリアルモニターで確認してみたところ、データの受信は問題なく行えているようなのですが、送信の際には値が表示されません。
sendSignal関数内のtemp[]の中に、recvSignal関数から受け取ったdata[]の値を格納しようとしているのですが、おそらく受け渡しがうまくいっていないのだと思います。

どなたか回答していただけると幸いです。よろしくお願いします。

コード:

//========================================================
#include "types.h"
//========================================================
// Config
//========================================================

#define SERIAL_BPS             (57600)   /* Serial bps */
#define IR_IN                  (8)       /* Input      */
#define IR_OUT                 (13)      /* Output     */
#define Button                 (7)      
#define LED1                   (11)
#define LED2                   (12)

#define TIMEOUT_RECV_NOSIGNAL  (50000)
#define TIMEOUT_RECV           (5000000)
#define TIMEOUT_SEND           (2000000)

//========================================================
// Define
//========================================================
#define STATE_NONE             (-1)
#define STATE_OK               (0)
#define STATE_TIMEOUT          (1)
#define STATE_OVERFLOW         (2)
#define DATA_SIZE              (800)

int recvSignal();
void sendSignal(int*);
//========================================================
// Program
//========================================================
u2 data[DATA_SIZE];
u1 s = 0;   /* Button counter */

void sendSignal(int *temp){
  u4 count = 0;
  u1 i = 0;
  u2 time = 0;
  u4 tmp = 0;
  u4 index = 0;
  u4 us = 0;
  
  for(count=0; count<index; count++){
    time = temp[count];
    us = micros();
    do {
      digitalWrite(IR_OUT, !(count&1));
      delayMicroseconds(8);
      digitalWrite(IR_OUT, 0);
      delayMicroseconds(7);
    }while(s4(us + time - micros()) > 0);
  }
  for(i=0; i<index; i++){
    Serial.print(temp[i]);
    Serial.print(",");
  }
  Serial.print("\n");
  Serial.println("OK");
}

int recvSignal(){
  
  u1 pre_value = HIGH;
  u1 now_value = HIGH;
  u1 wait_flag = TRUE;
  s1 state = STATE_NONE;
  u4 pre_us = micros();
  u4 now_us = 0;
  u4 index = 0;
  u4 i = 0;
  
  while(state == STATE_NONE){
    now_value = digitalRead(IR_IN);
    if(pre_value != now_value){
      now_us = micros();
      if(!wait_flag){
        data[index++] = now_us - pre_us;
      }
      wait_flag = FALSE;
      pre_value = now_value;
      pre_us = now_us;
    }
    
    if(wait_flag){
        if((micros() - pre_us) > TIMEOUT_RECV){
          Serial.println("TIMEOUT");
          state = STATE_TIMEOUT;
          break;
        }
      } else {
        if((micros() - pre_us) > TIMEOUT_RECV_NOSIGNAL){
          state = STATE_OK;
          break;
        }
      }
  }
  
  if(state==STATE_OK){
    for(i=0; i<index; i++){
      Serial.print(data[i]);
      Serial.print(",");
    }
    Serial.print("\n");
    Serial.println("OK");
  }else{
      Serial.println("NG");
    }

  sendSignal(data);   /* data[]を受け渡す */
  return 0;
}

void setup(){
  Serial.begin(SERIAL_BPS);
  pinMode(IR_IN, INPUT);
  pinMode(IR_OUT, OUTPUT);
}

void loop(){
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);

  if(digitalRead Button == 0){
    s++;
    if(s>2) s = 0;
    delay(20);  //チャタリング防止
    while(digitalRead Button == 0){}   //押しっぱなし防止
  }

  if(s==0){
    Serial.println(s);
    digitalWrite(LED1,0);
    digitalWrite(LED2,0);
  }
  else if(s==1){
    Serial.println(s);
    digitalWrite(LED1,1);
    recvSignal();
  }
  else if(s==2){
    Serial.println(s);
    digitalWrite(LED2,1);
    sendSignal(data);
    delay(1000);
  }
}
        

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 【C言語】関数間での配列データの受け渡しについて

#2

投稿記事 by みけCAT » 7年前

sendSignal関数において、countもindexも0に初期化したままであるため、count<indexを条件とするfor文の中身は実行されません。
配列のデータそのものだけでなく、データの長さ(有効な要素数)も渡す必要があります。
オフトピック

コード:

#define Button                 (7)     

  if(digitalRead Button == 0){
というように定数の方にカッコを付けることでカッコを使わずに関数呼び出しをしているように見せるのは独特な書き方ですね。目からうろこでした。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

きぃさま

Re: 【C言語】関数間での配列データの受け渡しについて

#3

投稿記事 by きぃさま » 7年前

回答いただきありがとうございます。

指摘していただいたようにdata[]の要素数(index)もsendSignal関数に送信するように変更しました。

data→temp
index→num

この状態でシリアルモニターでnumの値を確認してみたのですが値は0になっていました。
複数の戻り値がある場合の関数の呼び出し方に問題があるのでしょうか。

コード:

//========================================================
#include "types.h"
//========================================================
// Config
//========================================================

#define SERIAL_BPS             (57600)   /* Serial bps */
#define IR_IN                  (8)       /* Input      */
#define IR_OUT                 (13)      /* Output     */
#define Button                 (7)      
#define LED1                   (11)
#define LED2                   (12)

#define TIMEOUT_RECV_NOSIGNAL  (50000)
#define TIMEOUT_RECV           (5000000)
#define TIMEOUT_SEND           (2000000)

//========================================================
// Define
//========================================================
#define STATE_NONE             (-1)
#define STATE_OK               (0)
#define STATE_TIMEOUT          (1)
#define STATE_OVERFLOW         (2)
#define DATA_SIZE              (800)

int recvSignal();
void sendSignal(u2 *temp, u4 *num);
//========================================================
// Program
//========================================================
u2 data[DATA_SIZE];
u1 s = 0;   /* Button counter */
u4 index = 0;

void sendSignal(u2 *temp, u4 *num){
  u4 count = 0;
  u1 i = 0;
  u2 time = 0;
  u4 tmp = 0;
  u4 us = 0;
  
  for(count=0; count<num; count++){
    time = temp[count];
    us = micros();
    do {
      digitalWrite(IR_OUT, !(count&1));
      delayMicroseconds(8);
      digitalWrite(IR_OUT, 0);
      delayMicroseconds(7);
    }while(s4(us + time - micros()) > 0);
  }
  for(i=0; i<index; i++){
    Serial.print(temp[i]);
    Serial.print(",");
  }
  Serial.print("\n");
  Serial.println("OK");
}

int recvSignal(){
  
  u1 pre_value = HIGH;
  u1 now_value = HIGH;
  u1 wait_flag = TRUE;
  s1 state = STATE_NONE;
  u4 pre_us = micros();
  u4 now_us = 0;
  u4 i = 0;
  
  while(state == STATE_NONE){
    now_value = digitalRead(IR_IN);
    if(pre_value != now_value){
      now_us = micros();
      if(!wait_flag){
        data[index++] = now_us - pre_us;
      }
      wait_flag = FALSE;
      pre_value = now_value;
      pre_us = now_us;
    }
    
    if(wait_flag){
        if((micros() - pre_us) > TIMEOUT_RECV){
          Serial.println("TIMEOUT");
          state = STATE_TIMEOUT;
          break;
        }
      } else {
        if((micros() - pre_us) > TIMEOUT_RECV_NOSIGNAL){
          state = STATE_OK;
          break;
        }
      }
  }
  
  if(state==STATE_OK){
    for(i=0; i<index; i++){
      Serial.print(data[i]);
      Serial.print(",");
    }
    Serial.print("\n");
    Serial.println("OK");
  }else{
      Serial.println("NG");
    }

  sendSignal(data, index);   /* data[]とindexを受け渡す */
  return 0;
}
...

void loop(){
...
  if(s==0){
    Serial.println(s);
    digitalWrite(LED1,0);
    digitalWrite(LED2,0);
  }
  else if(s==1){
    Serial.println(s);
    digitalWrite(LED1,1);
    recvSignal();
  }
  else if(s==2){
    Serial.println(s);
    digitalWrite(LED2,1);
    sendSignal(data, index);
    delay(1000);
  }
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 【C言語】関数間での配列データの受け渡しについて

#4

投稿記事 by みけCAT » 7年前

まず、sendSignal関数の第二引数がポインタになっているのはおかしいでしょう。
きぃさま さんが書きました:この状態でシリアルモニターでnumの値を確認してみたのですが値は0になっていました。
グローバル変数のindexの値を更新しているところはなさそうなので、128行目の呼び出しではnumの値は0になるでしょう。
呼び出し元のindexの値も確認してみるといいかもしれません。
(「シリアルモニターでnumの値を確認」ってどうやってやるんだろう?)
きぃさま さんが書きました:複数の戻り値がある場合の関数の呼び出し方に問題があるのでしょうか。
提示されたコードには複数の戻り値がある関数もそれを作ろうとしたと推測できる部分も見当たらないので、違うと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

きぃさま

Re: 【C言語】関数間での配列データの受け渡しについて

#5

投稿記事 by きぃさま » 7年前

indexにiの値を代入して更新したところ、無事動作しました。
第二引数がポインタになっていたのはミスです。色々いじっているうちに変えてしまったようです。

回答ありがとうございました。

返信

“C言語何でも質問掲示板” へ戻る