前の状態を保持するプログラムについて

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

前の状態を保持するプログラムについて

#1

投稿記事 by C素人 » 8年前

SWが全部で8個あります。
SWの状態に応じてLEDが点灯するプログラムとなっております。

今テストしているプログラムを例に説明します。
1. swの状態が前の状態から変化した場合は、必ずReset()を実施する
2.  swの状態が変化しない場合は、その処理を繰り返す

[相談内容]
swの状態が、switch文で定義していない状態になった場合。
この場合も前の状態を保持してもらいたいのですが、↓のコードでは保持してくれません。

例えば、
case 0x00から、swの状態が0xF0になった場合、
case 0x00の処理(前の処理)を継続して欲しいです。

コード:

 while(1){

sw=PORTA &0xFF;

		if(prev_sw != sw) {
        	Reset();		//初期化
			delay_ms(1);	//delay
		}

		switch(sw){
			
			case 0x00:
				LED_R=1;
				LED_G=1;
				LED_B=1;
				break;

			case 0x01:
				LED_R=1;
				LED_G=0;
				LED_B=1;
				break;

			case 0x30:
				LED_R=1;
				LED_G=1;
				LED_B=0;
				break;

			default:break;
        	  }
 			prev_sw = sw;
		}

とけい

Re: 前の状態を保持するプログラムについて

#2

投稿記事 by とけい » 8年前

私も素人です、恐縮です。

あまりスマートではありませんが、
if文の中にswitchで、リセットするかどうかの分岐を放り込んでやれば良いのではないでしょうか?

コード:

 while(1){
 
sw=PORTA &0xFF;
 
        if(prev_sw != sw) {

         switch(sw){        //スグにリセットしないで、定義を確認する。
            
            case 0x00:     //定義があるからリセットする
            Reset();        //初期化
            delay_ms(1);    //delay
                break;
 
            case 0x01:     //定義があるからリセットする
            Reset();        //初期化
            delay_ms(1);    //delay
                break;
 
            case 0x30:     //定義があるからリセットする
            Reset();        //初期化
            delay_ms(1);    //delay
                break;
 
            default:break;  //定義が無いのでリセットしない
              }

        }
 
        switch(sw){
            
            case 0x00:
                LED_R=1;
                LED_G=1;
                LED_B=1;
                break;
 
            case 0x01:
                LED_R=1;
                LED_G=0;
                LED_B=1;
                break;
 
            case 0x30:
                LED_R=1;
                LED_G=1;
                LED_B=0;
                break;
 
            default:break;
              }
            prev_sw = sw;
        }


fm

Re: 前の状態を保持するプログラムについて

#3

投稿記事 by fm » 8年前

簡単な方法なら、if文のelseを使うか
if(???XXX???)
{
}else if(???YYY???)
{
}
else{//例外
}

switchのdefaultを使えばいいと思います。

switch(ZZZ)
{
case XX:
break;
case YY:
break;
default://例外
break;
}

fm

Re: 前の状態を保持するプログラムについて

#4

投稿記事 by fm » 8年前

swと、定数PORTA(ANDのマスク??)が何を表しているからよく分からないですが、宣言がstaticか、もしくは宣言から下でループ内に入ったら
staticにする必要はないです。

あとは、きちんと前回のループ内の結果を保存していますが、prev_swとswのif文の条件が不十分だと感じました。

sw=PORTA &0xFF;

if(prev_sw != sw && prev_sw==0x00 && sw==0xF0) {
Reset(); //初期化
delay_ms(1); //delay
}


こんな感じでしょうか?

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

Re: 前の状態を保持するプログラムについて

#5

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

C素人 さんが書きました:例えば、
case 0x00から、swの状態が0xF0になった場合、
case 0x00の処理(前の処理)を継続して欲しいです。
という条件には反してしまいますが、swの値に応じてLED_?の値を設定するだけなら、
fm さんが書きました:switchのdefaultを使えばいいと思います。
という方針が良さそうだと思います。

コード:

while(1){
	int next_r = 0, next_g = 0, next_b = 0; /* 設定する値 */
	int is_valid = 1; /* 定義があるか */

	sw = PORTA & 0xFF;

	switch(sw){
		
		case 0x00:
			next_r = 1;
			next_g = 1;
			next_b = 1;
			break;

		case 0x01:
			next_r = 1;
			next_g = 0;
			next_b = 1;
			break;

		case 0x30:
			next_r = 1;
			next_g = 1;
			next_b = 0;
			break;

		default:
			is_valid = 0;	/* 定義が無かった */
			break;
	}

	/* 定義がある場合のみ処理する */
	if(is_valid) {
		if(prev_sw != sw) {
			Reset();		//初期化
			delay_ms(1);	//delay
		}

		LED_R = next_r;
		LED_G = next_g;
		LED_B = next_b;
	}

	prev_sw = sw;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

C素人

Re: 前の状態を保持するプログラムについて

#6

投稿記事 by C素人 » 8年前

とけい様、fm様、みけCAT様

回答していただき、ありがとうございます。
みなさまの回答、大変勉強になります。

fm様の方針で試してみようと思っていますが、
1つ教えていただけないでしょうか。

定義がある場合 かつ SWの状態が変化した場合、
最後のif文の中でReset()を行っていますが、

next_x変数を使用しているのは何故でしょうか。
何か理由があるのでしょうか。
LED_R = next_r;
LED_G = next_g;
LED_B = next_b;

next_x変数を使用せず、LED_R,LED_G,LED_Bを直接使用した場合、
↓のコードでも良いのでしょうか。

初歩的な質問ですみません。

コード:

while(1){
    int next_r = 0, next_g = 0, next_b = 0; /* 設定する値 */
    int is_valid = 1; /* 定義があるか */
 
    sw = PORTA & 0xFF;
 
    switch(sw){
        
            case 0x00:
                LED_R=1;
                LED_G=1;
                LED_B=1;
                break;
 
            case 0x01:
                LED_R=1;
                LED_G=0;
                LED_B=1;
                break;
 
            case 0x30:
                LED_R=1;
                LED_G=1;
                LED_B=0;
                break;
 
        default:
            is_valid = 0;   /* 定義が無かった */
            break;
    }
 
    /* 定義がある場合のみ処理する */
    if(is_valid) {
        if(prev_sw != sw) {
            Reset();        //初期化
            delay_ms(1);    //delay
        }
    }
 
    prev_sw = sw;
}


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

Re: 前の状態を保持するプログラムについて

#7

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

C素人 さんが書きました:next_x変数を使用せず、LED_R,LED_G,LED_Bを直接使用した場合、
↓のコードでも良いのでしょうか。
PORTAの値が変化した時、
元のコードや提示したコードではReset()とdelay_ms(1)が呼び出された後にLED_xの更新が行われますが、
このコードではまずLED_xの更新が行われてからReset()とdelay_ms(1)が呼び出されます。

これでいいかどうかはC素人さんの想定する仕様によるでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

C素人

Re: 前の状態を保持するプログラムについて

#8

投稿記事 by C素人 » 8年前

みけCAT様

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

>PORTAの値が変化した時、
>元のコードや提示したコードではReset()とdelay_ms(1)が呼び出された後にLED_xの更新が行われますが、
>このコードではまずLED_xの更新が行われてからReset()とdelay_ms(1)が呼び出されます。

おっしゃる通り、試してみたら、Reset状態のまま、無限ループに入ってしまいました。
大変勉強になります。

いただいたコードを参考にして、最終的なプログラムに挑戦しています。
最終的には、LED_R, LED_G, LED,Bの所が、関数となります。
LED_R(),LED_G(),LEDB() という関数を用意して、それぞれの関数の中でLEDの点灯パターンを設定しています。

この場合、教えていただいたように、next_xを使用することができず、困っております
↓の記述ですと、LEDの点灯のあと、Reset状態に入ったままになってしまいます。

コード:

while(1){
    int next_r = 0, next_g = 0, next_b = 0; /* 設定する値 */
    int is_valid = 1; /* 定義があるか */
 
    sw = PORTA & 0xFF;
 
    switch(sw){
        
            case 0x00:
                LED_R();
                LED_G();
                LED_B();
                break;
 
            case 0x01:
                LED_R();
                LED_G();
                LED_B();
                break;
 
            case 0x30:
                LED_R();
                LED_G();
                LED_B();
                break;
 
        default:
            is_valid = 0;   /* 定義が無かった */
            break;
    }
 
    /* 定義がある場合のみ処理する */
    if(is_valid) {
        if(prev_sw != sw) {
            Reset();        //初期化
            delay_ms(1);    //delay
        }
    }
 
    prev_sw = sw;
}


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

Re: 前の状態を保持するプログラムについて

#9

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

C素人 さんが書きました:LED_R(),LED_G(),LEDB() という関数を用意して、それぞれの関数の中でLEDの点灯パターンを設定しています。
もし全部同じ関数を使うなら、分岐する必要は無いでしょう。

コード:

while(1){
    int is_valid = 1; /* 定義があるか */
 
    sw = PORTA & 0xFF;
 
    switch(sw){
        case 0x00:
        case 0x01:
        case 0x30:
            break;
 
        default:
            is_valid = 0;   /* 定義が無かった */
            break;
    }
 
    /* 定義がある場合のみ処理する */
    if(is_valid) {
        if(prev_sw != sw) {
            Reset();        //初期化
            delay_ms(1);    //delay
        }

        LED_R();
        LED_G();
        LED_B();
    }
 
    prev_sw = sw;
}
[/quote]
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

C素人

Re: 前の状態を保持するプログラムについて

#10

投稿記事 by C素人 » 8年前

みけCAT様

回答ありがとうございます。
すみません。記載したコードにミスがありました。
「同じ関数をすべて使う」ことはなく、caseごとに使う関数が異なります。

度々申し訳ありませんが、この場合の処理について教えていただけると助かります。

コード:

while(1){
    int next_r = 0, next_g = 0, next_b = 0; /* 設定する値 */
    int is_valid = 1; /* 定義があるか */
 
    sw = PORTA & 0xFF;
 
    switch(sw){
        
            case 0x00:
                LED_R();
                LED_B();
                break;
 
            case 0x01:
                LED_B();
                break;
 
            case 0x30:
                LED_G();
                LED_B();
                break;
 
        default:
            is_valid = 0;   /* 定義が無かった */
            break;
    }
 
    /* 定義がある場合のみ処理する */
    if(is_valid) {
        if(prev_sw != sw) {
            Reset();        //初期化
            delay_ms(1);    //delay
        }
    }
 
    prev_sw = sw;
}


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

Re: 前の状態を保持するプログラムについて

#11

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

C素人 さんが書きました:「同じ関数をすべて使う」ことはなく、caseごとに使う関数が異なります。

度々申し訳ありませんが、この場合の処理について教えていただけると助かります。
「このコードの場合」は、例えば関数を使うかをフラグで管理する方法が考えられます。

コード:

while(1){
    char use_r = 0, use_g = 0, use_b = 0; /* 各関数を使うか */
    char is_valid = 1; /* 定義があるか */
 
    sw = PORTA & 0xFF;
 
    switch(sw){
        
            case 0x00:
                use_r = 1;
                use_b = 1;
                break;
 
            case 0x01:
                use_b = 1;
                break;
 
            case 0x30:
                use_g = 1;
                use_b = 1;
                break;
 
        default:
            is_valid = 0;   /* 定義が無かった */
            break;
    }
 
    /* 定義がある場合のみ処理する */
    if(is_valid) {
        if(prev_sw != sw) {
            Reset();        //初期化
            delay_ms(1);    //delay
        }

        if (use_r) LED_R();
        if (use_g) LED_G();
        if (use_b) LED_B();
    }
 
    prev_sw = sw;
}
8ビットのマイコンでフラグにint型を使うと無駄にリソースを食うことが考えられるので、charにしました。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

C素人

Re: 前の状態を保持するプログラムについて

#12

投稿記事 by C素人 » 8年前

みけCAT様

回答ありがとうございます。
早速試してみたところ、意図する動作ができました。
本当にありがとうございます。

こちらの質問は解決とさせていただきます。
ただ、もう1つ問題が発覚してしまいましたので、そちらもご教授いただけると助かります。

閉鎖

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