• ベストアンサー

PICのTIMER0について

TMR0の初期値とプリスケーラ値の設定によって割り込み発生までに必要なカウント値が決まる、と書いてありますが。プリスケーラ値を変えると計算どおりなんですが、TMR0値をかえると、計算が大きくはずれてきます。なぜなんですか。TMR0値は0以外はだめなんですか。

noname#62952
noname#62952

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

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

TMR0値を書き込んだ時にその書き込みが有効なのは1回限りです。 割り込みが発生したら毎回書き換えてやらなくてはいけません。 割り込みが発生してからTMR0を書き換えるまでには時間がかかりますから その分設定値を調整する必要があります。 割り込み原因が発生してから実際に割り込みが動作するまでの時間は 場合によって変化しますから正確な繰り返しが必要な場合にはTMR0は使えません。 その場合はTMR3を使用しましょう。

noname#62952
質問者

お礼

回答ありがとうございます。 何回やってもおかしな結果ばかりでて不思議に思ってました。

関連するQ&A

  • PIC、TMR2とPWMについて。(再投稿)

    カテ違いなのか説明が悪いのか回答が付かなかったので 再投稿しました。 PWMでTMR2の10ビットの理屈がわかりません。 まず現状の理解ですが以下のとおりです。 ・分解能10ビットでPWMを使うにはPRxを255に設定する。  PRxに設定した値がTMR2のカウント最大値になる。  PRxを255に設定したのでTMR2も255までカウントされる。  (PRxに設定した値がPWMの周期として動作する最大値) ・パルスの幅はCCPRxL(上位8ビット)および、DCxB1,DCxB0(下位2ビット)の10ビットで設定する。 実際のPWMの動作は以下のとおり CCPRxL,DCxB1,DCxB0 の10ビット ↓コピー CCPRxH(10ビット) ↓比較 一致でPWMの出力が反転 TMR2(上位8ビット + 謎の下位2ビット) ↑比較 一致でTMR2 + 謎の下位2ビットがクリア PRx(8ビット) わからないぶぶんなんですが 1、TMR2の下位2ビットって具体的にどのレジスタなんでしょうか。 2、プリスケーラを設定しない場合(等倍)はPSという2ビットが付加されTMR2は10ビットカウンタとして 動作するとなっていましたが、0,1,2,...1023までカウントされるんでしょうか。 3、TxCKPS1,TxCKPS0 に値をセットしてプリスケーラを4,8,64等にした場合 TMR2の8ビットと下位2ビットはどういう関係になるんでしょうか。 単純に1024階調(0-1023) * 4tocs * プリスケール値 で0から1023までカウントされると考えていいんでしょうか。 4、PRxは8ビットしかないのにTMR2 + 2ビットの10ビットとどうやって比較されてるんでしょうか。 たとえばDCxB1,DCxB0(下位2ビット) のみ設定してCCPRxL(上位8ビット)を0にした場合、何と比較されるんでしょうか。 5、TMR2をスタートする前にカウンタをリセットしますが10ビット分リセットするにはTMR2のクリアと下位2ビットはどのレジスタをクリアすればいいんでしょうか。 PICは16F1936を使ってます。 MPLAB X + XC8で開発してます。 説明がわかりずらいかもしれませんが上記の部分がいまいち理解できません。 この辺の事に詳しい方、教えていただけると助かります。

  • 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マイコン、PWMが100%になりません。

    PIC16F1936でPWMのの実験をしているのですが PWMの分解能10bitでデューティーを1023にしてもオシロで確認するとOFFの部分が現れます。 (画像は実際にオシロで計測したものです。) 設定は以下の通りです。 ------------------------- // 10bit PR2 = 255; // TMR2を選択 CCPTMRS0 = 0; // PWMモードを選択 CCP1CON = 0b1100; // プリスケーラを64にセット T2CON = 0b11; //TMR2クリア TMR2 = 0; // tmr2開始 TMR2ON = 0b1; uint test1 = 1023; // 下位2bitをセット CCP1CON |= ((test1 << 4) & 0b110000); // 上位8bitをセット CCPR1L = test1 >> 2; ------------------------- PR2を254とかにセットすると1023で常時ONの状態が続くのですが 10bitの255にすると最大値の1023をセットしても常時ONになりません。 プリスケーラを変更したりいろいろ悪あがきしたのですがどうにもうまくいきません。 10bitで常時ON(デューティー100%)を作り出すのは無理なんでしょうか? 設定が足りないな部分などあれば教えてください。 開発環境は MPLAB X です。 コンパイラは XC8 です。 お知恵をおかしください m(._.)m

  • PICマイコン、水晶発振子の異常

    カテ違いかも知れませんがマイコンおよび電子回路についての質問です。 水晶発振子が異常発信しMCLRによるリセット後、正常に発振します。 マイコン:PIC16F887 水晶発振子:VT-200-F コンフィグは以下のように設定 __CONFIG _CONFIG1, _LVP_OFF & _FCMEN_ON & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _LP_OSC __CONFIG _CONFIG2, _WRT_OFF & _BOR21V OPTION_REGは以下のように設定 movlw B'01011000' ; 7.ポートBのプルアップ:無効 ; 6.ポートBの割り込みエッジ ; 5.TMR0のクロック源:内部命令サイクル ; 4.TMR0のカウントするクロックエッジ ; 3.プリスケーラ:WDTに割り当て ; 2.1.0.プリスケーラ初期値(未使用) movwf OPTION_REG 13ピン(CLKIN)と14ピン(CLKOUT)に水晶発振子を接続。 それぞれに15pFのコンデンサを接続。 40ピン(RB7)にLEDを接続(TMR0で割込みが発生したタイミングで点灯消灯を繰り返します。) 1ピンはMCLRとして利用 で、計算上の割込みタイミング(プリスケーラなし) (1/(32.768/4))*256=31.25ms なのですが40ピンのHI、LOWタイミングをオシロで観測したところ 実測値は以下のとおりでした。 電源接続直後:256.7us 1ピンでのリセット後:31.37ms(ほぼ計算通り) 電源接続直後は必ず上記のようになり1ピンでリセットすると正常に発振し始めます。 コンデンサの容量が合っていないのかと思いいくつか試してみました結果は同じでした。 水晶発振子も変えてみましたがやはり結果は同じでした。 コンデンサの足も切って短くしてみましたがこれも結果は変わりませんでした。(この程度の距離は関係ない?) 回路はブレットボード上です。 マイコンが壊れているのでしょうか? 今までもっぱらセラロックや水晶発振器を使っていて今回初めて水晶発振子を使ってみてこのような事象に遭遇しました。 どのようにしたら正常発振するか詳しい方、ご教示いただけたら幸いです。

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

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

  • 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; } } }

  • PICのPWMの使い方を教えてください

    PIC12F1822のPWMのテストをしていますが、正しい設定方法が判らず、以下の現象が出ています。 プログラム全体と、MPLIB のシミュレータによるLogic Analyzerの画像を添付しましたので、PICにお詳しい方のアドバイスをよろしくお願いいたします。 ◆ テスト内容: 周波数一定でデューティー比を変化させていく  今回の設定は、PR2=127 なので、パルス幅を0 ~ 最大パルス幅の 511 ((PR2+1)*4)で変化させる ●問題点1: デューティー比100%近く(508/512)でPWM出力が突然 50%に変わる。 ●問題点2: デューティー比100%以上(512/512以上)を設定するとPWMは100%('H'のまま)となる。 その後デューティ比を下げてもPWMの出力は'H'のままで、PWMの出力が出ない。 ● 問題点3: パルス幅の設定で、CCP1CON<5:4>に'00'以外をセットすると、PWMの動作がおかしくなる(出力が'H'のまま) ・・・ これはシミュレータのバグでしょうか? プログラム全体は、一番下にありますが、メインロジックは以下のように簡単なものです。 while (1) { for (i = 500; i <= 512; i = i + 1) { pulse_width = i ; CCPR1L = pulse_width >> 2; // パルス幅上位8bit CCP1CON = ((pulse_width & 0x0003) << 4) | 0x0C; // パルス幅下位2bit         // ここで、CCP1CON<5:4>に'00'以外をセットすると、PWMの動作がおかしくなる __delay_ms(1); } } どうぞよろしくお願いいたします。                           K.A. --------------------------------------------- /* * File: 周波数一定、ディューティー比連続変化 * Author: K.A. * * Created on 2014/07/20 * */ #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 #define __delay_ms(x) _delay((unsigned long)((x)*(_XTAL_FREQ/4000.0))) int main(int argc, char** argv) { OSCCON = 0b01110010; // 内部クロックは8MHz ANSELA = 0b00000000; // すべてをデジタルI/Oに割当 TRISA = 0b00001000; // すべてのピンは出力に割当てる(RA3は入力専用) PORTA = 0b00000000; // 出力ピンの初期化(全て'0'にする) RA5 = 0; // 動作確認用LED /* 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; // 0.064ms (プリスケーラが x1 の場合) T2CKPS0 = 0b0; // プリスケーラ 00:x1, 01:x4, 10:x16, 11:x64 T2CKPS1 = 0b0; // CCPR1L = 0; // パルス幅上位8bit CCP1CON = ((0 & 0x0003) << 4) | 0x0C; // パルス幅下位2bit TMR2ON = 1; // TMR2 カウント開始 while (TMR2IF == 0) { /** / do nothing /**/ } TRISA2 = 0; // RA2に出力を接続 unsigned int pulse_width; int i; while (1) { // パターン1 : デューティー比を変化させていく // 今回の設定は、PR2=127 なので、最大パルス幅は 511 ((PR2+1)*4) // 問題点1: デューティー比100%近く(508/512)でPWM出力が突然 50%に変わる。 // 問題点2: デューティー比100%以上(512/512以上)を設定するとPWMは100%('H'のまま)となる。 // その後デューティ比を下げてもPWMの出力は'H'のままで、PWMの出力が出ない。 // 問題点3: パルス幅の設定で、CCP1CON<5:4>に'00'以外をセットすると、PWMの動作がおかしくなる(出力が'H'のまま) for (i = 500; i <= 512; i = i + 1) { pulse_width = i ; // Pulse width を 設定する PW=(CCPR1L:CCP1CON<5:4>)*125ns(8MHz)*PreScaler(x1-x64) CCPR1L = pulse_width >> 2; CCP1CON = ((pulse_width & 0x0003) << 4) | 0x0C; // CCP1CON<5:4>に'00'以外をセットすると、PWMの動作がおかしくなる // printf("PR2= %d, PW= %d, CCPR1L= %x, DCIB= %x \n", PR2, pulse_width, CCPR1L, temp2) ; __delay_ms(1); if (RA5==1) RA5=0; else RA5=1 ; } } return (EXIT_SUCCESS); } ----------------------------------------

  • 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     ;割り込み全体を有効

  • 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の周波数を出力することは可能でしょうか? もし不足の部分や誤っていることがあったら教えてください。

  • C言語でPICマイコン開発

    今までずっとアセンブラを使い開発していたのですが、XC8コンパイラ+MPLABで C言語を使い開発したいと思っています。 以下の点について教えていただければ助かります。 ・タイマー割り込みについて アセンブラで書く場合、プリスケーラの設定などから計算して 一回の割り込み内で何命令まで書けるかがわかるため割り込みの最中に 再度割り込みが発生するようなことは避けられますが Cで書く場合はどのように回避するのでしょうか? ・コンフィギュレーションの設定の仕方 アセンブラでは__CONFIG _HS_OSC & _CP_OFF ・・・のように書きますが Cではどのように書くのでしょうか。 C言語はわかるので取っ掛かりの部分がわかれば後はすいすいいけると思うのですが。。。 上記とあわせてお勧めの書籍やページなどがありましたら教えていただけないでしょうか。 よろしくお願いします。