まずはPICについてこれまでのおさらいです。
なぜPICマイコンなのか?ですが・・ 透析装置のモーターを利用してミニ人工心肺をつくるが位相制御だけではスピードコントロールに限界を感じる ↓ PICマイコンをはじめてみる PICの奥深さに感銘と無限大の可能性を感じる ↓ PICマイコンの練習 いけそうな気がしてくる ↓ MPLABXでプログラミング前編 ・ 後編 で皆んなにPICの素晴らしさを知って欲しいと思ってみる ↓ PIC16F88のCCP機能でサーボモータを動かす事に成功 (2015/01) この後PICの世界から一時離れる。 まぁこういった具合にすすんできました。 あとPID制御要はフィードバック制御をできるようになるには ①割り込みを覚えること➡️今回やる事!! ②LCDパネルを扱えるようになること ③アナログデジタル変換ができるようになる です。 んで、今回は割り込みをやってみます。 先に結論から言うとPICで割り込みするのは結構簡単でした。 こちらが実際の動いているところです。CCP同様に滑らかに動いていますが、なんかギギギッとかいう音が気になるります。 CCP機能でPWMモードを使ったほうが無難かもしれませんね。 でも割り込みという機能の習得には大いに役立ちました。割り込みの概念
今回も内部クロックで動いてくれるPIC16F88を使用しました。 実は定番マイコンのPIC16F84Aでも割り込みのプログラムは同様です。
PIC16F88の割り込みの設定
まずはOPTION_REGの設定です。

INTOCONレススタの設定

TMR0レジスタ
8ビットのカウンタで、1命令サイクル毎に+1されます。 プルスケーラーが設定されていればその比率でカウントが伸びます。 最初に設定した値からカウントアップが始まり最大値の255から0に戻る時にTMR0割り込みが発生します。 たとえばTMR0に100がセットされていると (255-100+1)×(プリスケーラーの値)でTMR0割り込みが発生するのです。 内部クロックを8M㎐で駆動させていれば1サイクル0.5μsecなので プリスケーラを256倍とすれば、 156×256×0.5μsec=19968μsec 約20msecとなります。回路図

プログラム
// PIC16F88 Configuration Bit Settings // ‘C’ source line config statements #include <xc.h> // #pragma config statements should precede project file includes. // Use project enums instead of #define for ON and OFF. // CONFIG1 #pragma config FOSC = INTOSCIO //内部クロックをつかいますよー #pragma config WDTE = OFF // #pragma config PWRTE = OFF // #pragma config MCLRE = OFF // #pragma config BOREN = OFF // #pragma config LVP = OFF // #pragma config CPD = OFF // #pragma config WRT = OFF // #pragma config CCPMX = RB3 // #pragma config CP = OFF // // CONFIG2 #pragma config FCMEN = OFF // #pragma config IESO = OFF // //////////delay関数を使うために発振周波数を定義 8Mhz//////////// #define _XTAL_FREQ 8000000 void arg_delay(unsigned int x); //グローバル変数の定義 unsigned int angle; //サーボの振れ角度 //割り込みが入った時のプログラムです。 void interrupt myIsr(void) { if (INTCONbits.TMR0IE && INTCONbits.TMR0IF) { PORTAbits.RA0 = 1; //パルスON arg_delay(100 + angle);//angleは0-230の値で可変させるとうまくいきました。 //TMR0IEとTMR0IFが両方とも1ならRA0を1にします //パルスON時間はangleを変更して決定して継続させますよ。 PORTAbits.RA0 = 0; //パルスOFFさせます INTCONbits.TMR0IF = 0; //次の割り込みの為にTMR0IFをクリアしておきます } } //ここからがメインで設定 void main(void) { OSCCON = 0b01110000;//内部周波数8Mhzにします OPTION_REG = 0b00000111; //プリスケーラを256に設定 INTCONbits.TMR0IE = 1; //割り込みを許可 INTCONbits.GIE = 1;//全体の割り込みを許可 INTCONbits.TMR0IF=0;//TMR0IF最初にクリアしときます。 TMR0 = 100; //256-100= 156*256*0.5us=19968us ほぼ20msec ANSEL = 0b00000000;//すべてデジタルに設定しときますよ TRISA = 0b00000000;//portAはすべて出力に設定 TRISB=0b00000000;//portBはすへて出力に設定 PORTA = 0;//きれいにクリアしときます。 PORTB=0;//きれいにクリアしときます。 //メインの処理 PORTAbits.RA1 = 1; //RA2:パワーオンを示すLED点灯 angle = 115; //サーボの触れ角を0度に __delay_ms(2000); while (1) { //基準角度確認 angle = 115; //パルス幅 __delay_ms(1000); angle = 230; //パルス幅 __delay_ms(1000); angle = 115; //パルス幅 __delay_ms(1000); angle = 0; //パルス幅 __delay_ms(1000); } return; } //待ち時間が変数設定できるarg_delay()関数を定義 //_delay()は引数に変数設定が出来ない為) void arg_delay(unsigned int x) { while (x) { __delay_us(1); x–; } } |
スポンサードリンク