• ベストアンサー

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

タイマ0割り込みについて教えて下さい。 解説書などに、割り込みルーチンの最初の部分で (1)割り込みフラグ(TMR0IF)を消す (2)TMR0を再設定する と書かれていますが、なぜ(2)を割り込みルーチンの最初で行うのでしょう? これでは、 ・1秒ごとに割り込みを発生させたい ・割り込みルーチンの作業時間は0.5秒 だとすると、結果的に割り込み発生は0.5秒ごとになってしまいます。 TMR0再設定は割り込みを抜ける時(retfie の直前)に行えば、ほぼ希望通りの間隔で、割り込みを発生させられると思うのですが、それはルール違反なのでしょうか?

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

  • ベストアンサー
  • tnt
  • ベストアンサー率40% (1358/3355)
回答No.3

N0.2です。 普通の処理だったら問題無いのですが、 たとえば、割り込みが発生してもすぐに 割り込みルーチンに入れない様な場合、 気を付けないと次の割り込みが発生してしまいます。 で、マニュアルでは割り込み原因となる TMR0を再設定するように指示をしているのですが、 たしかに割り込み後に一定時間間隔でまた割り込みたい 場合には、抜ける前にまた再設定するしかありません。 ただ、通常の場合、一定時間の割り込みというのは 割り込みそのものを一定時間毎に発生させたい筈 なんです。 たとえば、割り込みは10mSおき、処理は1mSだとすると スタート(0mS)から数えて 10mS 割り込み発生 TMR0再設定 11mS 割り込み処理終了 20mS 割り込み発生 TMR0再設定 21mS 割り込み処理終了 30mS 割り込み発生 TMR0再設定 と言うぐらいに、きれいに 10mSおきに割り込みが発生します。 しかも、割り込み処理が長くなっても短くなっても 間隔は変わりません。

bota1984
質問者

お礼

>たしかに割り込み後に一定時間間隔でまた割り込みたい >場合には、抜ける前にまた再設定するしかありません。 >ただ、通常の場合、一定時間の割り込みというのは >割り込みそのものを一定時間毎に発生させたい筈 >なんです。 この辺、わかりました。 定期的な割り込み時間の中で、割り込み処理を行うという考え方をすればいいんですね! おつき合い下さり、ありがとうございました

その他の回答 (2)

  • tnt
  • ベストアンサー率40% (1358/3355)
回答No.2

ここでアセンブラの質問をするとは大胆な! でも、お答えします。 TMR0はオーバーフローが起こると割り込むように なっています。 すぐにクリアしてあげないとオーバーフローが 続いてしまいます。 割り込みフラグが立っている間は大丈夫ですが 落とした瞬間にまたフラグが立ってしまうのです。 なお、16C84,16F84には、公開されたバグがあり 割り込みフラグクリア中に割り込みが発生すると RETFIE命令実行時に再度割り込んでしまうという 問題もあります。 TMR0はオーバーフローで動くタイマーですから RETFIE命令の手前で再度クリアしてやるという 手は有効です。

bota1984
質問者

お礼

ありがとうございます。 >ここでアセンブラの質問をするとは大胆な! ありゃ、場所違いましたか?(;・∀・) 割り込み先の先頭で、割り込みフラグをクリアするのは理解できました。 で、割り込み周期時間の再設定ですが、再設定すればその時点からタイマは動き始めるんですよね? ということは、割り込みを抜ける時に再設定した方がわかりやすいと思うのです。例えば10msごとに割り込みさせたいのなら、10msの数値を設定すればいいだけですから。 でも、先頭で再設定する場合は、 希望する割り込み周期時間+割り込み処理にかかる時間 の数値をセットしないといけないことになると思うのですが…。 割り込み周期時間を厳密にしようと考えている訳ではないのです。勉強始めたばかりなので、参考書などを読み進めるごとに、子供のように「なんで?」「どうして?」と疑問が湧いてくるんです… >TMR0はオーバーフローで動くタイマーですから >RETFIE命令の手前で再度クリアしてやるという >手は有効です。 あ、割り込みルーチンを抜ける直前で再設定してもよいと言うことでしょうか。 とにかくやってみます。

  • tadys
  • ベストアンサー率40% (856/2135)
回答No.1

>割り込みルーチンの作業時間は0.5秒 等というのは、確実にルール違反です。 割り込みの中で長い処理を行って良いのは、割り込み以外に処理する物が無いような場合です。 割り込みに起因する処理が長くなる場合でも、割り込みの中ではフラグを立てるなどの処理だけを行い、 メインルーチンの中でフラグを見て処理を行うのが普通です。 割り込みの中でTMR0を再設定する方法では、大抵の場合、正確な時間間隔になりません。 TMR0以外の割り込みも併用する場合はなおさらそうです。 正確な1秒が欲しい場合には、TMR0の再設定をしなくても済むようにクロックの周波数を選んでください。 クロックの周波数が自由にならない場合は、TMR2を使用するか、TMR1を外部クロックで使用するのが良いです。 TMR1、TMR2付きのPICといっても大した値段じゃありません。

bota1984
質問者

お礼

ありがとうございます! まだPICの勉強を始めたばかりで、よくわからないことだらけです… >割り込みに起因する処理が長くなる場合でも、割り込みの中ではフラグを立てるなどの処理だけを行い、 >メインルーチンの中でフラグを見て処理を行うのが普通です。 これはすごい参考になりました。 今作っているプログラムで、割り込み処理の中でいろいろやりすぎている感じがしてきたので、整理してみます。

関連するQ&A

  • picのタイマ1発振開始時間に関して

    マイコン Pic16F1939を使用して回路を組み、タイマ1を外部に取り付けた水晶で 動作させています(pic自体は内部オシレータで8MHzで動作させ、Timer1は正確な 1秒を取得するために使用しています) 使用している水晶は32768Hzの時計用のものです。 タイマ1が0.5秒ごとにオーバーフローするように設定し、割込みの関数で液晶の 点滅処理をおこなっています。 水晶の両端はそれぞれコンデンサが添付画像のような接続でつながっています。 また、関連部分のプログラムの抜き出しは以下のようになっています。 // 割込み処理 static void interrupt isr(void) { if (PIR1bits.TMR1IF) { // 32Khz水晶 割込み Int_Timer1(); } ~ 省略 ~ } // タイマー1割り込み(32khz水晶) : 0.5秒ごと void Int_Timer1(void) { PIR1bits.TMR1IF = 0; // 次の割り込み許可のためクリア // 0.5秒で次の割り込みが発生するように設定 TMR1H = 0b11000000; TMR1L = 0b00000000;     ~ 点滅処理 ~     ~省略~ return; } そして以下の初期設定用関数 InitTimer1()と InitInterrupt()を main()の始めに呼んでいます。 // Timer1 setting 32kHz , external crystal void InitTimer1(void) { T1CONbits.TMR1CS1 = 1; T1CONbits.TMR1CS0 = 0; T1CONbits.T1CKPS1 = 0; T1CONbits.T1CKPS0 = 0; T1CONbits.nT1SYNC = 1; T1CONbits.T1OSCEN = 1; T1CONbits.TMR1ON = 1; } // 割込み初期化 void InitInterrupt(void) { PIE1bits.TMR1IE=1; // enable timer 1 interrupt INTCONbits.PEIE=1; INTCONbits.GIE=1; } 質問なのですが、実際に液晶が点滅するまでに2秒ほどかかっています。 どこかのホームページでタイマ1の水晶の発振が安定するまでに 数msecかかるというような情報が書いてあったので、ずいぶん 遅いなと感じ2つのコンデンサの容量を10pF~200pFくらいのあいだで色々 変更して試しているのですが、2秒より早く点滅開始となることはありませんでした。 これは、上記プログラムの問題なのでしょうか? それとも2秒ほどかかって発振するのは仕方ない(Picの仕様)なのでしょうか? どなたかご存知の方いらっしゃいましたらご回答をお待ちしております。

  • PIC16F タイマ0使い方

    久しぶりにPICを引っ張り出して触っていたのですが、タイマ割込みの部分がうまくできていないようで、LED(led_green)を1秒で点滅させたいのですが2秒ぐらいの中途半端な点滅をしてしまいます。 内部クロックを4MHzに設定しているので、これをプリスケーラで8分周しTMR0の値を130に設定し、1msごとに割込みが発生する算段なのですが、どこか間違えてますでしょうか? マイコンは PIC16F886 を使用しています。 #include<pic.h> #include<stdio.h> #include <stdlib.h> #include <xc.h> #define _XTAL_FREQ 4000000 // 内部クロック 4MHz // CONFIG1 #pragma config FOSC = INTRC_NOCLKOUT// Oscillator Selection bits (INTOSCIO oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config MCLRE = OFF // RE3/MCLR pin function select bit (RE3/MCLR pin function is digital input, MCLR internally tied to VDD) #pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled) #pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled) #pragma config BOREN = OFF // Brown Out Reset Selection bits (BOR disabled) #pragma config IESO = OFF // Internal External Switchover bit (Internal/External Switchover mode is disabled) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled) #pragma config LVP = OFF // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming) // CONFIG2 #pragma config BOR4V = BOR40V // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V) #pragma config WRT = OFF // Flash Program Memory Self Write Enable bits (Write protection off) #define TMR_set 130 // TMR0初期値 #define led_green RB0 #define led_white RC3 volatile unsigned int count = 0; volatile unsigned int cnt = 0; // タイマー割込みの処理 void __interrupt() int_f (void){ // 割り込みハンドラ if(T0IF == 1){ // 1ms count++; cnt++; TMR0=TMR_set; T0IF = 0; // 割り込みフラグをクリア (オーバーフローフラグ) if(count>=1000){ // 1s count=0; led_green = ~led_green; } } } void init(){ OSCCON = 0b01100000; ANSEL = 0b00000000; ANSELH = 0b00000000; TRISA = 0b00000000; TRISB = 0b00000000; TRISC = 0b00000000; PORTA = 0; PORTB = 0; PORTC = 0; GIE = 1; // すべての割り込みを許可 (0:禁止, 1:許可) T0IE = 0; // タイマー割り込みを禁止 (0:禁止, 1:許可) T0CS = 0; // TIMAR0モジュールをタイマーとして使用 (0:通常のタイマーとして使用, 1:T0CK端子に入ってきた入力のカウンタ) PSA = 0; // プリスケーラをTIMER0モジュール用にセット OPTION_REG = 0x02; // プリスケーラ 1:8 TMR0 = TMR_set; T0IE = 1; // タイマー割り込みを許可 (0:禁止, 1:許可) T0IF = 0; // 割り込みフラグをクリア (オーバーフローフラグ) } void main(void){ init(); led_white = 1; while(1){ } return; }

  • PICプログラミングに対する質問

    PIC16F627Aを使い、160KHzの周波数を外部に出力したいのですが、うまくいきません。 仕様はこのようになっています。 セラロックとして10MHzを使っています。(20MHzを使うことも考えている) 電源は5Vです。 開発環境はMPLAB IDEに CCS社Cコンパイラを使っています。 現在のプログラムはこのようになっています。 //////////////////////////////////////////////////////////////////////// //タイマ0を用いて160KHzの周波数を出力する //3.1μsでタイマ0の割り込み //////////////////////////////////////////////////////////////////////// #include<16f627a.h> #fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP  //コンフィグレーションの設定 #use delay(CLOCK = 10000000)      //発振子の周波数10MHz  //delay_ms()の使用 //定数の定義 #byte  PORTA=0x05 #bytePORTB=x06 #byte TMR0 = 0x01 #bit T0IF = 0x0B.2 //タイマ0割り込み処理 #INT_RTCC //タイマ0の割り込み処理関数の宣言 void rtcc_isr(void) { T0IF=0; //タイマ0の割り込みフラグ TMR0=0xF8; //タイマ0の初期値 PORTA^=0x04; //PORTAの出力反転 } //メイン関数 void main(void){ set_tris_a(0xF8); //出力ポートの設定 set_tris_b(0xF7); //出力ポートの設定 setup_timer_0(RTCC_INTERNAL | RTCC_DIV_1);//プリスケーラを使用しない set_timer0(0x0); //TMR0に0x0を書き込む enable_interrupts(INT_RTCC); //タイマ0の割り込み許可 enable_interrupts(GLOBAL); //グローバルの許可 PORTB = 0x7F; //出力 while(1){ //割り込みを待つ delay_ms(1); //1μs } } ///////////////////////////////////////////////////////////////////// このようなプログラムで160KHzの周波数を出力することは可能でしょうか? もし不足の部分や誤っていることがあったら教えてください。

  • PICでタイマー割込み(mikroC Vr8.2)

    再三お世話になります。大概の問題もこちらで、 解決できて来ましたが、流石に今回はそうも行かないのではと 覚悟しております。 タイトルにあります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){} } 以上です。

  • PICについての質問です。使用PIC(PIC16F88)

    PICについての質問です。使用PIC(PIC16F88) LEDを0.5秒点灯、0.5秒消灯させるプログラムを書いています。 追加でLEDを駆動するFETが故障してショートモードになったときを考えて、通電監視プログラムを 組み込みましたが、わからないところがあります。 タイマー1を使用して、0.1秒ごとに割り込み、通電検知させて、3秒連続して通電状態の場合はハード的にOFFにするという回路を組み込みました。 0.1秒ごとに割り込みさせて、通電と判断したらカウンターをカウントダウンさせて、0回になったらフラグをたてています。 メインルーチンで フラグチェック処理→0.5秒点灯、0.5秒消灯処理→(はじめに戻る)というフローにより、通電監視フラグを1秒ごとにチェックして、フラグが立ててあれば、強制的にOFFにします。 そのカウンターの設定値ですが、30回にすると3秒後の消灯になりません。いろいろ試した結果23回であれば、最短3秒後以降消灯できるようになりました。 自分で理解したいと思うのですが、なぜこれでうまくいくのかわかりません。 解説書、webも調べましたがわかりません。 どなたか推測でもいいので、教えていただけませんでしょうか?

  • PIC16F88 内部オシレータ使用による割り込み

    PIC16F88を内部オシレータで発振させて使用しています。 問題は、TIMER0割り込みが計算通りに動かないことです。 外部にオシレータを付けると計算通りのタイミングで割り込みが発生するのですが、内部オシレータ使用の場合は、その間隔よりもかなり長くなってしまいます。(0.01秒間隔で割り込みをかけるつもりが、3秒間隔ぐらいになってしまいます。) 何が原因なのでしょうか? 完全な答えでなくても色々試してみますので、何か気になる部分が御座いましたら、教えて下さい。

  • PICのPWMの正しい使い方について教えてください

    PIC12F1822用のPWMの基本動作テストプログラムを作りましたが、PWM出力が意図どおりに得られません。 (XC8のテストプログラムを下に添付。テストパターン1/2の切り替えはコメントアウトをお願いします。  アナライザの出力を画像で添付しました。) テスト目的: タイマー0の周期割り込みに合わせて、PWMのデューティー比(または周期)を変更するプログラム   テストパターン 1 : パルスのデューティー比を変えるテスト 質問1: パルスのデューティー比を変えるテストは、PWM設定の一回おきにCCPからのPWMの出力が出ません テストパターン 2 : パルスの周波数を変えるテスト 質問2: 周波数を変えるテストはOKに見えるものの、1回目のPWMがHighとなるのと、割り込みの11回目、13回目あたりでPWM出力が欠落する 【回答のお願い】 どうも、PWMのレジスタ設定に手順、またはタイミングがあるのではないかと思いますが、原因がわからず困っております。 PICに詳しい方からのご指導をよろしくお願いいたします。                                    K.A. ------------------------------------------------------ /* * File: PIC12F1822 PWC * Author: K.A. * * Created on 2014/07/20 * * タイマー0の周期割り込みに合わせて、PWMのデューティー比(または周期)を変更するプログラム * */ #include <stdio.h> #include <stdlib.h> #include <xc.h> #pragma config FOSC=INTOSC, WDTE=OFF, PWRTE=ON, BOREN=ON, MCLRE=OFF #define _XTAL_FREQ 8000000 // クロック8MHz /* * */ // タイマー割込みの処理 int TMR0_Count = 0; // タイマーの割込み発生回数をカウントする変数 void interrupt Timer0(void) { // タイマー0の割込み発生か? Timer0 は 8bitの オーバーフロー・カウンタ if (TMR0IF == 1) { TMR0_Count++; if (TMR0_Count > 5) { TMR0_Count = 0; if (RA5 == 0) RA5 = 1; else RA5 = 0; // RA5は、動作表示用LED } TMR0IF = 0; // タイマー0割込フラグをリセット } } int main(int argc, char** argv) { unsigned int pulse_width = 5; OSCCON = 0b01110010; // 内部クロックは8MHz ANSELA = 0b00000000; // すべてをデジタルI/Oに割当 TRISA = 0b00001000; // すべてのピンは出力に割当てる(RA3は入力専用) PORTA = 0b00000000; // 出力ピンの初期化(全て'0'にする) RA5 = 0; // 動作確認用LED // Timer0  Timer0 は 8bitの オーバーフロー・カウンタ OPTION_REG = 0b00000001; // 内部クロックでTIMER0を使用、プリスケーラカウント値 1:2 // bit5:0=Fosc/4, bit3:0=PreScaler_ON, bit2-0:PreScaler TMR0 = 0; // タイマー0の初期化 (+2cycle) TMR0IF = 0; // タイマー0割込フラグを0にする TMR0_Count = 0; // 割込み発生の回数カウンターを0にする TMR0IE = 1; // タイマー0割込みを許可する GIE = 1; // 1: 全割込み処理を許可する /* PWM */ TRISA2 = 1; // RA2 出力をサスペンド TMR2IF = 0; // TMR2 フラグをクリア CCP1SEL = 0b0; // CCP1/P1Aの機能をRA2に割り当てる CCP1CON = 0x0C; // PWM モード // Period を 設定する xx ms=((PR2)+1)*4*125ns(8MHz)* PreScaler(x1-x64) PR2 = 127; // 4.096ms (プリスケーラが x64 の場合) T2CKPS0 = 0b1; // プリスケーラ 00:x1, 01:x4, 10:x16, 11:x64 T2CKPS1 = 0b1; // CCPR1L = pulse_width >> 2; // パルス幅上位8bit CCP1CON = ((pulse_width & 0x0003) << 4) | 0x0C; // パルは幅下位2bit TMR2ON = 1; // TMR2 カウント開始 while (TMR2IF == 0) { /** / do nothing /**/ } TRISA2 = 0; // RA2に出力を接続 while (1) { if (TMR0_Count == 0) { /**** テストパターン 1 : パルスのデューティー比を変えるテスト ****/ // パルスのデューティー比を変えるテストは、PWM設定の一回おきにCCPがPWMの出力が出ません。 なぜ? pulse_width = pulse_width + 10; if (pulse_width > 500) pulse_width = 5; /**/ /**** テストパターン 2 : パルスの周波数を変えるテスト **** / // 周波数を変えるテストはOKに見えるが、 // 1回目のPWMがHighとなるのと、割り込みの11回目、13回目あたりでPWM出力が欠落する PR2 = PR2 - 8 ; if (PR2 < 8) PR2 = 127; pulse_width = PR2 ; // Duty 25% に相当 /**/ CCPR1L = pulse_width >> 2; CCP1CON = ((pulse_width & 0x0003) << 4) | 0x0C; TMR0_Count++; // 続けて PWMの設定変更をしないためのフラグ代わり } } return (EXIT_SUCCESS); }

  • PIC タイマー0の使い方

    PIC16F886を触り始めたのですが、タイマー割り込みで苦戦しています。 タイマー割り込みを使ったLEDの点滅の間隔が、自分の思った時間にならないのです。 下に今のプログラムを載せておきます。 私の今の考え方はこうです。 ・内部クロックは4MHzに設定してある ・TMR0のカウントはクロックの1/4らしい→1MHzなので周期は1μsec ・プリスケーラは1:128に設定→128μsecでTMR0がカウントアップ ・TMR0の初期値を61に設定→195回のカウントアップでT0IF=1 ・128μsec*195μsec=2496μsec≒0.025msec←タイマー割り込み ・40回カウントすると1秒 と、1秒ごとにLEDのON,OFFが切り替わるはずだと考えているのですが、書き込んで計測したところ、約0.8秒でon,offを繰り返しています。 私の考え方やプログラムに間違いがあるのでしょうか? もしくはPICがハード的に壊れているのでしょうか?(picに5Vをかけても動かず、mainが実行中に点灯するLED(この時点では点いていない)の端子の両端を指で触ると何故か動き出します。) 以下プログラムです。(注釈などは省いたので見難いかもしれません) #include <stdio.h> #include <stdlib.h> #include <xc.h> #include <pic.h> #pragma config FOSC = INTRC_NOCLKOUT #pragma config WDTE = OFF #pragma config PWRTE = OFF #pragma config MCLRE = OFF #pragma config CP = OFF #pragma config CPD = OFF #pragma config BOREN = ON #pragma config IESO = OFF #pragma config FCMEN = OFF #pragma config LVP = ON void interrupt tc_int(void); volatile unsigned int cnt = 0; volatile unsigned int cnt1 = 0; #define sw RB0 #define led RA0 #define led2 RA1 #define led3 RA2 #define _XTAL_FREQ 4000000 void init(void) //初期設定 { OSCCON=0b01101000; // 内部クロック設定 4MHz TRISA=0b00000000; TRISB=0b00000000; TRISC=0b00000000; ANSEL=0x00; /* 割り込み初期設定 */ GIE = 1; // すべての割り込みを許可 T0IE = 0; // タイマー割り込みを禁止 T0CS = 0; // TIMAR0モジュールをタイマーとして使用 PSA = 0; // プリスケーラをTIMER0モジュール用にセット OPTION_REG |= 0x06; // CPUクロックを128分周 TMR0 = 61; // カウンタ値をリセット T0IE = 1; // タイマー割り込みを許可 T0IF = 0; // 割り込みフラグをクリア } int main(void) { init(); sw=1; led=1; led3=0; cnt1=0; LEDflg=0; while(1) { if(cnt1>=10){ led3=~led3; cnt1=0; } } } void interrupt tc_int(void){ // 割り込みハンドラ if(T0IF == 1){ cnt++; TMR0=61; T0IF = 0; // 割り込みフラグをクリア if(cnt>=40){ cnt=0; cnt1++; led2= ~led2; } } }

  • PIC12F683 TMR2の割込がうまくいきませ

    タイトルのPICを使ってTMR2の割込動作を確認しているのですが、割込が全く掛かりません。 TMR2は単独で割込を掛けないで動作することは確認できましたがエラーもあるわけでもなく あれこれやっても解決せず迷走中です。また、割込ルーチンはこれまで動作が確認できたプログラムを埋め込んで使っているので問題はないと思っています。 何方かお助け頂けませんでしょうか。宜しくお願い致します。 ;******************************************* ; PIC初期設定 ;******************************************* START_INI BCF STATUS,RP0    ;BANK【0】 MOVLW 07h MOVWF CMCON0 ;GP0-2はデジタルIO BSF STATUS,RP0    ;BANK【1】 MOVLW B'0000000' MOVWF ANSEL ;A/D変換クロックF/2 デジタルI/O BCF OPTION_REG,7 ;GPIO端子をプルアップ MOVLW B'001000' ;RESET端子有効 MOVWF TRISIO ;GP0,1,2,4,5:OUT GPO3:IN MOVLW B'1000000' ;40h MOVWF OSCCON ;クロック=1MHz ;******************************************* ; TMR2の設定 ;******************************************* BCF STATUS,RP0    ;BANK【0】 MOVLW B'000101' ;ポス=1:1 TMR2=ON プリ=1:4 MOVWF T2CON ; BCF PIR1,TMR2IF    ;Timer2 割込み検出フラグをクリア BSF STATUS,RP0    ;BANK【1】 BSF PIE1,TMR2IE    ;Timer2 有効 MOVLW H'FA' ;250 MOVWF PR2    ;TRM2カウントSET ;******************************************* BCF STATUS,RP0     ;BANK【0】 CLRF TMR2 BSF INTCON,GIE     ;割り込み全体を有効

  • 2度目の投稿となります。

    2度目の投稿となります。 現在、社員研修でPIC18F2550を使ったプログラミングを行っているのですが、下記内容についてうまく動作しません。 大変恐縮ですが、原因についてアドバイス頂けますと幸いです。 作成環境はMPLAB V8.36、MPLAB C18コンパイラV3.33 です。 <質問内容> ◎タイマ1がうまく動作しない。 やりたい事は、  (1)タイマ0(8bit)を使い割り込みを発生させ、ポートから信号ON/OFF(PWM信号を出したい)。  (2)タイマ1(16bit)を使いCCP1/2のコンペアマッチ割り込みを行ない、CCP1ポートからPWM信号ON/OFF(サーボモータの動作用PWM信号を出したい)。 (1),(2)を同時進行で動作させたい、というものです。 シミュレーションで確認したところ、タイマ0/1のカウントアップ動作自体は確認できているのですが、タイマ1が8bitのところでオーバーフロー?して、タイマ0と同時に0にリセットされてしまいます。 以下に作成コードを掲載します。 --【以下、コード抜粋】-- //===《初期設定》=== //---<ヘッダーファイル>--- #include<p18f2550.h> //---<コンフィグレーション>--- //---<関数宣言>--- //---<割り込みの定義関連>--- //===《動作プログラム》=== //---<メイン関数>--- void main() { ioport_settei(); //サブルーチン「ioport_settei」実行(入出力ポート初期設定) interrupt_settei(); //サブルーチン「interrupt_settei」実行(割り込み初期設定) tmr_ccp_settei(); //サブルーチン「tmr_ccp_settei」実行(タイマ&CCPモード初期設定) while(1) //繰り返し(ずっと繰り返す) { } } //---<サブルーチン>--- void ioport_settei(void) //[入出力ポート初期設定] {省略} void interrupt_settei(void) //[割り込み初期設定] { INTCONbits.GIE = 1; //グローバル割り込み設定:許可 INTCONbits.PEIE = 1; //周辺割り込み設定:許可 INTCONbits.TMR0IE = 1; //タイマ0割り込み設定:許可 PIE1bits.TMR1IE = 1; //タイマ1割り込み設定:許可 PIE1bits.CCP1IE = 1; //CCP1割り込み設定:許可 PIE2bits.CCP2IE = 1; //CCP2割り込み設定:許可 } void tmr_ccp_settei(void) //[タイマ&CCPモード初期設定] { TMR0H = 0; TMR0L = 0; TMR1H = 0; TMR1L = 0; T0CON = 0b11001000; //タイマ0設定(有効,8bit,内部クロック,プリ1倍) T1CON = 0b10000001; //タイマ1設定(有効,16bit,内部クロック,プリ1倍) CCP1CON = 0b00001001; //CCP1設定(Compare mode,RC2=0,割り込み発生) CCP2CON = 0b00001011; //CCP2設定(Compare mode,スペシャルイベントトリガ,割り込み発生) CCPR1 = 3750; //CCP1 Duty値初期設定(PWM(ON時間)=1.5ms…ニュートラル位置) CCPR2 = 50000; //CCP2 Duty値初期設定(PWM(周期)=20ms) } //---<割り込み処理関数>--- #pragma code void isr(void) { if(INTCONbits.TMR0IF == 1) { INTCONbits.TMR0IF = 0; } } となります。 大変恐縮ですが、原因が判る方がいらっしゃいましたら、ご教示のほどよろしくお願い致します。

専門家に質問してみよう