AVRマイコンを用いてサーボを8個制御するプログラムをC言語で作っています。使っているマイコンはATmega64LでサーボはフタバのS3003、AVRstudio4.17とAVR-GCCを用いてコンパイルやシュミレートをしています。
プログラムはサーボを8個動かすために
タイマ2の比較一致割り込みで2.5msの周期をつくり
タイマ0の比較一致割り込みで0.5ms~2.5msのパルスをつくり
main関数でサーボの角度を制御するというものです。サーボ8個の角度の保持にはグローバル変数を用いています。
「サーボ初期位置→サーボ2個移動して固定」はうまくいくんですが「サーボ初期位置→※サーボ2個移動→さらに他のサーボ2個移動→はじめに動かしたサーボ2個を初期位置へ」というプログラムを書いたら、なぜか※をつけた「サーボ2個移動」の部分が実行されずその次の行動から実行されてしまいます。これはAVRに書き込んで確認したもので、シュミレータで確認するためにwait()などの待つ処理を除いてシュミレートしてみたのですが、「サーボ2個移動」の2行を飛ばして実行してしまっています。
具体的に飛ばされている部分は後述のソースコードのdo{・・・}while(1);の中の
servopos[FR_LEG]=31;
servopos[RL_LEG]=31;
で、do{・・・}while(1);の無限ループはservopos[FR_JOINT]=70;からservopos[RL_LEG]=94;を無限ループしています。
電気回路、C言語ともに初心者なので見当がつかず、いろいろ試したり調べてみてもわかりませんでした。
質問は「なぜこのようにプログラムを数行飛ばして実行してしまっているのか」です。ソースコードの指摘をしていただけると有り難いです。
ソースコード
#include <avr/io.h>
#include <avr/interrupt.h>
#define RL_JOINT 0
#define FR_JOINT 1
#define FL_LEG 2
#define RL_LEG 3
#define FL_JOINT 4
#define RR_JOINT 5
#define RR_LEG 6
#define FR_LEG 7
uint8_t phase=0;
uint8_t servopos[8]={94,94,94,94,94,94,94,94};
/*
void wait(uint16_t w){
while(w--){
volatile uint16_t i=200;
while(i--);
}
}
*/
ISR(TIMER2_COMP_vect){
PORTC=0x00;
TCNT0=0;
}
ISR(TIMER0_COMP_vect){
PORTC |= (1<<phase);
OCR0 = servopos[phase];
phase++;
if(phase>7){phase=0;}
}
int main( void ){
//ポート設定
DDRC=0xFF;
PORTC=0x00;
//タイマ0設定
OCR0 = 94;
TCCR0 |= (1<<WGM01)|(1<<CS02)|(1<<CS00);
TIMSK |= (1<<OCIE0);
//タイマ2設定
OCR2 = 79;
TCCR2 |= (1<<WGM21)|(1<<CS22);
TIMSK |= (1<<OCIE2);
// 全体割り込み許可
sei();
do{
// wait(10000);
servopos[FR_LEG]=31;
servopos[RL_LEG]=31;
//wait(1000);
servopos[FR_JOINT]=70;
servopos[RL_JOINT]=70;
//wait(1000);
servopos[FR_LEG]=94;
servopos[RL_LEG]=94;
}while(1);
}
No.1ベストアンサー
- 回答日時:
こんにちは。
servopos[FR_LEG]=31; // ←1
servopos[RL_LEG]=31;
<中略>
servopos[FR_LEG]=94; // ←2
servopos[RL_LEG]=94;
1の処理の後、その変数を使う事なく2の処理で新しい値(94)をセットしているため、コンパイラ君が
「ん?もしかして1の処理って要らないんじゃね?」
と気を利かせて、1を削除したと思われます。
処理1にも意味があるんだよ、という事をvolatileというキーワードで教えてあげればよいと思います。
回答ありがとうございます。volatileで宣言したらうまく動作しました。
volatile修飾子というのをはじめて知ったので調べてみました。AVR wikiのよくある質問を見てみたら「コンパイラが勝手にループの中の式を削除しちゃうんですけど。」というところにvolatile修飾子のことが書いてありました。指摘してくださったとおり最適化の対象になるみたいです。
これで滞りなくプログラミングできそうです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- 工学 モーターでブレーキを掛けると回らなくなります。 状況としては写真のJSP005というモーターをTA7 3 2022/08/07 20:58
- Visual Basic(VBA) VBAでの共有パスにつきまして 1 2023/03/04 17:24
- その他(プログラミング・Web制作) Arduino UNO のC言語 2 2023/04/18 19:42
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# C言語 3 2022/10/04 15:07
- C言語・C++・C# 質問です 下記のコードを分かりやすく解説お願いします 初心者です #include ‹stdio.h 3 2022/05/26 22:03
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
sleep関数の原理について
-
ショッピング
-
(H8マイコン)タイマ割込で変更...
-
Z80の割り込みについて
-
PICのPIN変化割り込みに...
-
実行した後、どうしてもフリー...
-
pic 複数の割り込み関数 切り分...
-
USJでの割り込み
-
USB機器からのデータ受信による...
-
電車で待機列の割り込みについ...
-
irqbalance って
-
緯度、経度の 10進法と 60進法...
-
Macターミナルで実行中のプログ...
-
VBAの配列サイズとメモリに関して
-
スレッドの安全な終了のさせ方
-
バックグラウンドのプロセスの...
-
Excelでのセル内容の高速消去方法
-
explorer.exeが異様にメモリを食う
-
C言語で、メモリを解放しないで...
-
VBSで応答不要のメッセージボッ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
インバウンドで迷惑している人...
-
pic 複数の割り込み関数 切り分...
-
スーパーのレジで並んでいたら...
-
ショッピング
-
Excelでタイマーの一時停止する...
-
電車で待機列の割り込みについ...
-
【組込み】割り込み中のstatic...
-
C言語でPICマイコン開発
-
CPUの処理量を減らすコーデ...
-
Amazonfireタブレットにわから...
-
マイコン C言語 割り込み処理...
-
USB機器からのデータ受信による...
-
一定時間操作がなかったら、と...
-
VB.net 割り込みの禁止
-
ウォッチドッグタイマ(WDT)の...
-
電車乗車時、並んでいるのに割...
-
USJでの割り込み
-
VB6でSendKeyを利用したTab移動...
-
PICでのプログラムによるチャタ...
-
H8マイコンで割り込みが任意の...
おすすめ情報