• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:disPICの質問)

トランジスタ技術2007年8月号のdsPICプログラム仕様

このQ&Aのポイント
  • トランジスタ技術2007年8月号に載っているdsPICプログラムのC言語ソースコードを教えてください。操作によりLEDの光度を変化させる仕様で、ハードウェアはPIC基盤実験基盤を搭載したユニバーサル基盤です。
  • プログラムは赤LEDのデューティー比を10段階に変化させます。また、緑LEDはデバック用に使用され、約300ms毎に点滅します。
  • 黒スイッチを押すと光度が1段階減少し、白スイッチを押すと光度が1段階増加します。デューティー比が0:10か10:0になると、それ以上の操作は無視されます。

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

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

>担当に確認したら20ではなく2でした。間違えてたみたいです。 >また赤LED のON/OFFのデューティー比は10段階ではなく11段階だったみたいです。 2msならデューティー比制御は問題ないですが他に矛盾が生じます。 >カウントアップし15回毎にon/offを反転させる。おおよそ300ms毎に点滅するのでプログラムが暴走していないか確かめられる。 このままだと30ms毎に点滅しますので、150回毎に点滅に変更してください。 >上のプログラム設計の詳細を解くのにそれに関連するヒントまたはサイトってありませんか? 一気に解決するサイトはありません。 dSPICの本でしたら発売されていますが、C言語やマイコンをある程度知っていることが前提になっている本です。 http://www.amazon.co.jp/%E9%9B%BB%E5%AD%90%E5%88%B6%E5%BE%A1%E3%83%BB%E4%BF%A1%E5%8F%B7%E5%87%A6%E7%90%86%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE-dsPIC%E6%B4%BB%E7%94%A8%E3%82%AC%E3%82%A4%E3%83%89%E3%83%96%E3%83%83%E3%82%AF-CD-ROM%E4%BB%98-%E5%BE%8C%E9%96%91-%E5%93%B2%E4%B9%9F/dp/4774128635 8bitのPICと違ってネット上の情報は少ないので、直接当てになるサイトを私は知りません。 私自身もdSPICで遊んでますが、8bitのPICの経験もありますし、付録のCD-ROMにあったPDFファイルの情報だけで十分プログラムは出来ています。 まず、あなた自身の問題を整理してみましょう。 1.C言語の知識。 このサイトを見てください。 http://www.asahi-net.or.jp/~YF8K-KBYS/c0.html このサイトのC入門5までは最低でも理解できている必要があります。 もし出来ないのであれば、C言語を勉強する必要があります。 2.ハードウェアの知識。 スイッチのチャタリング防止についての知識はありますか? デューティー比の意味は理解できていますか?ちゃんと説明できますか? 3.ソフトウェアを組むための能力。 仕様を理解して自分なりに手順を組み立てる能力が必要です。これは一石一丁に手に入れる能力ではなく、訓練が必要です。 仕様を整理して書き出してみてください。 プログラム全体のイメージが出来ているかどうかも問題ですが、出来るだけ細かく書き出せるかが理解度になります。 他の人に作業を頼む場合に作成する作業指示書のような物を書いてみてください。マイコンを作業する人間だと思って手順書を書き出します。

paramia
質問者

お礼

 お忙しい中わざわざ有難うございました。  スイッチのチャタリング防止についての知識に関するサイトで分かりやすいサイトがあれば教えてください。  デューティー比は、仕様に書かれているようにONとOFFの比率じゃないんですか。

その他の回答 (8)

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

>一体どう意味ですか?教えてください。 > PORTBbits.RB1=duty[x][y]の行は削除しました。 ん?残っていますけど。 コメントで修正点を書いたつもりですが、 //押したら押しただけカウントダウンします。 // SWが1->0と変化して初めてボタンを押したという認識をしてください。 // 押しただけの認識だと2ms周期だと20msで0以下になってしまいます。 // ん?そもそも比較じゃなくて代入文ですから常にif分はelseしか実行されませんよ。 とか // 0以下にならないようにガードをしましょう。 ってありますよね? ちゃんと読んでもらっていないみたいで悲しいです。 > それとプログラムをうつときに使っているMPLAB(統合開発環境)では、日本語でコメントできません。 ああ、別のエディタなら日本語で書けますが、確かにMPLAB自体ではかけませんね。私のコメントは単なる直してほしいポイントの指摘をしている分なので読んでほしいだけです。 それと、日本語でコメントかけなくてもローマ字とか手はあるので、なるべく書いてください。読む人への礼儀ですし、集団作業する場合には必須の作業です。

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

チャタリング処理は別として、こちらの#7のコメントがほとんど反映されていません。もう一度よく見直してみてください。その辺りが修正されたら、細かく見ますから。 こちらのコメントが意味不明なら聞いてください。

paramia
質問者

補足

>#7のコメントがほとんど反映されていません 一体どう意味ですか?教えてください。  PORTBbits.RB1=duty[x][y]の行は削除しました。  それとプログラムをうつときに使っているMPLAB(統合開発環境)では、日本語でコメントできません。  

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

このプログラムはコンパイル通りました? まずコンパイルエラーが無いか確認することが必要です。 #include <p30F2012.h> // 配列の数が違ったので修正と名前をつけて読みやすくしました。 #define DUTY_PATTERNS (11) //LED点滅パターン数 #define DUTY_BITS (10) //LED点滅ビットの数 void main(void) { int duty[DUTY_PATTERNS][DUTY_BITS]={ {0,0,0,0,0,0,0,0,0,0}, // {}がなかったので追加しました。 {1,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0}, {1,1,1,0,0,0,0,0,0,0}, {1,1,1,1,0,0,0,0,0,0}, {1,1,1,1,1,0,0,0,0,0}, {1,1,1,1,1,1,0,0,0,0}, {1,1,1,1,1,1,1,0,0,0}, {1,1,1,1,1,1,1,1,0,0}, {1,1,1,1,1,1,1,1,1,0}, {1,1,1,1,1,1,1,1,1,1} }; int i=0; // 緑のLED制御用。 int j=0; // 意図不明? int m=0; // 2msのウェイト用 int x=5; // デューティー比。 int y=0; // デューティー比配列のカウンタ。 // 入出力の初期化。 TRISBbits.TRISB0=0; TRISBbits.TRISB1=0; TRISBbits.TRISB8=1; TRISBbits.TRISB9=1; // 無限ループ while(1) { // 150回に一回緑LEDのON/OFF切り替え。300ms周期。 i++; if(i==150){ PORTBbits.RB0=~PORTBbits.RB0; i=0; } // デューティー比配列で赤LEDの点滅 PORTBbits.RB1=duty[x][y]; y++; #if 0 /* 意味不明。上でやったことと同じでは? */ if(duty[x][y]==1){ PORTBbits.RB1=1; } else if(duty[x][y]==0){ PORTBbits.RB1=0; } #endif // このif分は何もしませんが、なにをする予定でしたか? if(j>20){ ; } // チャタリング防止してませんし、押したら押しただけカウントダウンします。 // SWが1->0と変化して初めてボタンを押したという認識をしてください。 // 押しただけの認識だと2ms周期だと20msで0以下になってしまいます。 // ん?そもそも比較じゃなくて代入文ですから常にif分はelseしか実行されませんよ。 if( PORTBbits.RB9=0 ){ // 0以下にならないようにガードをしましょう。 x--; } else { // 入力ポートに値を書き込んでも意味はありません。無視されます。 PORTBbits.RB9=1; } // 上と同様です。 if(PORTBbits.RB8=0){ // DUTY_PATTERNS未満になるようにガードをしましょう。 x++; } // このjは常に0です。 j=0; // デューティー比配列の終端まできたら頭に戻す。 if(y==DUTY_BITS){ y=0; } // 2ms?のウェイトかな? for(m=0;m<3500;m++){ ; } } } 全体的に気をつけること。 ・コメントを付けましょう。 ・i,j,m,x,yなどの変数名より分かりやすい名前を付けましょう。

paramia
質問者

お礼

一応貴方のものを利用して書き直してみました。どうでしょうか。合っていますか。コンパイルは成功しました。 #include <p30F2012.h> // 配列の数が違ったので修正と名前をつけて読みやすくしました。 #define DUTY_PATTERNS (11) //LED点滅パターン数 #define DUTY_BITS (10) //LED点滅ビットの数 void main(void) { int duty[DUTY_PATTERNS][DUTY_BITS]={ {0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0}, {1,1,1,0,0,0,0,0,0,0}, {1,1,1,1,0,0,0,0,0,0}, {1,1,1,1,1,0,0,0,0,0}, {1,1,1,1,1,1,0,0,0,0}, {1,1,1,1,1,1,1,0,0,0}, {1,1,1,1,1,1,1,1,0,0}, {1,1,1,1,1,1,1,1,1,0}, {1,1,1,1,1,1,1,1,1,1} }; int i=0; // 緑のLED制御用。 int j=0; // while(1)からj=0;}までのループの回数 int m=0; // 2msのウェイト用 int x=5; // デューティー比。 int y=0; // デューティー比配列のカウンタ。 // 入出力の初期化。 TRISBbits.TRISB0=0; TRISBbits.TRISB1=0; TRISBbits.TRISB8=1; TRISBbits.TRISB9=1; // 無限ループ while(1) { // 150回に一回緑LEDのON/OFF切り替え。300ms周期。 i++; if(i==150){ PORTBbits.RB0=~PORTBbits.RB0; i=0; } // デューティー比配列で赤LEDの点滅 if(duty[x][y]==1){ PORTBbits.RB1=1; } else if(duty[x][y]==0){ PORTBbits.RB1=0; } j++; if(j>20){ ; } if( PORTBbits.RB9=0 ){ x--; } else { PORTBbits.RB9=1; } if(PORTBbits.RB8=0){ x++; } j=0; } // 2msのウェイト for(m=0;m<3500;m++){ ; } } }

paramia
質問者

補足

 昨日書いたプログラムはコンパイル成功しました。  今回の課題にはチャタリング防止は考えなくてよいといわれました。  また新しく変えたので見てください。 #include <p30f2012.h> void main(void) { TRISBbits.TRISB0=0; TRISBbits.TRISB1=0; TRISBbits.TRISB8=1; TRISBbits.TRISB9=1; int duty[11][10]={{0,0,0,0,0,0,0,0,0,0}, {1,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0}, {1,1,1,0,0,0,0,0,0,0}, {1,1,1,1,0,0,0,0,0,0}, {1,1,1,1,1,0,0,0,0,0}, {1,1,1,1,1,1,0,0,0,0}, {1,1,1,1,1,1,1,0,0,0}, {1,1,1,1,1,1,1,1,0,0}, {1,1,1,1,1,1,1,1,1,0}, {1,1,1,1,1,1,1,1,1,1} }; int i=0; int j=0; int m=0; int x=5; int y=1; while(1) { i++; if(i==150){ PORTBbits.RB0=~PORTBbits.RB0; i=0; } y++; if(y==9){ y=1; } PORTBbits.RB1=duty[x][y]; if(duty[x][y]==1){ PORTBbits.RB1=1; } else { PORTBbits.RB1=0; } j++; if(j>20){ if(x<=9){ if(PORTBbits.RB8=0){ x++; } } if(x>=1){ if(PORTBbits.RB9=0){ x--; } } j=0; } //2msのウェイトです。 for(m=0;m<3500;m++){ ; } } } また何かあったら教えてください。  

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

>スイッチのチャタリング防止についての知識に関するサイトで分かりやすいサイトがあれば教えてください。 これなんかどうですかね? http://www.picgames.org/modules/tinyd1/index.php?id=5 このサイトのPICは8bitPICでCコンパイラも違うので書き換えないと動かないと思いますが。 >デューティー比は、仕様に書かれているようにONとOFFの比率じゃないんですか。 正確には、一定時間内のON/OFFの比率ですね。1周期の時間が変化してはいけません。

paramia
質問者

お礼

失礼しました。問題点ではなく間違っている所でした。

paramia
質問者

補足

一応自分なりにプログラムを作成しました。 問題点があれば教えてください。 #include <p30F2012.h> void main(void) { TRISBbits.TRISB0=0; TRISBbits.TRISB1=0; TRISBbits.TRISB8=1; TRISBbits.TRISB9=1; int duty[10][9]={0,0,0,0,0,0,0,0,0,0, 1,0,0,0,0,0,0,0,0,0, 1,1,0,0,0,0,0,0,0,0, 1,1,1,0,0,0,0,0,0,0, 1,1,1,1,0,0,0,0,0,0, 1,1,1,1,1,0,0,0,0,0, 1,1,1,1,1,1,0,0,0,0, 1,1,1,1,1,1,1,0,0,0, 1,1,1,1,1,1,1,1,0,0, 1,1,1,1,1,1,1,1,1,0, 1,1,1,1,1,1,1,1,1,1}; int i=0; int j=0; int m=0; int x=5; int y=0; while(1) { i++; if(i==150){ PORTBbits.RB0=~PORTBbits.RB0; i=0; } PORTBbits.RB1=duty[x][y]; y++; if(duty[x][y]==1){ PORTBbits.RB1=1; } else if(duty[x][y]==0){ PORTBbits.RB1=0; } if(j>20){ ; } if(PORTBbits.RB9=0){ x--; } else{ PORTBbits.RB9=1; } if(PORTBbits.RB8=0){ x++; } j=0; if(y==9){ y=0; } for(m=0;m<3500;m++){ ; } } }

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

>出来ないと査定その他、仕事上で困ることがありますか?  解雇されるかもしれません。 そんな状況で放置していたんですか? そうすると、これからの仕事がマイコンの仕事になるんですね? 今のあなたの実力で、この課題は無理なのは間違いないです。 もう一度時間をもらって死ぬ気で勉強するか、自分の実力でできる仕事を希望するしか無いと思います。 そんな簡単に解雇されるって、派遣で実力を偽っていた時や入社時に自分の実力を偽って入社した場合だけですよ。

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

その他の矛盾ですか?他には無いです。 ちなみに出来上がっているプログラムは、P146を少し触っただけみたいですが、緑LEDの点滅周期は仕様をまったく満たしていません。 言語やマイコンの理解をしていないこともそうですが、期限ぎりぎりまで放置したおいたことが最大の問題だと思います。そもそもこの課題を受けたときに言語やマイコンを理解していないと報告したのでしょうか?それとも、すぐ出来ると思い込んでました? これが重要な仕事だと考えた場合、仕事を請ける上で自分の実力の把握は、いちばん重要な事で納期も実力から考えなければいけません。 お客さんのある仕事だったら、納期ぎりぎりで自分の実力では出来ませんと上司に泣き付くような状況です。そんな人に仕事を任せたいと思いますか? まぁ、そんなシビアな課題ではないと思いますが、仕事の忙しさは自分の実力を顧みず納期ぎりぎりまで放置しておいた言い訳にはなりません。実力不足で、忙しかったら最初に断るべき事なんです。 きびしく書きましたが、なにか学校の課題みたいな取り組み態度が気になったので書かせてもらいました。

paramia
質問者

補足

>デューティー比制御をするのに、「プログラム論理の最後でwaitルーチンをcallすることで、約20ms毎にタスクが動くようにする。」ようにしたらデューティー比制御なんて出来ません。 担当に確認したら20ではなく2でした。間違えてたみたいです。 また赤LED のON/OFFのデューティー比は10段階ではなく11段階だったみたいです。 >期限ぎりぎりまで放置したおいた これは一応研修課題のひとつで、担当者とも色々質問したりC言語の参考書で調べたりしました。この教えてGooというサイトは昨日初めて知りました。  上のプログラム設計の詳細を解くのにそれに関連するヒントまたはサイトってありませんか? 色々いってすみません。

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

仕事関係の課題なら素直に出来ないと報告すべきです。誰かにやってもらって出来たところで本人の実力でなければ意味がありません。 課題を出したほうも実力を見るためにやっているのではないでしょうか? 出来ないと査定その他、仕事上で困ることがありますか? 今回だけごまかしてもすぐに困る事になりませんか? アセンブラやC言語の知識が無い状態で、かつマイコンの知識も無い人間が2~3日で作れるほど簡単な問題ではありません。それに、この課題自体に大きな仕様の矛盾を持っています。そのことが分かっていない時点でデューティ比の意味もよく分かっていないのではと思われます。例えば10:0~0:10までの変化は10段階ではなく11段階ですし、デューティー比制御をするのに、「プログラム論理の最後でwaitルーチンをcallすることで、約20ms毎にタスクが動くようにする。」ようにしたらデューティー比制御なんて出来ません。

paramia
質問者

お礼

 わかりました。他にこの仕様に問題点があれば教えてください。 宜しくお願いします。

paramia
質問者

補足

>出来ないと査定その他、仕事上で困ることがありますか?  解雇されるかもしれません。

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

このは何かの宿題でしょうか? 問題の丸投げは禁止されていますので、自分のできたところまでを必ず書いてください。丸投げ認定されると削除されます。 つまり回答者に丸々プログラムを作ってもらうことは、ここでは出来ません。自分の作ったプログラムを掲載して問題点を指摘してもらうことはOKです。 私も問題の答えを丸々書くことは本人の為にならないので避けています。

paramia
質問者

補足

 すみません。何しろこのプログラムを明日中までに完成させなければならないのでついやってしまいました。  私ができたところといえば以下の通りです。 #include <p30F2012.h> void main(void) { unsigned i,j; TRISBbits.TRISB0=0; TRISBbits.TRISB1=0; PORTBbits.RB1 =1; TRISBbits.TRISB8=1; TRISBbits.TRISB9=1; while(1) { for (i=0; i<32; i=i+1) { for(j=0; j<65000; j=j+1){ ; } } PORTBbits.RB0=~PORTBbits.RB0; } } という風にテキストp146のリスト2のプログラムに手を加えた程度です。  私はdsPICのプログラムどころかC言語の知識もほとんどないので本当に困っています。具体的には「プログラムスタート時のデューティ比を5:5とする。黒スイッチ1回押すと、1段階減光させる。白スイッチ1回押すと、1段階明るくする。いずれも、デューティ比が0:10か10:0になったらそれ以上スイッチが押されても無視する。」のところをプログラム上どのように表せばいいか全然わかりません。  また緑LEDのところも合っているのかわかりません。 私はどうすればいいんでしょうか?他の仕事の忙しさで参考書が買えません。

関連するQ&A