アプリ版:「スタンプのみでお礼する」機能のリリースについて

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

}

A 回答 (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というキーワードで教えてあげればよいと思います。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。volatileで宣言したらうまく動作しました。

volatile修飾子というのをはじめて知ったので調べてみました。AVR wikiのよくある質問を見てみたら「コンパイラが勝手にループの中の式を削除しちゃうんですけど。」というところにvolatile修飾子のことが書いてありました。指摘してくださったとおり最適化の対象になるみたいです。
これで滞りなくプログラミングできそうです。

お礼日時:2009/10/15 12:17

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!