//************************************ //16F88 HI-TECH C v.9.83 //PWMの基本周波数変換プログラム //HI-TECH C Compiler for PIC10/12/16 MCUs (Lite Mode) V9.83 //PWM関数仕様 // //100Hz_TO_10000Hz // // //************************************ #define _LEGACY_HEADERS #include "pic.h" #include "stdlib.h" #include "lcd.h" #define _XTAL_FREQ 8000000 #define MAX_PWM_DUTY 200 #define MAX_ADV_VALUE 255 #define CONTROL_MODE_OFF 0 #define CONTROL_MODE_POT 1 #define CONTROL_MODE_EXTERNAL_PWM 2 #define CONTROL_MODE_SW_PIN RB7 #define EXTERNAL_INTERRUPT_PIN RB0 #define FALSE 0 #define TRUE 1 __CONFIG(CCPRB3 & DEBUGDIS & LVPDIS & BOREN & MCLRDIS & PWRTEN & WDTDIS & INTIO); //関数のプロトタイプ宣言 void OpenPWM(char period); void SetPWM(unsigned int dutycycle); void zero_pwm(void); //変数宣言 int count; long pwmOnTimeCounter; long pwmPeriodCounter; unsigned int dutyCycle; unsigned char bGotPwmPulse; //unsigned int32 pwmOnTimeCounter; //unsigned int32 pwmPeriodCounter; //unsigned int8 dutyCycle; //short bGotPwmPulse; //int8 controlMode; void main(void){ //PICの初期化 OSCCON = 0b01110000; //内蔵発振器 8MHz使用に設定 ANSEL = 0b00000000;// すべてデジタル TRISA = 0b00000000;// すべて出力 TRISB = 0b00000001;// すべて出力(RB0はINT入力 PORTA = 0b00000000;// すべてlow PORTB = 0b00000000;// すべてlow bGotPwmPulse=FALSE;//定数初期化 dutyCycle = 0;//定数初期化 //▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼10,000HzのPWM信号を発信▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ //周期 = 10,000Hz = 1/10,000 = 100μs //(PR2の範囲は0〜255) //Timer2のプリスケール 4 //周期 = (PR2 + 1) * 4 * Tosc * (Timer2のプリスケール値)であるから //PR2 = (周期 / (4 * Tosc * (Timer2のプリスケール値)) - 1 //PR2 = (100 / (4 * 0.125 * 4)) - 1 //PR2 = 49 // //PWM分解能 DC1(Max)は //duty = DC1 * Tosc * (Timer2のプリスケール値)であるから //DC1 = duty / (Tosc * (Timer2のプリスケール値)) //DC1(Max) = 100 / (0.125 * 4) //DC1(Max) = 200 //▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ //▼▼▼▼▼▼▼▼▼▼▼▼▼▼TIMER2とPWMの設定▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ //Timer2のプリスケール値設定 //T2CON |= 0b00000001; //プリスケール 4 //T2CON = 0b00000001; //PWMの初期化と起動 OpenPWM(49); //引数は0-255 PWM 10,000Hz //▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ //▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼Timer0設定▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ //クロック8MHz→1クロック0.125μs→1命令サイクル0.5μs //割り込み周期 0.5*256*プリスケラ-----0.128ms*プリスケラ- //8ms/0.128*64----8ms //PS2-PS0・・・・・・・・・プリスケラ // 000-2 // 001-4 // 010-8 // 011-16 // 100-32 // 101-64 // 110-128 // 111-256 TMR0=0; OPTION=0b000000101;//プリスケラ-64 //T0CS=0;(5ビット)内部クロック・・0 外部クロック・・1 //PSA =0;(3ビット)タイマー・・0 WDT・・1 //PS2 =0;(2ビット) //PS1 =0;(1ビット) 0.0.0でプリスケラ-2 //PS0 =0;(0ビット) //▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ //▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼Timer1設定▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ T1CON = 0b00110000; //T1RUN = 0; system clock status (SystemClock) //T1CKPS = 11B; プリスケール 8 //T1OSCEN = 0; oscillator enable (Enable) //T1SYNC = 0 外部クロック同期(OFF) //TMR1CS = 0; クロックソース(内部クロック) //TMR1ON = 1; カウント開始 TMR1H = 0;// カウンタクリア TMR1L = 0; TMR1ON = 1; //▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ //▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼割り込み許可▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼ TMR0IE = 1;//タイマー0割り込み発生許可 TMR1IE = 1;//タイマー1割り込み発生許可 TMR2IE = 1;//タイマー2割り込み発生許可 INT0IE = 1;// 外部割込みの許可 INTEDG = 1;// 立ち下がりで割り込み PEIE=1;//拡張割り込み許可−−TIMET1に必要 //▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ TMR0IF = 0;//タイマー0割り込みフラグクリア TMR1IF = 0;//タイマー1割り込みフラグクリア TMR2IF = 0;//タイマー2割り込みフラグクリア INT0IF = 0;// 外部割込みフラグをクリア GIE= 1;//割り込み全体の許可 int i; while (1){ //for (i = 0; i < 201; i++){ //10000Hz時の分解能は200 出力RB3 // SetPWM(200- i); //PWMのDuty変更 // __delay_ms(100); //0.02秒(=20ミリ秒)待つ //} } } void OpenPWM(char period){ //http://kuri6005.sakura.ne.jp/pic/index.php?cmd=read&page=LED%A4%CE%CC%C0%A4%EB%A4%B5%A4%F2%CA%D1%A4%A8%A4%EB%28PWM%29%2816F886%29&word=HI-TEC CCP1CON |= 0b00001100; //PWMモードにする PR2 = period; T2CON |= 0b00000101; //Timer2 Enable プリスケラ-4 } void SetPWM(unsigned int dutycycle){ //解像度10ビットのうち上位8ビットをCCPR1Lレジスタに格納 CCPR1L = dutycycle >> 2; //解像度10ビットのうち下位2ビットをCCP1CONレジスタの4,5ビットへ格納 CCP1CON |= (dutycycle & 0x0003) << 4; } void zero_pwm(void){ pwmOnTimeCounter = 0; pwmPeriodCounter = 0; dutyCycle = 0; SetPWM(dutyCycle); } static void interrupt warikomi(void) {//割り込み処理 //***********TIMER0割り込み処理**************** if(TMR0IF==1){ if (bGotPwmPulse==FALSE){ zero_pwm(); SetPWM(0); RB6=1; } bGotPwmPulse = FALSE; //TMR0=0; TMR0IF = 0; } //***********TIMER1割り込み処理**************** if(TMR1IF==1){//LCD・LED表示 //RB7=!RB7; TMR1H = 0;// カウンタクリア TMR1L = 0; TMR1IF = 0; } //***********TIMER2割り込み処理**************** if(TMR2IF==1){//100usでサンプリング if (EXTERNAL_INTERRUPT_PIN==1){ pwmOnTimeCounter++; } pwmPeriodCounter++; TMR2IF = 0; } //***********外部割り込み処理**************** if(INT0IF==1){ bGotPwmPulse = TRUE; TMR0=0; // determine the duty cycle if (pwmPeriodCounter !=0) { // prevent divide by zero dutyCycle = pwmOnTimeCounter * MAX_PWM_DUTY / pwmPeriodCounter; } SetPWM(dutyCycle); // reset the counters pwmOnTimeCounter = 0; pwmPeriodCounter = 0; INT0IF=0; } }