質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

3回答

5043閲覧

割り込みとvolatile修飾子について

Alyn

総合スコア50

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

1クリップ

投稿2020/06/24 04:28

編集2020/06/24 04:43

質問内容

割り込みを使う際には変数に"volatile"を付けるとネットに記載されていましたが、どこまでが"volatile"を付けるべきかわかりません。
下記ソースコードには6種類の変数が使われて、そのどれに"volatile"を付ければよいのでしょうか?
serialEvent()はシリアル受信があった際に割り込まれる関数で、printFx()は割り込みピン(3)にLOW信号を受信した際に割り込まれる関数です。

①int recv
②static uint32_t before
③uint32_t current
④uint32_t a
⑤uint32_t b
⑥uint32_t gettime

ソースコード

Arduino

1#define INT_PIN 3 2 3void setup() 4{ 5 Serial.begin(9600); 6 pinMode(INT_PIN, INPUT_PULLUP); 7 attachInterrupt(digitalPinToInterrupt(INT_PIN), printFx, FALLING); 8} 9 10void loop() 11{ 12 //何もしない 13} 14 15void serialEvent() 16{ 17 int recv = 0; 18 19 //シリアル受信判定 20 if(Serial.available() > 0) 21 { 22 while(1) 23 { 24 recv = Serial.read(); //1byteずつ吐き出し 25 if(recv != -1) 26 { 27 if(recv == '1') 28 { 29 printFx(); 30 } 31 } 32 else 33 { 34 //シリアルデータなし 35 break; 36 } 37 } 38 } 39} 40 41void printFx() 42{ 43 static uint32_t before = 0; 44 uint32_t current = millis(); //ミリ秒時間取得 45 46 //2000ミリ秒経過判定 47 if(getTime(current, before) >= 2000) 48 { 49 Serial.println("Print!"); 50 before = current; 51 } 52} 53 54uint32_t getTime(uint32_t a, uint32_t b) 55{ 56 uint32_t gettime = 0; 57 58 if(a >= b) 59 { 60 gettime = a - b; 61 } 62 else 63 { 64 //オーバーフロー時 65 gettime = a + (0xFFFFFFFF - b); 66 } 67 68 return gettime; 69} 70

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2020/06/24 04:46

> 割り込みを使う際には変数に"volatile"を付けるとネットに記載されていましたが 引用元のURLください
YufanLou

2020/06/24 05:08

変数に`volatile`をつけるのは変数を複数の関数で使う場合、変数の数値を共有するためです。このコードに変数を共有してる関数がないと見れますが、したいことをもっと詳しく説明してください。ちなみに、Arduinoのメモリーが8-bitのため、`byte`より大きい変数(例えば`int`)に`volatile`をつけたら、乱数を読んでしまう可能性があります。
Alyn

2020/06/24 05:15

したいとはこのソースコードに問題があるかないかを知りたいことです。volatileを付けなくても動いていたので、volatileは必要なのか必要でないのか、volatileを付けないとどうなるのか、そもそもvolatileがわかりません。volatileが必要なソースコードはどういうソースコードか、このソースコードになぜvolatileが必要か、もしくは必要ないのかです。
guest

回答3

0

volatileはプログラムコードの管理外で値が変わってしまうことを明記するキーワードです。

このキーワードがない変数はメモリアクセスをせずにレジスタキャッシュアクセスや文脈等で最適化をする場合があります。

volatileをつけるべき変数は、
1.ハードウェア的に値が変わってしまうもの(タイマーやIOポート等のレジスタ)
2.メイン処理と割り込み処理で共用している変数

が主なものだと思います。

Arduinoの場合は、割り込み関数かそうでないかで判断すると良いと思います。

投稿2020/06/24 08:03

bjnes

総合スコア113

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Alyn

2020/06/24 08:19

ありがとうございます。割り込み関数内で使用されてる関数は当てはまるのでしょうか?引数のようなコピーは問題ないでしょうか?
bjnes

2020/06/25 00:12

変数のスコープ(直訳:見える範囲、意訳:生存期間、有効期限)について考えてみましょう。 関数の入り口から出口までより、変数の有効期限が長いものに対してvolatileをつける。 割り込み関数内で使用される関数は その関数内でstatic変数を利用している場合その変数にはvolatileをつけるべきです。 引数のようなコピーは一時変数です。関数の寿命と同じか短いはずです。 問題ありません。 C++だと色んな所にvolatileをつけることができますが、基本的に volatileをつけるべき変数は、 1.ハードウェアレジスタを指したポインタ変数 2.グローバル変数(割り込み関数とメイン関数で共用する) です。
guest

0

ベストアンサー

変数にvolatileをつけるのは変数を複数の関数で使う場合、変数の数値を共有するためです。このコードに変数を共有してる関数がないため、volatileの必要がありません。

Arduino公式サイトよりvolatileの例:

arduino

1// toggles LED when interrupt pin changes state 2 3int pin = 13; 4volatile byte state = LOW; 5 6void setup() { 7 pinMode(pin, OUTPUT); 8 attachInterrupt(digitalPinToInterrupt(2), blink, CHANGE); 9} 10 11void loop() { 12 digitalWrite(pin, state); 13} 14 15void blink() { 16 state = !state; 17}

ご覧の通り、loop()blink()stateを共有しています。volatileをつけないと、blink()stateを反転しても、loop()が見えません。なぜなら、byteは小さい型であり、速さのため、Arduinoのメモリーから読むことがなく、一度レジスタにコピーして、後でずっとそこから読むことです。volatileの意味は「変わりやすい」です。変わりやすいから、必ず毎回メモリーから新しい数値を読んでくださいと、コンパイラに伝えるのです。そうしたら、stateの変化がどこでも反映されます。

こういった依存関係がなければ、volatileの必要がありません。

投稿2020/06/24 06:03

YufanLou

総合スコア463

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Alyn

2020/06/24 07:17

ありがとうございます。仮にloop関数でgetTime関数を使うことになった場合でも共通として使ってる変数(引数)ではないため、何も問題はないという認識で合っていますでしょうか?
YufanLou

2020/06/24 07:24

はい、その通りです。
Alyn

2020/06/24 08:19

ありがとうございます!
guest

0

volatile ってのは最適化をしないように指定するキーワードです
結論から言うと、提示の変数はどれもVolatileを付ける必要はありません

「組み込み」ならではの基礎知識 ――スタートアップ・ルーチンからハードウェアまで|Tech Village (テックビレッジ) / CQ出版株式会社

投稿2020/06/24 06:19

編集2020/06/24 06:25
y_waiwai

総合スコア87778

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問