スイッチの状態監視プログラムについて教えてください。
①スイッチ1、スイッチ2のいずれかが押されるまでは、
while (sw==0x03) {}の処理を行う
②スイッチ1、スイッチ2のいずれかが押されたら、
while(1){}の処理を行う
スイッチの状態を監視していて、スイッチが押されたらすぐに②の処理に移りたいのですが、
下記プログラムでは、5秒間待たなければなりません。(当然ですが…)
delay_ms()の時間を変えられれば良いのですが、諸事情により変更できません。
何か方法はありますでしょうか?
スイッチの状態監視について
Re: スイッチの状態監視について
単純に考えれば、delay_msを実行しないようにすればいいでしょう。C言語素人 さんが書きました:delay_ms()の時間を変えられれば良いのですが、諸事情により変更できません。
何か方法はありますでしょうか?
delay_msの前にif(0)を追加します。
while (sw==0x03) {
LATAbits.LATA4=0; //LED1点灯
LATAbits.LATA5=0; //LED2点灯
sw = PORTA & 0x03; //スイッチの状態を取得
if(0) delay_ms(5000); //delay時間調整
}
while(1)
{
LATAbits.LAT6=0; //LED3点灯
}
}
ビジーループで設定した時間が経過するのを待つのがいいかもしれません。
while (sw==0x03) {
LATAbits.LATA4=0; //LED1点灯
LATAbits.LATA5=0; //LED2点灯
run_timer(5000); //タイマーをセット
do {
sw = PORTA & 0x03; //スイッチの状態を取得
} while (sw==0x03 && !timer_done) //時間調整
}
while(1)
{
LATAbits.LAT6=0; //LED3点灯
}
}
タイマー割り込みを用いて指定した時間経過したらグローバル変数timer_doneを1にするように設定する関数とします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: スイッチの状態監視について
みけCAT様
回答ありがとうございます。
教えていただきたいことがあります。
①if(0)について
delay_msの前にif(0)を追加するとありますが、このif(0)の解釈の仕方が分かりません。
次の解釈で正しいでしょうか。
sw==0x03の状態が真で、これ以外(つまり、いずれかのスイッチが押された状態)が偽。
→この「偽」を表す式としてif(0)を追加
→つまり、「偽」の状態になれば、delay_msを実行しないで、ループを抜けることができる。
②タイマ割り込みについて
『もしも精度があまり重要でなく、かつ利用している環境でタイマー割り込みが利用できるのであれば、
ビジーループで設定した時間が経過するのを待つのがいいかもしれません。』
私もタイマ割り込みでの解決方法を考えてみました。
まだ正しく動作できていませんが、次の内容で挑戦しています。何かおかしな点がありましたら、指摘して頂けると助かります。
①スイッチ1、スイッチ2のいずれかが押されるまでは、
while (sw==0x03) {}の処理を行う
②スイッチ1、スイッチ2のいずれかが押されたら、
while(1){}の処理を行う
電源ON後、スイッチは押されていない状態です。
その状態から、スイッチが押されるまでの間、2.5sec周期で[動作0]を実行しています。
この間、タイマ割り込み(0.1msec周期)で常にスイッチの状態を監視し、押されたらただちにwhile(1)文の処理へ移行したいと考えています。
次のコードで試していますが、2.5sec周期の途中でスイッチを押しても、while(1)の処理へ移ってくれません。
回答ありがとうございます。
教えていただきたいことがあります。
①if(0)について
delay_msの前にif(0)を追加するとありますが、このif(0)の解釈の仕方が分かりません。
次の解釈で正しいでしょうか。
sw==0x03の状態が真で、これ以外(つまり、いずれかのスイッチが押された状態)が偽。
→この「偽」を表す式としてif(0)を追加
→つまり、「偽」の状態になれば、delay_msを実行しないで、ループを抜けることができる。
②タイマ割り込みについて
『もしも精度があまり重要でなく、かつ利用している環境でタイマー割り込みが利用できるのであれば、
ビジーループで設定した時間が経過するのを待つのがいいかもしれません。』
私もタイマ割り込みでの解決方法を考えてみました。
まだ正しく動作できていませんが、次の内容で挑戦しています。何かおかしな点がありましたら、指摘して頂けると助かります。
①スイッチ1、スイッチ2のいずれかが押されるまでは、
while (sw==0x03) {}の処理を行う
②スイッチ1、スイッチ2のいずれかが押されたら、
while(1){}の処理を行う
電源ON後、スイッチは押されていない状態です。
その状態から、スイッチが押されるまでの間、2.5sec周期で[動作0]を実行しています。
この間、タイマ割り込み(0.1msec周期)で常にスイッチの状態を監視し、押されたらただちにwhile(1)文の処理へ移行したいと考えています。
次のコードで試していますが、2.5sec周期の途中でスイッチを押しても、while(1)の処理へ移ってくれません。
void main(void){
OSCCON=0b01110000; //8MHz設定
TRISA = 0b00000011; // RA1-0 input
TRISB = 0b00000011; // RB1-0 input
TRISC = 0b00000000; // RC7-0 output
ADCON1 = 0x0F;
PORTC=0x00;
delay_ms(100);
//0.1msec周期タイマ割り込み設定
OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_2);
WriteTimer0(65436);
INTCONbits.TMR0IE = 1; //タイマ0割り込み許可
INTCONbits.GIE = 1; //割り込み許可
//(1)センサが白白状態の間に行う動作(黒検知するまで直進)
while (sw==0x03) { //動作0
LATCbits.LATC0=1;
LATCbits.LATC1=1;
LATCbits.LATC2=1;
LATCbits.LATC3=1;
delay_ms(5000); //delay時間固定2.5sec
LATCbits.LATC0=0;
LATCbits.LATC1=0;
LATCbits.LATC2=0;
LATCbits.LATC3=0;
delay_ms(5000); //delay時間固定2.5sec
}
//(2)少なくとも1つのスイッチが押された後の処理
while(1){
T0CONbits.TMR0ON=0; // Timer0 On/Off Control bit (1:Enable Timer0/0:Stop Timer0)
sw=PORTA &0x03;
switch(sw){
case 0: //動作1
LATCbits.LATC0=1;
LATCbits.LATC1=1;
LATCbits.LATC2=1;
LATCbits.LATC3=1;
break;
case 1: //動作2
LATCbits.LATC0=1;
LATCbits.LATC1=0;
LATCbits.LATC2=1;
LATCbits.LATC3=1;
break;
case 2: //動作3
LATCbits.LATC0=1;
LATCbits.LATC1=1;
LATCbits.LATC2=0;
LATCbits.LATC3=1;
break;
case 3: //動作3
LATCbits.LATC0=1;
LATCbits.LATC1=1;
LATCbits.LATC2=1;
LATCbits.LATC3=0;
break;
default:break;
}
}
}
//遅延関数
/**0.5msec Delay SubFunction at 10MIPS**/
void delay_ms(int time){
while(time > 0){
Delay100TCYx(10);
time--;
}
}
#pragma interrupt all_isr //割り込みの宣言
#pragma code isr_vector = 0x08 // 割込みベクタにジャンプ命令をセット
void goto_isr(void)
{
_asm
Goto all_isr
_endasm
}
#pragma code //割込み処理関数を用意
void all_isr(void) //割込み処理関数
{
sw = PORTA & 0x03; //スイッチの状態を取得
INTCONbits.TMR0IF = 0; ///タイマ0割り込みフラグのクリア
WriteTimer0(65436);
}
Re: スイッチの状態監視について
いいえ。C言語素人 さんが書きました: delay_msの前にif(0)を追加するとありますが、このif(0)の解釈の仕方が分かりません。
次の解釈で正しいでしょうか。
sw==0x03の状態が真で、これ以外(つまり、いずれかのスイッチが押された状態)が偽。
→この「偽」を表す式としてif(0)を追加
→つまり、「偽」の状態になれば、delay_msを実行しないで、ループを抜けることができる。
0はswに依存せず0なので、常にdelay_msを実行しないという意味になります。
delay_ms関数でswを全く見ていないので、スイッチを押してもすぐにdelay_ms関数から戻ることは出来ず、while(1)文の処理へ移行することもできません。C言語素人 さんが書きました:私もタイマ割り込みでの解決方法を考えてみました。
まだ正しく動作できていませんが、次の内容で挑戦しています。何かおかしな点がありましたら、指摘して頂けると助かります。
delay_ms関数の書き換えが許されるのであれば、
- swの状態を監視し、0x3で無かったらすぐに戻るようにする。
- もしもスイッチの入力があった時に割り込みがかけられるのであれば、(ハードウェアでチャタリング/バウンシング対策をした上で)
delay_msで利用する時間を数える関数をグローバルにし、キー入力の割り込みでその変数を0に書き換えるようにする。
(この場合ループ内の1個目のdelay_msの呼び出しの直後にもスイッチの判定をしないといけない)
もしくは、このようにキー入力があったら即戻る遅延関数を別に作ってもいいでしょう。
オフトピック
8MHzで10MIPS出るということは命令を並列で実行する高度なパイプライン的な装置を積んでいるか、
もしくはPLLで4倍くらいの周波数で走っているのかな?
もしくは単にコメントにデタラメが書かれているか。
【追記】
Delay100TCYx関数の効果がここで説明されているものであると仮定すると遅延時間はあっていそうだし、単にコメントが間違っているか、自分の「10MIPS」の解釈が間違っているかな?
MCC18 ライブラリ <delays.h>
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: スイッチの状態監視について
みけCAT様
回答ありがとうございます。
いただいた回答を参考にさせていただき、次のプログラムを記述してみました。
『swの状態を監視し、0x03で無かったらすぐに戻るようにする』
getsens関数を用意し、センサの状態を監視しています。
デバッグしていますが、スイッチが押されていない状態(sw==0x03)から、いずれかのスイッチを押しても、while(1)に移りません。
何か根本的に間違えているのでしょうか。
回答ありがとうございます。
いただいた回答を参考にさせていただき、次のプログラムを記述してみました。
『swの状態を監視し、0x03で無かったらすぐに戻るようにする』
getsens関数を用意し、センサの状態を監視しています。
デバッグしていますが、スイッチが押されていない状態(sw==0x03)から、いずれかのスイッチを押しても、while(1)に移りません。
何か根本的に間違えているのでしょうか。
void main(void){
OSCCON=0b01110000; //8MHz設定
TRISA = 0b00000011; // RA1-0 input
TRISB = 0b00000011; // RB1-0 input
TRISC = 0b00000000; // RC7-0 output
ADCON1 = 0x0F;
PORTC=0x00;
delay_ms(100);
//(1)スイッチが白白状態の間に行う動作
while (getsens() == 0x03) { //動作0
LATCbits.LATC0=1;
LATCbits.LATC1=1;
LATCbits.LATC2=1;
LATCbits.LATC3=1;
delay_ms(5000); //delay時間固定2.5sec
LATCbits.LATC0=0;
LATCbits.LATC1=0;
LATCbits.LATC2=0;
LATCbits.LATC3=0;
delay_ms(5000); //delay時間固定2.5sec
}
//(2)少なくとも1つのスイッチが押された後の処理
while(1){
sw=PORTA &0x03;
switch(sw){
case 0: //動作1
LATCbits.LATC0=1;
LATCbits.LATC1=1;
LATCbits.LATC2=1;
LATCbits.LATC3=1;
break;
case 1: //動作2
LATCbits.LATC0=1;
LATCbits.LATC1=0;
LATCbits.LATC2=1;
LATCbits.LATC3=1;
break;
case 2: //動作3
LATCbits.LATC0=1;
LATCbits.LATC1=1;
LATCbits.LATC2=0;
LATCbits.LATC3=1;
break;
case 3: //動作3
LATCbits.LATC0=1;
LATCbits.LATC1=1;
LATCbits.LATC2=1;
LATCbits.LATC3=0;
break;
default:break;
}
}
}
//遅延関数
/**0.5msec Delay SubFunction at 10MIPS**/
void delay_ms(int time){
while(time > 0){
Delay100TCYx(10);
time--;
}
}
/*=========================================================================
getsens()
==========================================================================*/
int getsens(void)
{
int sens, now_sens;
if((now_sens = sw) == 0x03) return 0x03;
delay_ms(20);
now_sens = sw;
while((sens = sw) != 0x03){
if(sens > now_sens) now_sens = sens;
}
return now_sens;
}
Re: スイッチの状態監視について
C言語素人 さんが書きました:何か根本的に間違えているのでしょうか。
- 問題になっているdelay_ms関数に全く手が加えられていない
- やりたそうなことに対して無駄に複雑そうでしかも意味がなさそうなgetsens関数が導入されている
(なんで最大値?動作2より動作3を優先したい?それにしては肝心の後半部分で使われていないし…)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)