dポイントプレゼントキャンペーン実施中!

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

タイトルにあります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){}
}
以上です。

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が見つからない時は、教えて!gooで質問しましょう!