• ベストアンサー

PICのプログラミングについて質問です

現在PICを制御するためのプログラムを組んでおり、その中で「連続で二回スイッチを押すとループを脱出」という動作をさせようと考え、以下のようなものを組んでみましたが、うまくループから脱出してくれませんでした。 悪い場所はなんとなくわかっているのですが・・・希望のように動作させるにはどのようにプログラムを組めばいいのか考えつかず困っています (;--) while(t == 3) { for( i = 0; i < 3000; ){ if(RA1 == 0) { for ( k = 0; k< 3000; ){ if(RA1 == 0) { t = 4; break;   } else { k++; DelayMs(1); } } } else { i++; DelayMs(1); } } }

質問者が選んだベストアンサー

  • ベストアンサー
  • maku_x
  • ベストアンサー率44% (164/371)
回答No.1

2重ループからの脱出ですから、goto もアリかと思いつつ、 > for( i = 0; i < 3000; ){ > if(RA1 == 0) { > for ( k = 0; k< 3000; ){ は、 for( i = 0; (i < 3000) && (t == 3); ){ if(RA1 == 0) { for ( k = 0; (k < 3000) && (t == 3); ){ で脱出できるかと。

chicken773
質問者

お礼

なるほど・・・多重ループから脱出はこのようにする方法が・・・ これは知りませんでした、お答え有難うございます(^^ お陰で無事装置を動作させる事ができました!

その他の回答 (1)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.2

すでに遅いと思いますがアドバイスを。 1.スイッチのチャタリングが考慮されていません。 ハード的にチャタリング除去されていない場合はプログラムで除去する必要があります。 http://www.picgames.org/modules/tinyd1/index.php?id=5 2.「連続で二回スイッチを押すとループを脱出」は、次のようにループを分けて考えた方が簡単です。 (1)ONを待つループ。 (2)OFFを待つループ。 (3)ONを待つループ。(2)から一定時間経過してしまったら(1)のループへ戻る。 (4)ここに抜けてくれれば条件成立です。

chicken773
質問者

お礼

この部分でチャダリングを考慮するのを忘れていました(;^^ 有難うございます。 お二方のアドバイスのお陰で無事装置を動作させる事ができました! 感謝の気持ちでいっぱいです

関連するQ&A

  • PICの割り込み機能

    現在電子工作をしており、それにPIC16F84Aを使っています。 正直アセンブリはよくわからないので、C言語でプログラムを作っています。 コンパイラはPICCLITEで、LEDの点灯・消灯に関するプログラムです。 機能としては ・RA0に入力があったときRB0につないであるLEDが消灯しているならLEDを点灯。 ・RA0に入力があったときRB0につないであるLEDが点灯しているならLEDを消灯。 ・RA1に入力があったときLEDが点灯しているなら5秒後にLEDを消灯。 というものを目指しています。 1つ目、2つ目の項目はif文で簡単に実現できましたが、割り込みがうまくいかず、 消えている状態でRA1に入力を入れたときなぜか5秒後に点灯してしまいます。 だからRB0の出力を逆にしてみたんですがうまくいかず・・・。 ハード的には、RB0には反対側から5Vをかけ、 RB0=0の時は点灯 RB0=1の時は消灯 としています。 またセラロックは10MHzのものを使用しています。 現在のプログラムとしては #include "pic.h" #define XTAL_FREQ 10MHZ #define MHZ*1000 void DelayUs(unsigned char cnt){ //時間待ち関数  unsigned char i;  i=(cnt)/(12MHZ/(XTAL_FREQ))|1;  while(--i!=0) continue; } void DelayMs(unsigned int cnt){ //時間待ち関数  unsigned char i;  do{   i=4;   do{    DelayUs(250);   }while(--i);  }while(--cnt); } int cnt,SW; //SWが0なら消灯 //SWが1なら点灯 void interrupt isr(void){ //割り込み関数  if(T0IF==1){   T0IF=0;   cnt--;  }  if(cnt==0){   RB0=1; //消灯   SW=0;   cnt=190;   T0IE=0;   GIE=0;  } } main() {  TRISA=0xFF; //入出力設定  TRISB=0x00;  PORTA=0x00;  PORTB=0x00;  SW=0;  OPTION=0x87; //プリスケーラの設定  TMR0=0x00;  T0IF=0;  T0IE=1;  cnt=190;  while(1){   if(RA0==1){    DelayMs(60); //チャタリング防止    if(RA0==1){     if(SW==0){      RB0=0;      SW=1;     }    else{     RB0=1;     SW=0;    }   }  }  if(RA1==1){   DelayMs(60); //チャタリング防止    if(RA1==1 && SW==1){     TMR0=0;     T0IF=0;     T0IE=1; //割り込み許可     GIE=1; //全体割り込み許可    }   }  } } インターネット上での割り込みのプログラムをいくつか見てみたのですが、 どれもすべて動作を終えて、あとはwhile(1)で割り込みを待つだけ というプログラムばかりでした。 僕のは基本的にRA0の入力によってLEDを点灯・消灯させつつ RA1の入力で割り込みを開始。 5秒後に消えたら割り込みを禁止する。 という仕様にしたいのですが・・・・・・。 1ヶ月ぐらいやってますがうまくいきません。 良ければご回答をお願いします。

  • 下記プログラミングについて

    下のプログラミングの解説ができる方がいましたら教えてください! どう頑張っても理解できなくて困っています;; もしかしたら間違っているところがあるかもしれませんが、よろしくお願いします。 ---------------------------------------------------------------- #include<stdio.h> #include<math.h> main() { int A,B,C,t,h,i,j,k; int sum_column,sum_row,diagonal1,diagonal2; int conf,diag,seed,max; int U[101][101],V[101][101]; int rand(); A=1,B=1,C=1; printf("Please define the pueen problem size(5-100).\n"); scanf("%d", &max); printf("Please input a seed(0-999).\n"); scanf("%d", &seed); for(i=1; i<=seed; i++){ U[1][1]=rand(); }; for(i=1; i<=max; i++){ for(j=1; j<=max; j++){ U[i][j] = -(abs(rand() % 8)); V[i][j]=0; }; };   /* Main program */ t=0; diag=1; while((diag>0)&&(t<500)){ diag=0; for(i=1; i<=max; i++){ for(j=1; j<=max; j++){ sum_column=0; sum_row=0; for(k=1; k<=max; k++){ sum_row=sum_row+V[i][k]; sum_column=sum_column+V[k][j]; } diagonal1=0; k=1; while(((j+k)<=max)&&((i-k)>=1)){ diagonal1=diagonal1+V[i-k][j+k]; k++; } k=1; while(((j-k)>=1)&&((i+k)<=max)){ diagonal1=diagonal1+V[i+k][j-k]; k++; } k=1; while(((j+k)<=max)&&((i+k)<=max)){ diagonal2=diagonal2+V[i+k][j+k]; k++; } k=1; while(((j-k)>=1)&&((i-k)>=1)){ diagonal2=diagonal2+V[i-k][j-k]; k++; } k=1; h=0; conf=1; if(sum_column == 0) h=1; if(sum_row == 0) h++; if((sum_column+sum_row==2) && (diagonal1<2) && (diagonal2<2)) conf=0; U[i][j]=U[i][j]-A*(sum_row+sum_column-2)-B*(diagonal1+diagonal2)+C*h; if(U[i][j]>8) U[i][j]=8; if(U[i][j]<-8) U[i][j]=-8; if(U[i][j]>0) V[i][j]=1; else V[i][j]=0; diag=diag+conf; }; }; t++; printf("t=%d\n", t); if((t % 15) < 5) C=4; else C=1; }; printf("the number of iteretion steps=%d\n", t); printf("\n"); for(i=1; i<=max; i++){ for(j=1; j<=max; j++){ if(j==max){ if(V[i][j]==1) printf("*\n"); else printf("-\n"); } else{ if(V[i][j]==1) printf("* "); else printf("- "); } } } }

  • PIC のプログラムについて どうすれば終了できますか?

    PICのプログラムは実行させると、永遠にmain関数がループするようになっていると思うのですが、それを抜け出すにはどのようにしたらいいでしょうか? 例えば #include <pic.h> void main(void) { int a,b; a=1; if(a == 1) ????????//main脱出したい } ?の部分をどのように書けば脱出できますか?

  • プログラミングについての質問です。

    プログラミングについての質問です。 できるだけ早めの解答をお待ちしてます。 次の構文をC言語として表したいのですが、一応作っては見たもののできません。 1.S→E<A4> 2.E→TX 3.X→+<A1>T<A2>X 4.X→ε 5.T→FY 6.Y→*<A1>F<A2>Y 7.Y→ε 8.F→-<A1>F<A2>Y 9.F→I<A1> 10.F→(E) 11.I→a|b|c|d|e A1はスタック上に項目を挿入するという動作。 A2はスタックから3つの項目を除去し、それらを'='と次に割り当てられる4つ組とともに印刷し、この整数をスタックにおくという動作。 A3はスタックから2つの項目を除去し、それらを'='と次に割り当てられる4つ組とともに印刷し、この整数をスタックにおくという動作。 A4はスタックから1つの項目を除去する。 #include<stdio.h> #include<string.h> intmain(void) { charsymbol[10][10]; inti=0,j,k=0; printf("Inputsymbol:"); while(1) {scanf("%s",symbol[i]); if(strcmp(symbol[i],"_")==0) {i--;break;} i++;} printf("symbol="); for(j=0;j<=i;j++) {printf("%s",symbol[j]);} printf("¥n"); gotoS; S: if(strcmp(symbol[k],"a"|"b"|"c"|"d"|"e")==0) {gotoE;return;} elseif(strcmp(symbol[k],"-")==0) {gotoE;return;} elseif(strcmp(symbol[k],"(")==0) {gotoE;return;} else {gotoerror;} E: if(strcmp(symbol[k],"a"|"b"|"c"|"d"|"e")==0) {gotoT;gotoX;return;} elseif(strcmp(symbol[k],"-")==0) {gotoT;gotoX;return;} elseif(strcmp(symbol[k],"(")==0) {gotoT;gotoX;return;} else {gotoerror;} X: if(strcmp(symbol[k],"+")==0) {k++;gotoT;gotoX;return;} else {if(strcmp(symbol[k],"_")!=0) {gotoerror;} elseif(strcmp(symbol[k],")")!=0) {gotoerror;} } T: if(strcmp(symbol[k],"a"|"b"|"c"|"d"|"e")==0) {gotoF;gotoY;return;} elseif(strcmp(symbol[k],"-")==0) {gotoF;gotoY;return;} elseif(strcmp(symbol[k],"(")==0) {gotoF;gotoY;return;} else {gotoerror;} Y: if(strcmp(symbol[k],"*")==0) {k++;gotoF;gotoY;return;} elseif(strcmp(symbol[k],"_")==0) {gotoerror;} elseif(strcmp(symbol[k],")")==0) {gotoerror;} elseif(strcmp(symbol[k],"+")==0) {gotoerror;} I: if(strcmp(symbol[k],"a"|"b"|"c"|"d"|"e")==0) {k++; } elsegotoerror; F: if(strcmp(symbol[k],"-")==0) {k++;gotoF; } else if(strcmp(symbol[k],"a"|"b"|"c"|"d"|"e")==0) {gotoI;} else {if(strcmp(symbol[k],"(")==0) {k++;gotoE; if(strcmp(symbol[k],")")!=0) gotoerror;} elsegotoerror;} error: printf("No¥n"); exit(1); 制限字数の関係でプログラムを削ったりしています。 見にくくてすみません。 御指導よろしくお願いします。

  • PICで1μsの待機時間を作りたい

    現在PIC18F2431の制御プログラムを組んでいます。 INTOSC 8M を使って1μsと3μsの待機時間を作りたくて下記のような、空のループを用意しました。 for(i=0; i<1; i++) ; しかしこれではどう頑張っても6μsよりも小さくすることが出来ません。 何か良い方法はないでしょうか? どうかご教授ください

  • PIC 出力を持続したい

    鉄道模型のコントローラーを作っています。 マイコンはPIC16F886です。 以下のようなプログラムを作りました。 (ただし、mainよりも前の設定等は今回の質問に関係ないと思われますので、省略してあります) 質問箇所は(1)~(5)です。 while(RC3==0)のときその部分がループされるようになっていまして、ループから抜けた時に(1)(2)(3)で変更された内容は保持されているのですが、(4)(5)はループを抜けた瞬間に0になってしまいます。 たとえば、(1)と(4)の条件を満たしてRA1=1、RB6=1となり、relay1とrelay3がONになります。 しかしループを抜けると、relay1はONのままなのですがrelay3がOFFになってしまいます。 なぜでしょうか。 出力しているピンの問題なのですか? ご回答よろしくお願いします。 以下プログラム (省略) main() { PORTA = 0x00; PORTB = 0x00; PORTC = 0x00; TRISA = 0b11111001; TRISB = 0b00111111; TRISC = 0b11111111; ANSEL = 0b00000001; ANSELH = 0b00111111; ADCON1 = 0b00000000; while(RC3==1); // マスコンを「非常」にしないと動作しない while(1) { if(RC3==0 && SPD==0) // マスコンが非常、かつ車両が停止している時 { while(RC3==0) // マスコンが非常のとき、無限ループ開始 { if(RC4==0) // 方向セレクトSWがRC4の時・・・(1) { RA2 = 0; // relay2をOFF DelayUs(20); RA1 = 1; // relay1をON } else if(RC5==0) // 方向セレクトSWがRC5の時・・・(2) { RA1 = 0; // relay1をOFF DelayUs(20); RA2 = 1; // relay2をON } else if(RC4==1 && RC5==1) // 方向セレクトSWが中立の時・・・(3) { RA1 = 0; // relay1をOFF DelayUs(20); RA2 = 0; // relay2をOFF } if(RC6==0) // 出力セレクトSWがRC6の時・・・(4) { RB6=1; // relay3をON } else if(RC7==0) // 出力セレクトSWがRC7の時・・・(5) { RB6=0; // relay3をOFF } } } ADCON0 = 0b10000001; // 最高速度をAN0から読み込む DelayUs(20); // ADCが安定するまで待つ GODONE=1; // ADC起動 while(GODONE); // ADC終了まで待つ MAX=ADRESH; // ADCの上位8ビットを最高速に代入 if(RA3==0) // マスコンが加速3の時 { ADCON0 = 0b10110101; // 加速度をAN13から読み込む } if(RA4==0) // マスコンが加速2の時 { ADCON0 = 0b10101101; // 加速度をAN11から読み込む } if(RA5==0) // マスコンが加速1の時 { ADCON0 = 0b10100101; // 加速度をAN9から読み込む } if(RC1==0) // マスコンが減速1の時 { ADCON0 = 0b10100001; // 加速度をAN8から読み込む } if(RC2==0) // マスコンが減速2の時 { ADCON0 = 0b10101001; // 加速度をAN10から読み込む } if(RC3==0) // マスコンが非常の時 { ADCON0 = 0b10110001; // 加速度をAN12から読み込む } DelayUs(20); // ADC安定するまで待つ GODONE=1; // ADC起動 while(GODONE); // ADC終了まで待つ ACC=ADRESH; // ADCの上位8ビットを加速度に代入 func01(); } }

  • ループを途中で抜けたいのですが。

    無限ループさせているwhileやfor文などで、 何かのキーを押すとループを抜けるように設定したいのですが可能でしょうか? (scanfやcinなどをループの中に組み込まずに。ctrl+Cも無しで。) (あと、フォーム上ではなくコンソール上で。) 多分説明不足なのでもうちょっと詳しく。 たとえば、 while ( i != 1 ){ j += 1; } の様な無限ループを設定したとして、 本来なら if (j > 100 ){ break; } とか、 while文の中に scanf ( "%d" , &i ); 等を入れて終了条件を満たさせるべきですが、 そうではなく、ひたすら無限ループを続けているところにEscキーを押すとループから脱出するようなプログラムを作ってみたいのです。 そういうプログラムは可能でしょうか? どうかご教授下さい。 使用コンパイラ:Visual C++ 2008 Express Edition

  • C言語のプログラミングについて質問です。

    以下の文を出力して入力:に16進数を入れると10進数に変換した数値の小さい列順に並ぶプログラムを作りたいのですがうまく出来ません。 仕様は以下に記載します。 入力:__、__、__、__、__EnterKeyで結果を表示。 以下のバブルソートの文のどこをいじれば良いでしょうか? 返答宜しくお願いします。 #include <stdio.h> int main (void) { char data[256]; int val[100]; int i = 0; int work; int j; int k; printf("入力 = "); scanf("%s",data); for(i=0;i<100;i++){ val[i] = 0; } k=0; for(i = 0;i<100 ; i++){ if(data[i] == 0x00){ //data[i]がNULLだったら処理を抜ける k++; break; //enterキーでprintf出力 } else if(data[i] == ','){ //カンマだったら /*printf("%d\n",k);*/ k++; } else{ if(data[i] >= 'A' && data[i] <= 'Z'){ //data[i]にAからZが入ったら val[k] = val[k] *16 + data[i] -'A'+10; } else if(data[i] >= '0' && data[i] <= '9'){ //data[i]に0から9が入ったら val[k] = val[k] *16 + data[i] -'0'; } } } /* printf("k=%d\n",k); for(i=0;i<k;i++){ printf("出力 = %d\n",val[i]); } */ //バブルソート//     for(i=0; i<k-1; i++) { if(val[i] < val[i+1]) { } else{ work = val[i]; val[i] = val[i+1]; val[i+1] = work; } } for(i=0;i<k;i++) { printf("出力 = %d\n",val[i]); } }

  • PICプログラミング

    テストプログラムとして以下のようなプログラムを作ってみました。 RB0を一定時間だけHIGHにした後に、LOWに戻すプログラムなのですが、テスターで測定したところRB0は結果的にHIGHのままでした。wait関数が間違っているのかと思いましたが、どう考えても文法的な間違いはないと思います。 原因がまったく分からないので、分かる方がいましたらヒントだけでもいいので是非教えてください。よろしくお願いします。 PIC16F819 セラロック20MHz #include <pic.h> __CONFIG(DEBUGEN&WDTDIS&LVPDIS&HS&PWRTEN); #define voltage 5.0 void wait(int a){ int i,j; for(i=0;i<=30000;i++) for(j=0;j<=2000*a;j++); } void init_a2d(void){ ADCON0=0x80; ADCON1=0x00; ADON=1; } unsigned char read_a2d(unsigned char channel){ channel&=0x07; ADCON0&=0xC5; ADCON0|=(channel<<3); // GODONE=1; // while(GODONE)continue; ADCON0|=0x04; while(ADCON0&0x04)continue; return(ADRESH); } void main(void){ int i,j; unsigned char x; double y; init_a2d(); GIE=0; TRISB=0x00; PORTB=0x00; RB0=1;    wait(5); RB0=0; }

  • PIC24F C言語プログラミングについて

    PIC24Fについて こんにちわ PIC24Fの勉強をしています。 使っているPICはPIC24FJ64GA002で、コンパイラは MPLAB IDE,C30 です。 現在LEDを2つ使って、異なるタイミングで点滅させるプログラムを作りたいと思っています。 参考書に載っていたプログラムを参考にして、1つのLEDを点滅させることはできました。 下にそのプログラムを書きます。 #include "p24FJ64GA002.h" /// コンフィギュレーション ビットの設定 _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & BKBUG_OFF & COE_OFF & ICS_PGx1& FWDTEN_OFF ) /// 8MHz*PLL4=32MHz (Full Speed) _CONFIG2( IESO_OFF & FNOSC_FRCPLL & FCKSM_CSDCMD & OSCIOFNC_OFF & IOL1WAY_OFF & I2C1SEL_PRI & POSCMOD_NONE) int main(void) { CLKDIV = 0; // クロックの分周1:1に設定 AD1PCFG = 0xFFFF; // ポートA全ディジタルに指定 /// ポートの入出力モード設定 TRISB = 0; // ポートB を出力に設定 /// タイマ1の設定 FOSC=16MHz,プリスケーラ 1:256, 200msec=5Hz PR1 = 12500-1; // 16000000/5/256=12500 T1CON = 0b1000000000110000; /// メイン ループ while(1) { if(IFS0bits.T1IF) // タイマ割り込みチェック { IFS0bits.T1IF = 0; // 割り込みフラグクリア /// LEDの反転制御 LATBbits.LATB15 = !LATBbits.LATB15; } } } 2つの点滅のタイミングをずらすために、またさらにPRレジスタ(PR2)を付け加え、適当な値にします。 すると、割り込みフラグT2IFビットがセットされると思います。 そこでさらにもう一つif文をつけ、同様の書式で異なるピンにLATを割り振ってやれば異なるタイミングで割り込みが起きるというやり方でやろうと思っています。(まずこれで正しいのかどうかもわかりませんが・・・。) ですがそれ以降がよくわかりません。 まず if文の中に入っている(IFS0bits.T1IF)とはどういう意味を持っているのでしょうか? C言語にも疎く、if文に=や不等号などの条件が入っていないものを見るのも初めてです。 この他、○○bits.○○ というような書き方が手持ちの参考書に頻出している上に、まだ読んでいる途中ですので何とも言えませんが、どこにも詳しく書いてありません。 LATBbits.LATB15 = !LATBbits.LATB15 くらいならなんとなく想像はつきますが書式もいまいちわかりません また、 同様にif文を使ってやる場合、IFSxレジスタは何を使えばいいのでしょうか? 割り込みベクタテーブル表を見ると、使っているタイマ1の割り込みフラグがIFS0<3>となっていましたので、PR2によりセットされたT2IFと合わせて if(IFS0bits.T2IF)~ と適当に入力してみましたが、シミュレータでもうまくいきません。 分かりづらい文章かと思いますが、よろしくお願いします。

専門家に質問してみよう