人に聞けない痔の悩み、これでスッキリ >>

PIC12F629をC言語でプログラミングしています。
GP2ピンをデジタル入力としてスイッチを接続しGP4をデジタル出力
としてLEDを接続し、スイッチを押すたびにLEDが点灯、消灯を繰り返す
ようにプログラミングしてみました。

ところがデジタル入力のピンをGP0,GP1に変更しピンにスイッチを
接続し入力しても同じように動作しません。回路に電源をいれた瞬間
LEDが点灯しスイッチを入力しても点灯したままです。

GP0,1をGP2と同様にデジタル入力として使いたいのですが、単にピンの
番号をプログラム中で変更するだけではダメなのでしょうか?
ご教授おねがいします。

このQ&Aに関連する最新のQ&A

A 回答 (1件)

はじめまして,


私も趣味でPICの魅力にはまっている一人です.
回路図もソースもわかりませんので,想像の範囲でお答えしますと,PIC12F629に内蔵されているコンパレータの初期化が行われていないのではないでしょうか.手持ちにあったPIC12F629/635のデータシートではP35~P37に説明があります.(先月マイクロチップ社のHPよりダウンロードしたものです)
P35に記載されている"6.0 COMPARATOR MODULE"内蔵コンパレータの制御はCMCON(19H)レジスタで行います.このレジスタのデフォルト値は00000000Bですので,CM2,CM1,CM0ともゼロクリアされています.CM0:CM2の意味はP37にありますが,オールゼロの意味は”不使用”ではなく,コンパレータを(使えるように)初期状態にセットします,という意味で,各種ピンは,GP0,GP1をアナログに,GP2をデジタル入出力にセットします.質問者様の文脈から察するに,GP2は動いたのにGP0と1の(ディジタルIOとしての)I/O動作が期待に反したことに近いと思います.
ですので,コンパレータ機能を使わずにGP0,1,2をディジタル入出力で使う場合には,このCMCONに7H(CM2:CM1:CM0=1:1:1)を書き込まなければなりません.一般的には,スタートアップルーチンでTRISIOレジスタにGPIOをセットする手前にCMCONをconfigureします.

最後にアドバイスになるか否かわかりませんが,データシートや仕様書が間違っていることは本当に稀です.汎用ディジタル入出力として使える,と書いてあれば必ず使えます.ただし,ことPICの場合は小型で多機能である反面,ピンの共用がかなり激しく,思わぬところで勘違いを起こします.偉そうに言っていますが,私も実は毎回はまっています.定番のPIC16F84で作成したソフトをPIC16F88に持ってこようとした時はANSEL(アナログ入力の仕様設定)にやられました.またつい最近,非常に単機能なPIC12F509を使い始める時にも,GP2がTMR0のクロック入力とかぶっていて,OPTIONレジスタのデフォルト値がTMR0を優先させていた為にやはりGPIOが動かない,という現象にはまりました.
その時あまりにも悔しかったので備忘録としてブログに挙げてあります.お暇だったら見てください.
http://fp-masamichi.cocolog-nifty.com/pic/2009/0 …
私も異なるPICを使う度にはまっている状態ですが,いずれにしても最後はデータシート通りにちゃんと動きます.PICを信じてやってください.

参考URL:http://fp-masamichi.cocolog-nifty.com/pic/2009/0 …
    • good
    • 0
この回答へのお礼

ご回答いただきありがとうございます。
ご指摘にありましたCMCOMレジスタにデータをセットしてみました。

CMCOM=0x07;
この1文をIOピンの初期設定を行っているサブルーチン書き込んだ
だけでGP0,1ピンをデジタル入力として使えるようになりました。

プログラムのソースコード、回路図等を掲載したかったのですが、
参考書のサンプルソースなので掲載してはよろしくないのでは
と思い掲載しませんでした。

参考書 オーム社 C言語ではじめるPICマイコン
http://ssl.ohmsha.co.jp/cgi-bin/menu.cgi?ISBN=4- …
この本のP84,85に載っているプログラムです。
(よくみるとこの本にCMCOMレジスタの説明も載ってましたね^^;)

ブログも今度ゆっくり拝見させていただきます。
今回はどうもありがとうございました。

お礼日時:2009/07/21 22:19

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

QPIC12F629 3分 時間延長ルーチン 作り方 考え方

ラーメン3分タイマーを作ってます。
3分たつと、LED点灯、ブザーが鳴るといった感じです。
時間延長ルーチンについて、3分の時間延長ルーチンの作り方教えて。
PIC初心者です。
解説もよろしくお願いいたします。

Aベストアンサー

時計とかストップウォッチ、PICで検索すると、ソースまで公開している人が見つかると思います。
基本的には、タイマ割り込みを長くして数えていくという作り方がスタンダードだと思います。
12F629の仕様を呼んでいないのでわかりませんので、簡単な例で。
4.194304MHzの発振器を使うとします。
8bitのカウンタが一周すると256回のカウントです。そこで割り込みかけます。
で、カウンタの割り込みをまた8bitのカウンタで数えて、一周したら割り込み。これを更にもう一回繰り返して一周させると4秒になります。
これを45回数えれば3分です。
単純に書くとこうなりますが、実際は割り込み処理のクロック消費数(PICは普通、1命令2クロックですよね)などを考えて調整します。
これでわかるように、時計用などという名目で売っている発振器を使うと割り切れるのでプログラムが楽になります。
精度がそこまで要らないのなら、nopを駆使してウェイト調整すればそこそこ使えます。

と書くと難しそうですが、ひとつずつクリアしていってください。
まずはタイマ割り込みの使い方を勉強して、割り込みがかかったらLED点けてみるとか。
その次は割り込み回数を数えて・・・という風にやっていけば、いつかできるようになります。

時計とかストップウォッチ、PICで検索すると、ソースまで公開している人が見つかると思います。
基本的には、タイマ割り込みを長くして数えていくという作り方がスタンダードだと思います。
12F629の仕様を呼んでいないのでわかりませんので、簡単な例で。
4.194304MHzの発振器を使うとします。
8bitのカウンタが一周すると256回のカウントです。そこで割り込みかけます。
で、カウンタの割り込みをまた8bitのカウンタで数えて、一周したら割り込み。これを更にもう一回繰り返して一周させると4秒になります...続きを読む

QPIC12F675 キャリブレーションデータ

PICの勉強を始めて間もない者です。
MPLAB IDE ver8.84にてHI-TECH Cにてプログラムを組んで勉強をしています。
ライターにはPICkit3を使用しています。

12F675を使用しているのですが、何回か書込みをしていたところエラーが発生しました。
(おそらくソケットにきちんと12F675がセットされていなかった?)
その後、再度書込みをしようとしたところ、
  The target has invalid calibration data (3fff).
というメッセージが出ました。

確認してみたところ、データの最後に入っていたクロックのキャリブレーションデータが
消えていることが原因だとわかりました。
幸いデータの値は記録しておいたので、この値を再度書き込みたいと思うのですが
方法がわかりません。

やってみたこと
 ViewのProgram Memoryを開く。
 3FFの所のデータ(3fff)を選び、右クリックのFill Memoryをクリック。
 Dataの値を書き直し、Writeをクリック。

その後Readしてみると値が3fffに戻ってしまいます。

データの修正/書込み方法を教えて下さい。
よろしくお願いします。

PICの勉強を始めて間もない者です。
MPLAB IDE ver8.84にてHI-TECH Cにてプログラムを組んで勉強をしています。
ライターにはPICkit3を使用しています。

12F675を使用しているのですが、何回か書込みをしていたところエラーが発生しました。
(おそらくソケットにきちんと12F675がセットされていなかった?)
その後、再度書込みをしようとしたところ、
  The target has invalid calibration data (3fff).
というメッセージが出ました。

確認してみたところ、データの最後に入っていたクロックのキャリブレ...続きを読む

Aベストアンサー

PICKIT2では、Tools / OSCCAL / SetManually の項目があります。

参考URL:http://www.ne.jp/asahi/air/variable/picmel/other_info/index.htm#note2

Q抵抗の1/2W、1/4Wの違いについて

 クルマのLED工作で抵抗を使おうと思っています。

 その時 抵抗には、〇Ω以外にも
1/2W、1/4W等の規格があるのですが、よくわかりません
調べてみたところ<電力消費>という
キーワードが分かりましたが他がサッパリ・・・・

・例えば (+)1/4W 430Ω LED (-)という場合
抵抗を 1/2W 430Ωでは、ダメなのですよね?
 1/2Wの場合 〇Ωになるのでしょうか?

・また、1/2W、1/4Wは、単純に大きさ(太さ、長さ)で
判別がつくのでしょうか?

Aベストアンサー

抵抗が焼ききれずに使用できる or 性能を保証できる電力です。

例えば1kΩの抵抗に24Vの電圧を与えると、抵抗はP=V*I=(V^2)/R=0.576Wの電力を熱として消費します。
1/2W抵抗は0.5Wまでしか持たないので1W抵抗を使用することになります。
一瞬でも定格を越えるとダメなので、通常は余裕を持って考えます。

>・例えば (+)1/4W 430Ω LED (-)という場合
>抵抗を 1/2W 430Ωでは、ダメなのですよね?

定格を満たしているため問題ありません。

>・また、1/2W、1/4Wは、単純に大きさ(太さ、長さ)で
>判別がつくのでしょうか?

大抵の場合大きさで分かります。長さも太さも違います。
同一シリーズであれば確実にワット数の大きいほうがサイズがでかいです。
(1/2W>1/4W)

http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1314083328

Qpicタイマ0割り込みについて

タイマ0割り込みについて教えて下さい。
解説書などに、割り込みルーチンの最初の部分で

(1)割り込みフラグ(TMR0IF)を消す
(2)TMR0を再設定する

と書かれていますが、なぜ(2)を割り込みルーチンの最初で行うのでしょう?
これでは、
・1秒ごとに割り込みを発生させたい
・割り込みルーチンの作業時間は0.5秒
だとすると、結果的に割り込み発生は0.5秒ごとになってしまいます。

TMR0再設定は割り込みを抜ける時(retfie の直前)に行えば、ほぼ希望通りの間隔で、割り込みを発生させられると思うのですが、それはルール違反なのでしょうか?

Aベストアンサー

N0.2です。
普通の処理だったら問題無いのですが、
たとえば、割り込みが発生してもすぐに
割り込みルーチンに入れない様な場合、
気を付けないと次の割り込みが発生してしまいます。
で、マニュアルでは割り込み原因となる
TMR0を再設定するように指示をしているのですが、
たしかに割り込み後に一定時間間隔でまた割り込みたい
場合には、抜ける前にまた再設定するしかありません。

ただ、通常の場合、一定時間の割り込みというのは
割り込みそのものを一定時間毎に発生させたい筈
なんです。
たとえば、割り込みは10mSおき、処理は1mSだとすると
スタート(0mS)から数えて
10mS 割り込み発生 TMR0再設定
11mS 割り込み処理終了
20mS 割り込み発生 TMR0再設定
21mS 割り込み処理終了
30mS 割り込み発生 TMR0再設定
と言うぐらいに、きれいに
10mSおきに割り込みが発生します。
しかも、割り込み処理が長くなっても短くなっても
間隔は変わりません。

QC言語でプログラミングし、PICマイコンでLEDを制御する

現在PICを使ってLEDを制御する事を勉強しています。
3つのLEDを3秒間隔で点灯させ、それを無限に繰り返すプログラムを考えてみました。LEDは一つのポートに一つのLEDを割り振るのではなく、ICを使って制御しています。

これを発展させ、待ち時間の3秒間にRA2ポートに入力があるとLEDの点灯をその場所で停止させ、もう一度RA2ポートに入力するとループが再開するといった内容にしようと考えていますが、調べてもどうすればいいのか分かりません、分かる方は教えて頂けないでしょうか

# include <16f84a.h>
# fuses HS, NOWDT, NOPROTECT
# use delay(clock=20000000)
int flag, sec, count;

main()//main関数の開始宣言
{
set_tris_a(0x10);
set_tris_b(0x10);
#use fast_io(a)//port_aの高速処理を行う設定
#use fast_io(b)//port_bの高速処理を行う設定


while(1){//無限ループのwhile文の宣言

output_low(PIN_A0);//RA0の出力
output_low(PIN_B5);//RB5の出力
output_low(PIN_B6);//RB6の出力
output_low(PIN_B7);//RB7の出力
//LED1が点灯
delay_ms( 3000 ) ;//3秒待つ

  output_high(PIN_A0);//RA0の出力
output_low(PIN_B5);//RB5の出力
output_low(PIN_B6);//RB6の出力
output_low(PIN_B7);//RB7の出力
//LED2が点灯
delat_ms( 3000 ) ;//3秒待つ

       output_low(PIN_A0);//RA0の出力
output_high(PIN_B5);//RB5の出力
output_low(PIN_B6);//RB6の出力
output_low(PIN_B7);//RB7の出力
//LED3が点灯
delay_ms( 3000 ) ;//3秒待つ
}

現在PICを使ってLEDを制御する事を勉強しています。
3つのLEDを3秒間隔で点灯させ、それを無限に繰り返すプログラムを考えてみました。LEDは一つのポートに一つのLEDを割り振るのではなく、ICを使って制御しています。

これを発展させ、待ち時間の3秒間にRA2ポートに入力があるとLEDの点灯をその場所で停止させ、もう一度RA2ポートに入力するとループが再開するといった内容にしようと考えていますが、調べてもどうすればいいのか分かりません、分かる方は教えて頂けないでしょうか

# include <16f84a.h>
...続きを読む

Aベストアンサー

★回答ではないが気になったので。
>main() //main関数の開始宣言
 ↑
 main関数の定義です。開始の宣言ではないです。記述の開始かな。
>while(1){ //無限ループのwhile文の宣言
 ↑
 while文の宣言という表現はおかしいね。
 ちなみに無限ループなら for( ; ; ){ … } でも出来ます。

本題:
・LED の点灯と停止の方法
 RA2ポートの入力状態のチェック方法
 の2つを教えて下さい。
・考え方としては delay_ms() 関数の部分にRA2ポートの入力状態をチェックしてその場で
 停止したり、再開させたりすれば良いと思います。つまり、delay_ms() 関数で 3 秒間
 のループを作ってそのループ内でRA2ポートの入力状態から停止、再開を出来るように
 記述するわけです。
 
 while (1){
  // LED1の点灯
  for ( int i = 0 ; i < 3000 ; ){
   /*
   RA2ポートの入力状態を読み出す
   例えば flag 変数に停止なら 0、再開なら 1 を入れるとする
   */
   if ( flag ){ // 再開の時に処理
    i++; // ここでインクリメント
   }
   delat_ms( 1 ); // 1ms待つ
  }
  // LED2の点灯
  for ( int i = 0 ; i < 3000 ; ){
     :
   上と同じ処理
     :
  }
  // LED3の点灯
  for ( int i = 0 ; i < 3000 ; ){
     :
   上と同じ処理
     :
  }
 }

最後に:
・for 文のループは関数にして3箇所に記述したほうが便利です。
・以上。

★回答ではないが気になったので。
>main() //main関数の開始宣言
 ↑
 main関数の定義です。開始の宣言ではないです。記述の開始かな。
>while(1){ //無限ループのwhile文の宣言
 ↑
 while文の宣言という表現はおかしいね。
 ちなみに無限ループなら for( ; ; ){ … } でも出来ます。

本題:
・LED の点灯と停止の方法
 RA2ポートの入力状態のチェック方法
 の2つを教えて下さい。
・考え方としては delay_ms() 関数の部分にRA2ポートの入力状態をチェックしてその場で
 停止したり、再開...続きを読む

QPICで内部タイマーを使わずカウントダウンする方法

こんにちは。
今回、PICのプログラムをアセンブラで組むことになりました。

その中で「100ミリ秒間、あるポートからの入力を監視する」という部分があり、
これを内部タイマーなどは使わずに実装するとします。

自分なりには、
PICのクロック数とループ内のサイクル数で
何回ループを回せばよいのかを予め計算しておいて
その回数だけループを回せばよいのかな?
と考えました。。。

しかしループ内のサイクルがせいぜい数μSですので、
100mSecとなると10万回単位でループを回さなければなりません。

しかしPICでは変数が8Bitしか無いので255までしかカウントできないと思うのですが、
こういう大きい数字のカウントをしたい場合、どうしたら良いのでしょうか?
宜しくお願いします。

Aベストアンサー

他の回答者の回答を見てると、最近はアセンブラ等でソフトを組む人は居ないんだなぁ。と思ってしまいますね。

>「100ミリ秒間、あるポートからの入力を監視する」

とどまっているんじゃなくて、監視し続けなければならないのでしょう。
重い処理なんてはさんだら、性能が落ちちゃいますし、見落としますからね。


ポートの入力は、割り込み信号は上がるのでしょうか?それとも、ポーリングを掛けて見続けていなければならないのでしょうか?
これで作り方は変わります。


通常、こういうプログラムの作り方は、一定の処理をダイナミックループで回していて、その中で、各処理を行っていくのが普通です。

なので、ダイナミックループの中にある、サブルーチンの平均所要時間を割り出してやると、ダイナミックループ1回にかかる時間が判ります。
このダイナミックループの中に、カウンタールーチンを作っておいて、何回回ったかを記録してその回数で、時間の経過を測定します。

指定時間内だけポートをチェックするのであれば、そのダイナミックループの中にポートチェックを入れておいて、カウンタールーチンで積算されている内容で、ポートチェックのルーチンに入るのかはいらないのかをすればよいだけです。

割り込み処理があるのなら、カウンタールーチンを、ダイナミックループに入れる必要は無く、割り込み処理の方に入れてやればよいだけです。
当然カウンタールーチンで、割り込みを開放、停止すればそもそもチェックに行く必要もなくなるわけです。

8ビットしかないからと言うのは、他の人も書かれて居る様に、単純に増やせばよいだけの話です。
カウンタ用の1バイトがいっぱいになってたら上位桁用の1バイトにインクリメントしてあげれば、1ビットのカウンタになるでしょう?
そんなに難しい話ではないと思います。

nopは、コンパイラによっては、削除されてしまう物もあります。
その辺は仕様書を読まないと判りませんけどね。
nopコードとして入れてくれる物もあるのですけどね。


タイマーなんて持っていないCPUを使う時はこんな方法は良く使って居ましたね。
途中に思い処理が分岐で入ると、そこを通ったか通らなかったかで、タイマーのカウンタの上げ方も変えなければならなかったですからね。

カウンタが足りないだけなら、上の様に増やせばよいだけの話です。

他の回答者の回答を見てると、最近はアセンブラ等でソフトを組む人は居ないんだなぁ。と思ってしまいますね。

>「100ミリ秒間、あるポートからの入力を監視する」

とどまっているんじゃなくて、監視し続けなければならないのでしょう。
重い処理なんてはさんだら、性能が落ちちゃいますし、見落としますからね。


ポートの入力は、割り込み信号は上がるのでしょうか?それとも、ポーリングを掛けて見続けていなければならないのでしょうか?
これで作り方は変わります。


通常、こういうプログラムの作り方は...続きを読む

QPIC12F683でLEDをスイッチで点滅させる

PIC12F683でLEDをスイッチで点滅させる
電源から3番ピンの間に10KΩの抵抗を入れ、3番ピンからグランドの間にタクトスイッチをつなげ

5番ピンからFETでLEDをドライブさせる回路を組みました。
開発環境は、mikroC PRO for PICです。
いろんなサイトを見ながらコードを書きましたが動いてくれません。
どなたかご教示お願いします。
PIC触るの初めてです。

void main() {
TRISIO = 0b00100000; //GP4を1:入力に、他を0:出力設定
OSCCON = 0b01110000; // 8MHz internal clock
ANSEL = 0b00000000; //GP0~5をデジタル利用に設定
OPTION_REG.NOT_GPPU = 0; //内部プルアップ利用に設定
WPU = 0b00100000; //GP2を内部プルアップ

GPIO = 0b00000000; //GPIOの中身をきれいにする
CMCON0 = 0b00000111; //コンパレータを使わない

do {
if(Button(&GPIO, 4, 1, 0)) { //スイッチONの場合
GPIO.F4 = 1; //LED ON
} else { //スイッチOFFの場合
GPIO.F4 = 0; //LED OFF
}
}while(1);
}

PIC12F683でLEDをスイッチで点滅させる
電源から3番ピンの間に10KΩの抵抗を入れ、3番ピンからグランドの間にタクトスイッチをつなげ

5番ピンからFETでLEDをドライブさせる回路を組みました。
開発環境は、mikroC PRO for PICです。
いろんなサイトを見ながらコードを書きましたが動いてくれません。
どなたかご教示お願いします。
PIC触るの初めてです。

void main() {
TRISIO = 0b00100000; //GP4を1:入力に、他を0:出力設定
OSCCON = 0b01110000; // 8MHz internal clock
ANSEL = 0b00000000; //G...続きを読む

Aベストアンサー

3番ピン(GP4)が入力で、Pull-upがONですね。だったら、
TRISIOの1にするビットが上にずれていませんか? bit4のはずです。
WPUも同様。
これらを設定の際にバンク切換をちゃんと指定していますか?
PICのメモリーやI/Oのアドレスは7ビットですね。これを超えるアドレスに対してはバンク切換で対応します。バンク指定はSTATUSレジスタ(アドレスは03h)のbit5です(ビット名はRP0)。これを1にしておくとバンク1が選択され、0ではバンク0が選択されます。なおSTATUSレジスタは現在指定されているバンク値と無関係にアクセスできます。
お使いの開発ツール(言語処理)によってはバンクは指定しなくても自動的に命令が付加されるものもあります。

もうひとつ気になったのがクロック発振の指定。OSCCONだけでなくCONFIGレジスタへの指定が必要です。
CONFIGレジスタはハード的な動作指定になるのでプログラムとして書くのではなくこのレジスタ自体もSFR(I/Oやメモリー)の並びにありません。開発ツールによって表記の仕方が違うと思うのでツールの説明書を見てください。内部発振、クロック出力なし に指定します。
なおCONFIGレジスタについてはPIC12F683 Data Sheet の84ページにあります(マイクロチップからDLできます)。

私も経験がありますが最初に動くまでが大変。でもちょっとでも動いたら後は楽チンです。頑張って!!

3番ピン(GP4)が入力で、Pull-upがONですね。だったら、
TRISIOの1にするビットが上にずれていませんか? bit4のはずです。
WPUも同様。
これらを設定の際にバンク切換をちゃんと指定していますか?
PICのメモリーやI/Oのアドレスは7ビットですね。これを超えるアドレスに対してはバンク切換で対応します。バンク指定はSTATUSレジスタ(アドレスは03h)のbit5です(ビット名はRP0)。これを1にしておくとバンク1が選択され、0ではバンク0が選択されます。なおSTATUSレジスタは現在指定されているバンク値と無関係にア...続きを読む


人気Q&Aランキング