//===================================== // File: main.c // Author: mabo-2016 // // XC8 Compiler V1.35 // RECreated on 2019/05/30, 11:17 // rebild // // PIC 16F88 // //    100Hz→→10Khz // // RB0 外部割り込み(PWM検出) // RB3 変換後PWM出力 // RB7 モニターLED表示 // =================================== //************************************ //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 // // //************************************ // CONFIG1 #pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin) #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT enabled) #pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR) #pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB3/PGM pin has PGM function, Low-Voltage Programming enabled) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Code protection off) #pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off) #pragma config CCPMX = RB3 // CCP1 Pin Selection bit (CCP1 function on RB3) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) // CONFIG2 #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor enabled) #pragma config IESO = OFF // Internal External Switchover bit (Internal External Switchover mode enabled) #include //#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 //関数のプロトタイプ宣言 void OpenPWM(char period); void SetPWM(unsigned int dutycycle); void zero_pwm(void); //変数宣言 int count; long pwmOnTimeCounter; long pwmPeriodCounter; long CONTROL_MODE_EXTERNAL_PWM_LOW; 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 SetPWM(dutyCycle); //▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲▲ //▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼▼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_REG=0b000000110;//2019-5-29変更 //OPTION=0b000000101;//プリスケラ-64 //OPTION_REG=0b000000101; //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;//割り込み全体の許可 RB6=1; while (1){ //for (i = 0; i < 201; i++){ //10000Hz時の分解能は200 出力RB3 // SetPWM(i); //PWMのDuty変更 // __delay_ms(50); //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(); 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; //TMR0IF = 0; // determine the duty cycle if (pwmPeriodCounter !=0) { // prevent divide by zero dutyCycle = pwmOnTimeCounter * MAX_PWM_DUTY / pwmPeriodCounter; } SetPWM(dutyCycle);//テストコメントアウト // reset the counters RB6=0; pwmOnTimeCounter = 0; pwmPeriodCounter = 0; INT0IF=0; } }