- 締切済み
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);
- yf491224
- お礼率65% (58/88)
- その他(プログラミング・開発)
- 回答数1
- ありがとう数1
- みんなの回答 (1)
- 専門家の回答
みんなの回答
- monova
- ベストアンサー率68% (68/100)
PICは実際に使った事が無いので感で回答します。 まず、オシロスコープがあれば、4pin をモニタすると 原因をつかみやすいのかもしれません。 この様な場合に考えられる原因は 1.4pin が"H"レベルになっていない。 2.4pin は"H"レベルになっているが、時間が短すぎてLEDをドライブできない。 もしくは、ドライブ時間が短すぎて人間の目では確認できない。 3.4pin のドライブ能力が不足している。 4.5pin がスイッチの動作を検知できていない。 と、いった感じでしょうか? この辺の切り分けが出来れば解決しやすいと思います。 このプログラムは、スイッチに寄る立ち上がりを検知したら 4pinを "H" にホールドしたままプログラムを終了する事を 意図している…って、事で良いのでしょうか?
関連するQ&A
- 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; }
- ベストアンサー
- その他(趣味・娯楽・エンターテイメント)
- 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); }
- 締切済み
- その他([技術者向] コンピューター)
- PIC18F1320でwarningがでる
PIC18F1320で MPLAB X IDE v3.26 XC 8です warningがでる warningがでてもプログラムは動く warningがでなくしたい LCD液晶表示装置を使うので8ビット符号なし整数型がいい 0から255の8ビット符号なし整数型しか使わない キャラクターコードをLATB(PORTB)に送るため プログラムで-1や256になったりしないよう制御してある #include <xc.h> CONFIG 省略 ほとんど省略 // EQU unsigned char TMRA=1; unsigned char TMRB=1;//など void main(void) { TMRA = TMRA - 20; TMRB = TMR+1;//など } newmain.c: warning: (xxx) conversion to shorter data type よろしくお願いします。
- ベストアンサー
- その他(プログラミング・開発)
- 表示パターンを作りたいです。
7セグメント表示(1A~G・2A~G)とその他のマーク(T1・T2)を表示する液晶の表示パターンを作りたいのですが、ポートのアドレス内のビット配置が 1A・1B・1C・1D・T1・1E・1F・1G とセグメントとその他のマークが混在していたり、 2A・2B・2C・2D・ー・ー・ー・ー ー・ー・ー・ー・T2・2E・2F・2G と、さらに2つのアドレスにまたがって配置されていたりします。 各アドレスとポートはヘッダで union tag_IOPORT { unsigned char byPORT; struct { unsigned char B7:1; unsigned char B6:1; unsigned char B5:1; unsigned char B4:1; unsigned char B3:1; unsigned char B2:1; unsigned char B1:1; unsigned char B0:1; } BIT; }; #define IOPORT1_addr (*(volatile union tag_IOPORT *)0xffff) #define port1 IOPORT1_addr.byPORT #define 1A IOPORT1_addr.BIT.B7 #define 1B IOPORT1_addr.BIT.B6 #define 1C IOPORT1_addr.BIT.B5 #define 1D IOPORT1_addr.BIT.B4 #define T1 IOPORT1_addr.BIT.B3 #define 1E IOPORT1_addr.BIT.B2 #define 1F IOPORT1_addr.BIT.B1 #define 1G IOPORT1_addr.BIT.B0 という感じで#defineで宣言してあって、バイト単位でもビット単位でも操作出来るようにしてあります。 そこで、セグメントとマークを ・セグメント1 ・セグメント2 ・マーク などのそれぞれのグループごとにまとめて操作する方法はないでしょうか? イメージとしては disp_T[4][2]={{0,0},{0,1},{1,0},{1,1}} というような表示パターンの配列を作って代入すればマークの表示が出来るような感じにしたいのですが、代入する先を作れば良いかわかりません。 イメージ通りに作る事は可能なのか、どう作れば良いのか、他に良い方法など教えてください。 わかりにくい文章かもしれませんがお願いします。
- 締切済み
- C・C++・C#
- 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; } } となります。 大変恐縮ですが、原因が判る方がいらっしゃいましたら、ご教示のほどよろしくお願い致します。
- 締切済み
- C・C++・C#
- PIC16F88に書き込んだプログラムについて
以前、直流電圧と電流を測定する回路を製作し、その時書いたプログラムでは正常にLCDに表示されていたのですが、最近になって測定した電圧および電流を1秒間に8回更新するように書き替えました。しかしLCDに正常に表示されなくなりました。 プログラムと回路図を掲載しますのでどなたか、どうすればいいか教えてください。 よろしくお願い致します。 ////////////////////以下プログラム/////////////////////////////////////////////////// <lcd.c> #include <pic.h> //#include "lcd.h" //#include "delay.h" #define _XTAL_FREQ 4000000 #define LCD_RS RA0 #define LCD_RW RA7 #define LCD_EN RA6 #define LCD_DATA PORTB #define LCD_STROBE() ((LCD_EN = 1),(LCD_EN=0)) /* write a byte to the LCD in 4 bit mode */ void lcd_write(unsigned char c) { //DelayUs(40); __delay_us(40); LCD_DATA = ( ( c >> 4 ) & 0x0F ); LCD_STROBE(); LCD_DATA = ( c & 0x0F ); LCD_STROBE(); } /* * Clear and home the LCD */ void lcd_clear(void) { LCD_RS = 0; lcd_write(0x1); //DelayMs(2); __delay_ms(2); } /* write a string of chars to the LCD */ void lcd_puts(const char * s) { LCD_RS = 1; // write characters while(*s) lcd_write(*s++); } /* write one character to the LCD */ void lcd_putch(char c) { LCD_RS = 1; // write characters lcd_write( c ); } /* * Go to the specified position */ void lcd_goto(unsigned char pos) { LCD_RS = 0; lcd_write(0x80+pos); } /* initialise the LCD - put into 4 bit mode */ void lcd_init() { char init_value; //ADCON1 = 0x06; // Disable analog pins on PORTA init_value = 0x3; //TRISA=0; //TRISB=0; LCD_RS = 0; LCD_EN = 0; LCD_RW = 0; //DelayMs(15); // wait 15mSec after power applied, __delay_ms(15); LCD_DATA = init_value; LCD_STROBE(); //DelayMs(5); __delay_ms(5); LCD_STROBE(); //DelayUs(200); __delay_us(200); LCD_STROBE(); //DelayUs(200); __delay_us(200); LCD_DATA = 2; // Four bit mode LCD_STROBE(); lcd_write(0x28); // Set interface length //lcd_write(0xF); // Display On, Cursor On, Cursor Blink lcd_write(0x0C); lcd_clear(); // Clear screen //lcd_write(0x6); // Set entry Mode lcd_write(0x07); } <main.c> #include <pic.h> #include <stdlib.h> #include "lcd.h" #define _LEGACY_HEADERS #define _XTAL_FREQ 4000000 __CONFIG(FOSC_INTOSCIO & WDTE_OFF & PWRTE_ON & MCLRE_OFF & BOREN_OFF & LVP_OFF & CPD_OFF & WRT_OFF & CCPMX_RB0 & CP_OFF); __CONFIG(FCMEN_OFF & IESO_OFF); unsigned int ADConv(unsigned char ch) { ADCON0=(ch<<3)&0x38; ADCS2=0; ADCS1=0; ADCS0=1; ADON=1; ADIF=0; __delay_us(20); GO_DONE=1; while(GO_DONE); return (ADRESH<<8) | ADRESL; } unsigned short Code2mV(unsigned char ch) { unsigned short ret; ret=0; ret += ADConv(ch)<<1; ret += ADConv(ch)>>1; ret += ADConv(ch)>>3; ret += ADConv(ch)>>4; ret += ADConv(ch)>>5; return ret; } void ioport(void) { CMCON=0x07; ANSEL= 0b00001110; TRISA = 0b00001110; PORTA=0x00; TRISB = 0b00000000; PORTB=0x00; } void main(void) { static double data, offset; static unsigned int v ,i,n1,n0; static unsigned char buf[8], cnt,tmp1[2],tmp2[2]; OSCCON = 0b01100000; // �N���b�N��8Mhz ioport(); ADCON1=0b11100000; lcd_init(); lcd_write(0x0D); lcd_goto(0); lcd_puts("Starting"); lcd_goto(0x40); lcd_puts("DC Meter"); __delay_ms(2500); lcd_clear(); offset=0.0; while (1) { data=0.0; for(cnt=0; cnt<10; cnt++) { data += Code2mV(1); } data /= 10.0; data *= 2.4287109375; data *= 11.0; data -= offset; v=(unsigned int)(data); n1=(unsigned int)(v/1000); n0=v-1000*n1; itoa(tmp2,n1,10); itoa(tmp1,n0,10); lcd_goto(1); lcd_puts(tmp2); lcd_goto(3); lcd_putch('.'); lcd_puts(tmp1); lcd_goto(6); lcd_puts("V"); data =0.0; for(cnt=0; cnt<10; cnt++) { data += Code2mV(2); } data /= 10.0; data *= 2.4287109375; data /= 11.0; offset = data; i=(unsigned int)(10.0 * data); itoa(buf,i,10); lcd_goto(9); lcd_puts(buf); lcd_goto(13); lcd_puts("mA"); __delay_ms(125); } }
- ベストアンサー
- C・C++・C#
- 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); } ----------------------------------------
- 締切済み
- その他([技術者向] コンピューター)
- PIC16F84内部動作スピードについて
マイコンを始めて触る 超超初心者 です。 PIC16F84を使用してHS Modeで10MHzで動作をさせています。 内部での動作する周期は10MHzで動作するものでしょうか? whileループでソフトカウンタを作成し8bitカウンタのLSBをオシロスコープでみ たところ1カウントアップするのに500KHzでした。 何かレジスタで設定すると10MHz外部オシレータと同スピードで動作するのでしょ うか? 下が今回使用したソースです。 どうぞ宜しくお願いします。 #include <pic.h> __CONFIG(0x3FFE); unsigned char count; void ioport(void); main() { ioport(); } void ioport(void) { TRISA=0b11111; TRISB=0b00000000; count=0b0; while(1){ PORTB=count; count++; } }
- 締切済み
- その他(プログラミング・開発)
- 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 タイマー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; } } }
- ベストアンサー
- 電気・電子工学
お礼
ありがとうございます。 いろいろ条件変えて調べてみます。 また、よろしくお願いいたします。
補足
あれから、よく配線を調べてみたらスイッチの接続箇所が間違えていました。 接続箇所を変えて動かしたところ、ちゃんと動きました。 お騒がせいたしました。