PICマイコンのPWMの設定で100%にならない現象について

このQ&Aのポイント
  • PICマイコンのPWM設定で、デューティーを1023にしてもOFFの部分が現れる現象が発生しています。
  • 10bitのPWMモードで最大値の1023をセットしても常時ONにならず、プリスケーラを変更しても解決できません。
  • MPLAB XとXC8を使用して開発を行っています。10bitで常時ONを作り出す方法についてのアドバイスをお願いします。
回答を見る
  • ベストアンサー

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

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

  • ベストアンサー
回答No.1

その様な仕様ですデーターシートを見れば容易にわかることです。 http://ww1.microchip.com/downloads/en/DeviceDoc/41364E.pdf 1023カウントで出力はOFFになります、同時に次のサイクルに入りますが出力に反映されるまで遅延時間(td)があるので100%デューティーにはなりません。 1024以上にするかPWMを使用せず単純にONにするかですね。

chibichan_dayo
質問者

補足

TooManyBugsさん ご回答ありがとうございます。 データシートの件ですが201ページに記載の内容でしょうか? (日本語版のほうを見ています。http://www.microchip.jp/docs/41364B_JP.pdf) デューティーは10bitで1023までしか設定できないと思うのですが1024以上に設定するというのは 具体的にどのようにするのでしょうか。 すみませんが再度ご回答いただけると幸いですm(._.)m

関連するQ&A

  • 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の使い方を教えてください

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

  • PWM を使ったSine波の生成について

    今、以前に投降した正弦波発振器とは別に、PIC16F88のPWMを使って正弦波を発生する小型の回路を作ろうと考えています。 以下のようなプログラムを作りました。 コンパイルは通るのですが、「error: (1250) could not find space (128 bytes) for variable F994」と「could not find space (128 bytes) for variable _data」というエラーメッセージがでてビルドができません。 どの個所が悪いのでしょうか教えてください。 また、開発環境については、MPLAB X IDE(バージョン3.20)でコンパイラーはXC8(バージョン3.60)を使用しています。 ///////////////////////////以下プログラム///////////////////////////////////////// #include <pic.h> #define _XTAL_FREQ 4000000 //CONFIGは省略 void ioport(void); void setCcpMode(unsigned char); void setPwmPeriod(unsigned char); void setPwmDuty(unsigned int); void ConfigTMR2(unsigned char set); void main(void) { unsigned int cnt; unsigned char data[128]={128,134,140,146,152,159,165,171,176,182,188,193,199,204,209,213,218,222,226,230,234,237,240,243,246,248,250,252,253,254,255,255,256,255,255,254,253,252,250,248,246,243,240,237,234,230,226,222,218,213,209,204,199,193,188,182,176,171,165,159,152,146,140,134,128,121,115,109,103,96,90,84,79,73,67,62,56,51,46,42,37,33,29,25,21,18,15,12,9,7,5,3,2,1,0,0,0,0,0,1,2,3,5,7,9,12,15,18,21,25,29,33,37,42,46,51,56,62,67,73,79,84,90,96,103,109,115,121}; ioport(); setCcpMode(CCP_PWM_ACTIVE_HIGH);//CCP1CONに0b00001100をセット setPwmPeriod(255);//PR2に255をセット setPwmDuty(0); ConfigTMR2(TMR2_DIV4_ON);//TMR2のプリスケーラーを4倍に、そしてTMR2をON while(1){ //duty=adconv(0); for(cnt=0;cnt<128;cnt++){ setPwmDuty(data[cnt]); } } } void ioport(void){ OSCCON=0x60; CMCON=0x07; TRISA=0x00; ANSEL=0x00; PORTA=0x00; TRISB=0x00; PORTB=0x00; } void setCcpMode(unsigned char mode) { CCP1CON= mode; } void setPwmPeriod(unsigned char T) { PR2=T; } void setPwmDuty(unsigned int duty) { unsigned char tmp; tmp=(unsigned char)((duty & 3)<<4); CCP1CON |=tmp; tmp=(unsigned char)(duty>>2); CCPR1L=tmp; } void ConfigTMR2(unsigned char set) { T2CON=set; }

  • PIC16F627Aを低電圧で動かすには

    PIC16F627Aです 電池で駆動するプログラムを書いていてうまく動かないので 5V安定化電源につないだら動きました。 確かめるために BポーがをHIにするところでストップするようにして確かめました。 4.4Vでは動作しません。5Vでは動作します。 プログラムは下記です。 このPICは3Vから動作すると思いますが低電圧で 動かすために特別な設定が必要なのでしょうか。 あるいは小生の設定に問題があるのでしょうか。 ご教授ください。   TRISA = 0xFF;   TRISB = 0x01; CCP1CON = 0x0C; PR2 = 0x19; CCPR1L = 0x0C; CCP1CON = PWM_STOP;   T2CON = 0x0C; T1CON = 0x01; TMR1L = 0; TMR1H = 0; TMR1IF = 0; TMR1IE = 1; PORTA = 0x00; PORTB = 0xFF;   ここで4.4V(電池)ではPORTB がHIになりません。   5V電源ではHIになります。   電圧チェックおよびダイオード発光で確認しました while(1) {;}; 以下省略

  • 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; } } となります。 大変恐縮ですが、原因が判る方がいらっしゃいましたら、ご教示のほどよろしくお願い致します。

  • 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出力の周期について

    PIC(16f873)を用いて、モータをPWM制御しようと思っています。 そこでいくつか質問なんですが、PWMの周期は下記の式で与えられるとありますが、 PWM周期 = (PR2の値+1)x4x発振器周期xタイマー2のプリスケーラ値 この周期は、自分で適当に決めていいのでしょうか?それともモータによって決まっているんでしょうか?  そもそもPWMは、デューティ比で出力が変わると思うんですが、周期が違うとどのような違いが出るのでしょうか?周波数が高くなると細かい制御が出来るって感じでしょうか? 初歩的な質問ですが、よろしくお願いします。m(_ _)m

  • PIC12F683を用いたCapture実験

    いま、PIC12F683を用いてCCPモジュールのCapture機能の実験をしています。一応、ビルドはできたので書き込んで動かしてみましたが、思ったとおり(スイッチを押したときにLEDを点灯させる)に動作しませんでした 動作はとしては、押しボタンスイッチを押したときにキャプチャーして LEDを点灯させるという簡単なものです。 下に使用しているプログラムを掲載しますので、どうしたらいいか教えてください。 // CaptureTest.c #include <pic.h> #include "delay.h" #include "CCP.h" __CONFIG( FCMDIS & IESODIS & BORDIS & WDTDIS & UNPROTECT & UNPROTECT & MCLRDIS & PWRTEN & INTIO); __IDLOC(0x00); unsigned char temp; ioport(); main(void) { //ポートの初期化、入出力設定など     ioport(); //Captureモード、立ち上がりエッジに設定 setCcpMode(CCP_CAPUTURE_PGE);      //フラグ(CCP1IF)を「0」にセット ResetCcpFlag();      //CCP割り込み許可 setCcpEnable(ENABLED); //TIMER1のプリスケーラを「1/8」に設定      T1CKPS1=1; T1CKPS0=1;     //外部回路を動作させない T1OSCEN=0;     //TIMER1を同期モードにセット T1SYNC=0;     //TIMER1のクロックは内部クロックを使用 TMR1CS=0;     //全割り込み、周辺割り込み許可 GIE=1; PEIE=1;      //TIMER1をリセット(0セット) ResetTMR1(); //TIMER1スタート     T1_START();      //CCP割り込みフラグが立つまでチェック while(ChkCcpFlag()==0);     //CCP割り込みフラグクリア ResetCcpFlag();     //GP3をハイレベルに設定してLEDを点灯 temp=1; GPIO3=temp; } ioport() { ANSEL=0x00; TRISIO=0x04; } //CCP.c #include <pic.h> void setCcpMode(unsigned char mode) { CCP1CON= mode; } void setPwmPeriod(unsigned char T) { PR2=(T-1); } void setPwmDuty(unsigned int duty) { DC1B0 = 0x01&duty; DC1B1 = 0x02&duty; CCPR1L = 0xFC &duty; } void setCcpEnable(unsigned char flag) { CCP1IE=flag; } void ResetCcpFlag(void) { CCP1IF=0; } unsigned char ChkCcpFlag(void) { unsigned char ret=0; if(CCP1IF==1) return ret=1; return ret; } void ResetTMR1(void) { TMR1H=0x00; TMR1L=0x00; } void T1_START(void) { TMR1ON=1; } void T1_STOP(void) { TMR1ON=0; } //CCP.h #define ENABLED 1 #define DISABLED 0 #define CCP_OFF 0x00 #define CCP_CAPUTURE_NGE 0x04 #define CCP_CAPUTURE_PGE 0x05 #define CCP_CAPUTURE_4th_PGE 0x06 #define CCP_CAPUTURE_16th_PGE 0x07 #define CCP_COMPARE_SET_ON_MATCH 0x08 #define CCP_COMPARE_CLR_ON_MATCH 0x09 #define CCP_COMPARE_INT 0x0A #define CCP_COMPARE_RESET_TIMER 0x0B #define CCP_PWM 0x0C extern void setCcpMode(unsigned char); extern void setPwmPeriod(unsigned char); extern void setPwmDuty(unsigned int); extern void setCcpEnable(unsigned char); extern void ResetCcpFlag(void); extern unsigned char ChkCcpFlag(void); extern void ResetTMR1(void); extern void T1_START(void); extern void T1_STOP(void);

  • 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マイコンでGIEビットが1に出来ません。(コンパイラのバグ?)

    質問は初めてです。 GIEビットが1にセット出来ません。 デバッグでは、 GIE = 1; の文が無視され飛び越えます。 デバッグのwatchで監視してもセットされないのが確認出来ます。 マイコンに書き込んで実行させても割り込みが発生してないのが分かります。 環境はMAPLAB IED v8.46 と HI-TECH PICC の無料版?です。 ↓プログラム全てを書くとやたら長いのでIOなどの設定している関数だけ表示します↓ void Ioport(){ PORTA = 0x00; //ポートA初期化 PORTB = 0x00; //ポートB初期化 PORTC = 0x00; //ポートC初期化 TMR0 = 0x00; //タイマ0初期化 OSCCON = 0x60; //外部クロック20MHz使用 OSCTUNE = 0x00; //動作クロックのチューン無し CM1CON0 = 0x00; //コンパレータ無効でデジタルIOモード可能 CM2CON0 = 0x00; ANSEL = 0x00; //デジタルIOモード ANSELH = 0x00; OPTION = 0x08; //RBプルアップ有効、TMR0を命令クロック、 //プリスケーラをTMR0に使わない T0IF = 0; //フラグ タイマ0初期化 T0IE = 1; //割り込みタイマ0可能 GIE = 1; //割り込み全体可能(ココが飛ばされます) TRISA = 0b11000000; //出力:0~4LED7セグメントのブロック用5つ WPUB = 0b11100111; //0~2プルアップ設定 3赤外線受信4赤外線送信 TRISB = 0b11101111; //0~2ボタン3つ 出力:4赤外線送信 TRISC = 0b00000000; //0~7LED7セグメントのパーツ用8つ //GIE = 1; ココに書くとコンパイラがエラーを起こします。 } void main(void){ Ioport();     //GIE = 1; ココに書くとセットしてくれて正常に動作します。 } 他に GIE = 1; を書く場所によっては、 Ioport()関数の最後に書くと、 67.23 ";" expected 71.1 undefined identifier "portBRead" 77.9 void function can't return a value 81.9 void function can't return a value 85.9 void function can't return a value 88.9 void function can't return a value 91.9 void function can't return a value と、的外れ的なコンパイルエラーが出ます。 そして、 main()関数のIoport()関数の後に書くと、 何故か正常動作し実際に書き込んでも正常に動作します。 後 書く順番によっては T0IF = 0; GIE = 1; T0IE = 1; と書くとGIEビットは1にセットされるが、T0IEビットは無視され飛び越えます。 新規projectで再度試しましたが同じでした。 これは、コンパイラのバグなのでしょうか? 解決策の回答をお願いします。

専門家に質問してみよう