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

再三お世話になります。大概の問題もこちらで、
解決できて来ましたが、流石に今回はそうも行かないのではと
覚悟しております。

タイトルにありますPICと言えば、CCS社のコンパイラーが
王道と聞いておりますが、素人の浅はかで、
マイナーな方を選択した為、
お手上げ状態に陥っています。

質問の概要はサーボモータの制御信号生成が最終目的です。
まずその基本となる、前段部分として、一定巾周期のパルス毎に、
制御パルスを送り、希望通りの信号をLEDの点滅で確認出来るかと
したものです。内容は(PIC16F887,8MHZ内部クロック使用、
1:8プリスケール、TIMER1とのコンペアマッチ割込みと、
TIMER0の割込みの2つのタイマー使用)TIMER1からは、
割り込み発生後、1秒毎にPORTB-1を点灯する信号を出し、
もう一方TIMER0から、0.5秒ごとにPORTB-1を消灯させる。
と言うものです。

後で気づきましたが、この時間設定では正確なものなら、
まず1秒後に点灯、次の1秒までの間に、もう一方で
0.5秒毎に消灯信号が出ているため、1秒後には
お互い打ち消し合って本来ずっと消灯する
結果になるはずですが、実験では、0.1sec~0.5sec間隔の
点滅が、ある周期ごとに繰り返されます。

両方同時に割り込み処理が働き、命令サイクルのずれから、
点滅現象になるのではと推測します。
希望として、1秒の割込みの後に、
0.5秒の割込みが来るようにしたいのですが、
思うようになりません。

そこで、そのソースコードを記述しましたので
稀少mikroCをご使用の方に
検証とご教示が叶えられれば、最高に幸せです。
何卒宜しくお願いいたします。
            記
unsigned count,count1 = 0;
void interrupt()
{
//timer1 interrupt
if(PIR1.CCP1IF == F)
{
PIR1.CCP1IF = 0;
count++;
if(count == 5)
{
PORTB.F1 = 1;
count = 0;
}
}
//timer0 interrupt
if(INTCON.TMR0IF == 1)
{
INTCON.TMR0IF = 0;
TMR0 = 216;
count1++;
if(count1 == 100)
{
PORTB.F1 = 0;
count1 = 0;
}
}
}
void main()
{
ANSEL = 0;
ANSELH = 0;
TRISB = 0;
PORTB = 0;
PIE1.CCP1IE = 1;
PIR1.CCP1IF = 0;
CCP1CON = 0x0B;
CCPR1L = 0x50;
CCPR1H = 0xC3;
T1CON = 0x31;
OPTION_REG = 0x87;
TMR0 = 216;
INTCON = 0xA0;
INTCON.PEIE = 1;
INTCON.GIE = 1;
while(1){}
}
以上です。

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

A 回答 (2件)

ANo.1です。

趣旨は分かりました。PICは詳しくないので具体的なコードは書けませんが、基本的なやり方を答えます。

やり方は2つです。
・タイマー1つで行う方法
タイマを0.5msインターバルで使って、40回(20ms)に一回ON指示、その2回(1ms)、3回(1.5ms)あるいは4回(2ms)後にOFF指示をします。
タイマをインターバルにするには割込みハンドラの最初で割り込みを再設定します。なお、設定の関係で正確な0.5msが出せなくて20ms周期の精度が悪いということなら、再設定ごとにカウントを補正して対応します。
例えば4.9msか5.3msしか設定できないなら、再設定ごとに5.3, 4.9, 4.9, 4.9のシーケンスで設定します。
注意は、一回のタイマハンドラ処理が0.5msを超えるとこの方法では破綻する点です。

・タイマー2つで行う方法
タイマ0は20msインターバルで使い、タイマ1は1ms、1.5msあるいは2msのアラームで使います。
初めにタイマ0を設定・起動し、ハンドラではタイマ0アップならタイマ0の再設定(インターバル利用の為)、ON指示をしてタイマ1を設定・起動します。タイマ1アップなら(タイマ1は再設定せずに)OFF指示だけします。

サーボモータの代わりにLEDを使って確認するにしても、基本的な制御を同じにしないと検証にならないと思います。1sと0.5sじゃなく上記のタイミングのままでやってみた方が良いでしょう。パルスは見えなくても1ms、1.5ms、2msで明るさが変わることで分かると思います。
    • good
    • 0

本当にしたいことの趣旨が分からないので本当の解決になるか分かりませんが、2つの周期が連動する必要があるなら2つのタイマーを使うのではなく1つのタイマーで駆動することで解決すると思います。


質問の例では0.5秒ごとタイマー割込みを設定して、1秒ごとの処理は2回に一回、0.5秒ごとの処理は毎回実行すれば良いでしょう。

この回答への補足

早速、お目に留めていただき、回答ありがとうごさいます。
本題の趣旨が伝わりにくかった事の不手際、誠に申し訳ございません。
このソースコードは質問中にもありますが、サーボモータを制御
するため、異なる2つのパルス出力をLEDで目視確認しようとした
ものです。一般的にサーボモータの回転角を変えるには、
メーカー製品によっても若干異なりますが、
規則正しい20msec周期毎に1msec・1.5msec・2msecの
パルスを送ることで、それぞれのパルスに応じて、位置角度が
右、中央、左と変化することは、一般的知れてます。実験では、
実際に20msecに対して1msecや2msecのパルス信号を目視確認するには
困難です。そこでタイマー割り込みによる動作確認が目視出来る様に
設問中では、20msecの部分を1秒に充当させ、1msec~2msecに該当する
位置パルスとして0.5秒に置き換えて現したものです。
正確なパルスを得、それぞれが干渉し合わない様に
する為にも2つのタイマー使用が理想かと思われます。
ですが、2つのタイマー割り込みを別々にずらして使用する為の
コード記述が分かっておりません! 
また、実験成果を見るためにも、1秒と0.5秒の時間組合せも
マズイかとも、考えているところでありますが、
要するに、1秒のタイマー割込み終了後、0.5秒のタイマー割込みを
発生させ、その結果を1つのPORTに出力するコード構成が知り得たくて
ご教示願い出た次第でございます。

補足日時:2010/02/04 22:43
    • good
    • 0

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

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

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

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

QPICによるPWM出力の周期について

PIC(16f873)を用いて、モータをPWM制御しようと思っています。
そこでいくつか質問なんですが、PWMの周期は下記の式で与えられるとありますが、

PWM周期 = (PR2の値+1)x4x発振器周期xタイマー2のプリスケーラ値

この周期は、自分で適当に決めていいのでしょうか?それともモータによって決まっているんでしょうか?
 そもそもPWMは、デューティ比で出力が変わると思うんですが、周期が違うとどのような違いが出るのでしょうか?周波数が高くなると細かい制御が出来るって感じでしょうか?

初歩的な質問ですが、よろしくお願いします。m(_ _)m

Aベストアンサー

http://homepage1.nifty.com/rikiya/software/106pwm1.htm

知りたことは殆ど出てますますね

QPICでパルス数をカウントし、カウント数に応じで、ある操作をする

PICにファンクションジェネレータからパルス(数100ms程度の幅)を0.2~1Hzで入力して、たとえば10回のパルスが入ってきたら、10回目のパルスの後、数ms後にパルスを出力するといった事をしたいのですが、わかりません。

PIC初心者です。よろしくお願いします。

Aベストアンサー

PICは(Peripheral Interface Controller)で良いですね。
外部入力を判断するには(1)専用入力端子を使うか、それがなければ(2)割り込みが使える端子を使うか(3)通常の入力端子をポーリング(ソフトのタイミングで見る)かのどれかを使うことになると思います。
(1)はパルスの入力やパルス幅、その他の機能が考えられますがIC自体が高価にもなります。(2)はレベルの割り込みと、エッジの割り込みがあり、(2)(3)共にノイズ等による無効パルスや有効パルス中のエッジ発生や反転を予測して、有効/無効パルスの判定(反転を認識してから一定の時間で再認識)をしないといけないでしょう。
後はダウンカウントかアップカウントの10回カウンタでゼロまたは一致にてパルスを出力すればよいと思います。タイミングを計るのは内部タイマを使うか、あまり勧めませんがソフトのループ間隔で時間を決めるソフトカウンタという方法もあります。

QPICでのプログラムによるチャタリング対策

こんにちは。
非常に基本的かも知れませんが、
プログラムによるチャタリング対策の
仕方がわかりません。

スイッチONを割り込みでうけつけてから、
0.5~1秒待って、まだ、ONであれば、
実行する、という方式でやっています。
短い秒は、カットされていますが、長押し
があると、おかしな動作になってしまいます。

どういう方式をとるのが一般でしょうか。
特に言語はといません。方式、考え方が
知りたいです。
(ハードによる防止は、
まったく考えていませんので、
結構です)。

以下、参考までに
自分のプログラムです(PA使用)。

warikomi
call cwait //0.5-1s待ち
sb rb.7 //もう一度チェック
goto warikominot //押されてなければ、addしない。
add intervala,#01h
warikominot
clrb rbif
retfie

お願いします。

Aベストアンサー

普通「チャタリング」っていうとせいぜい数十ms くらいを想定するものだと思うんだけど....
0.5s~1s って, どんなチャタ?
ついでにいうと (聞いても答えられないような気はしますが)「長押しするとおかしな動作をする」といわれても, 「押し続ける時間」「期待する動作」「実際の動作」を示さないと解決できないかもしれませんよ.


人気Q&Aランキング