• 締切済み

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

みんなの回答

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.1

回答でなくて申し訳ありません。 質問者さんが何度目の投稿をなさろうが、 回答しようとする側には「どうでもいいことです」。 >PIC18F2550を使ったプログラミング ということであれば、タイトルを見ただけで ある程度質問内容が推測できるようにしてください。 次回からでかまいませんので。

annie-t
質問者

補足

すみません。入力ミスです。 久しぶりに「OK Wave」で投稿したのですが、フォームにタイトルを入力する欄が無く(前回投稿した時は確かタイトル入力欄があったような気が…)、どこに入力するのかわからないままに入力作業を行っていたところ、投稿されてしまい、「本文の1行目がタイトルとなってしまう」事がわかった時は手遅れでした。 即座に1行目にタイトルを入れたものを投稿し直し、本投稿を削除しようと思ったのですが、削除できないようで、本投稿もそのまま残ってしまいました。 紛らわしい投稿となってしまい、申し訳ありませんでした。

関連するQ&A

  • 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

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

  • 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の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マイコンで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で再度試しましたが同じでした。 これは、コンパイラのバグなのでしょうか? 解決策の回答をお願いします。

  • 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) {;}; 以下省略

  • 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の仕様)なのでしょうか? どなたかご存知の方いらっしゃいましたらご回答をお待ちしております。

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

  • PIC18F2550・コンパイルできない(再掲)

    初めて投稿します。 技術職(機械系)の会社員です。 マイコンプログラム作成歴:約3ヶ月のほぼド素人です。 現在、会社の技術研修でPIC18F2550を使ったライントレーサの動作プログラムを作成しています。先日までPIC16F84A&88でのプログラミングを行なっており、基本は理解できているつもりです。 …が、これまで見た事のないエラーコードが出てしまい、理由がわからず困っています。 エラーコードは、[1101]lvalue required と[1105]symbol '○○○' has not been defined というもので、コンパイラのユーザーガイドを見ると、変数(GIE,LATA0等)の認識ができない?エラーのようです。ヘッダーファイルのインクルードもしており、これまでの84A&88では出なかったエラーです。 webも調べましたが、わかりませんでした。 作成環境はMPLAB V8.36、MPLAB C18コンパイラV3.33 です。 エラーメッセージ画面添付、ソースコード掲載しますので、PICプログラムに精通されている方、間違い部分をご教授頂けないでしょうか? 何卒ご協力のほどよろしくお願いします。 --【以下、コード抜粋】-- //●使用マイコン:PIC18F2550 //===《初期設定》=== //---<ヘッダーファイル>--- #include<p18f2550.h> #include"delays.h" //---<コンフィグレーション>--- #pragma config PLLDIV = 5 #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 #pragma config FOSC = HSPLL_HS #pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config PWRT = ON #pragma config BOR = OFF #pragma config BORV = 3 #pragma config VREGEN = OFF #pragma config WDT = OFF #pragma config WDTPS = 1 #pragma config MCLRE = ON #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config CCP2MX = ON #pragma config STVREN = OFF #pragma config LVP = OFF #pragma config XINST = OFF #pragma config DEBUG = OFF #pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF #pragma config CPB = OFF, CPD = OFF #pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF #pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF #pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF #pragma config EBTRB = OFF //---<関数宣言>--- void ioport(void); void interr(void); void pwm_settei(void); void move_A(void); void move_B(void); void delay_ms(long); //---<変数宣言>--- int c_flg = 0; //変数「c_flg」を宣言 //------------------------------------------------------------ //===《動作プログラム》=== //---<メイン関数>--- void main() { ioport(); interr(); pwm_settei(); while(1) { move_A(); } } //---<サブルーチン>--- void ioport(void) //[入出力ポート初期設定] { ADCON1 = 0b00001111; //A/D設定:全ポートデジタル TRISA = 0b00000000; //ポートA・I/O設定 TRISB = 0b11111111; //ポートB・I/O設定 TRISC = 0b00110000; //ポートC・I/O設定 } void interr(void) //[割り込み初期設定] { GIE = 1; //グローバル割り込み設定:許可 TMR2IE = 1; //タイマ2割り込み設定:許可 } --【途中省略】-- void move_A(void) //[動作A(直線&曲線走行モード)] { switch(PORTB) { case 0b01000000 : //センサB(内左)認識 CCPR1L = 100; //CCP1 Duty値設定 CCPR2L = 30; //CCP2 Duty値設定 LATC7 = 1; //モータR1:正転 LATA0 = 1; //モータL1:正転 LATC6 = 1; //モータR2:ON LATA1 = 1; //モータL2:ON break; --【以下続く】--

  • 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で開発してます。 説明がわかりずらいかもしれませんが上記の部分がいまいち理解できません。 この辺の事に詳しい方、教えていただけると助かります。

専門家に質問してみよう