/***************************************************************** PC-Power-SW Control v1.0 2016/10/09 By JA3OOK T.nakamura   役割    ・IPリモコンからの出力とPCの電源SWをON/OFFしているリレーの間に入れ、     リレーへの通電時間を制限する。     従って、オペレーターがIPリモコン操作のSWをOFFにすることを忘れても自動で     通電が切れる    ・通電時間はこのプログラム内の定数で指定する。 ワッチドッグタイマーを使用 ・開始はプログラムで指定(#pragma config ではない) ブラウンアウトリセット機能を使用 ・#pragma config BOREN = ON //Brown-out Reset enable ------------------------------------------------------------------ 開発環境 MPLAB X IDE ver 3.05 MPLAB XC8 C Compiler Free mode v1.34 PIC16F88 Pin assignment Debug / Real 1:RA2:0:LCD DB6 / no-use 2:RA3:0:LCD DB7 / no-use 3:RA4:1:IPリモコンからリレー経由(ON:Hight OFF:Low) 4:MCLR/RA5:I:リセット / インサーキットプログラミング 5:VSS:GND 6:RB0:1:LED点滅(生きてる表示) 7:RB1:1:出力(ON:Hight OFF:Low) 8:RB2: 9:RB3: 18:RA1:0:LCD DB5 / no-use 17:RA0:0:LCD DB4 / no-use 16:RA7: 15:RA6: 14:VDD:DC +5V 13:RB7:0:LCD E / インサーキットプログラミング 12:RB6:0:LCD RS / インサーキットプログラミング 11:RB5: 10:RB4: ******************************************************************/ // refer \c:Program Files\Microchip\xc8\v1.31\docs\chips\16f88.html #pragma config BOREN = ON //Brown-out Reset enable #pragma config CPD = OFF //Code protection off #pragma config CCPMX =RB3 //CCP1 function on RB3 #pragma config DEBUG = OFF //In-Circuit Debugger disabled #pragma config WRT =OFF //Write protection off #pragma config FOSC = INTOSCIO //INTRC oscillator; port I/O function on both RA6/OSC2/CLKO pin and RA7/OSC1/CLKI pin //#pragma config FOSC =HS //XTAL 20MHz #pragma config MCLRE =ON //MCLR #pragma config WDTE =OFF //WDT disabled WDTはプログラムで指定して使用している #pragma config CP =OFF //Code protection off #pragma config LVP =OFF //RB3 is digital I/O, HV on MCLR must be used for programming #pragma config PWRTE =ON //Power-up Timer Enable #pragma config IESO =OFF //Internal External Switchover mode disabled #pragma config FCMEN =OFF //Fail-Safe Clock Monitor disabled // #include "pic16f88.h" //#include //#include #include #include "lcd.h" #define MHz 000000 #define _XTAL_FREQ 8MHz //PIC_OSC_FREQ #define sw1 RA4 // IPリモコンからリレー経由(ON:Hight OFF:Low) #define led_port RB0 #define out1_port RB1 //to driver for PC-POWER-SW #define t1init -62500 // タイマー1用カウントの初期値(62500カウントでオーバー) //割込間隔0.250s = (1/8000000μs*4*8*62500) // (Fosc=8MHz Prescale=8 の場合) #define interrupt_span 250 //割込み間隔 mS 前行に合わせる unsigned int debug = 0; // 1:debug mode unsigned int tm1_count; // 割込み回数(Power-SW通電時間管理)用カウント unsigned int sw1stay_time = 4; // Power-SW通電時間(割込み回数)を指定 unsigned int life_count; // 生存表示用カウント unsigned int life_span = 12; // 生存表示用LED点灯間隔(割込み回数)を指定 //3秒間隔に点滅させたい。割込み間隔が0.25秒なので、12回割り込むと3秒間隔。 unsigned int w_timer; //汎用待ち時間カウント用(符号無し16ビット長) bit onSW1; //sw1 ON の指示中(電圧継続中) bit out1_ind; //out1_portの状態を記憶 bit pass_mainloop_ind; //WDT 正常にメインループ中 bit pass_int_ind; //WDT 基本タイマー割込みが正常 void interrupt Interrupt_Service_Routine( void ){ // 割り込みサービスルーチン(ISR) if (TMR1IF) { // タイマー1の割込み発生か? //割込間隔は#define t1initで指定している TMR1IF = 0 ; // タイマー割込フラグをリセット TMR1H = (t1init >> 8); // タイマーの初期化 TMR1L = (t1init & 0x00FF) ; // タイマーの初期化 tm1_count ++; if(tm1_count > sw1stay_time){ out1_port = 0; //PC-powerSW OFF out1_ind = 0; tm1_count = 0; } //生存証明のLED点滅 life_count++ ; // 割込み発生回数をカウント if (life_count >= life_span) { // 生存証明  割込み間隔 × life_span = 点灯間隔 life_count = 0 ; led_port = 1; __delay_ms(100); //0.1s led_port = 0; } // ワッチドックタイマー pass_int_ind = 1; //WDT 基本タイマー割込みが正常に動作中 } } void Init_value(void){ out1_port = 0; //PC-power OFF out1_ind = 0; onSW1 = 0; } void Sense_voltage(void){ w_timer = interrupt_span; while(w_timer--){__delay_ms(2);}; //Wait 最低割込み間隔の倍 while(1){ //無限ループ if(pass_mainloop_ind & pass_int_ind){ pass_mainloop_ind = 0;//WDT メインループの正常チェック中 pass_int_ind = 0;//WDT 基本タイマー割込みの正常チェック CLRWDT(); //ワッチドッグタイマーをクリアー:番犬をなでてやる //CLRWDT命令はメインループの中に一箇所だけに記述すること。 //割込み処理内とかfunctionの中に記述すると効果が半減する。 } if(sw1){ //リモートで SW ON の指示 if(!onSW1){ // ON指示受け直後 または ON指示継続中でない=電圧継続中でない out1_port = 1; //PC-powerSW ON out1_ind = 1; tm1_count = 0; onSW1 = 1; } } else { //リモートで SW OFF の指示 onSW1 = 0; __delay_ms(30); //Wait チャタリング防止 } led_port = out1_ind; //out1_portと同期してLEDを点ける pass_mainloop_ind = 1; //WDT 正常にループしている } } void main(void){ SWDTEN = 0 ; // WDT許可しない OSCCON = 0x70; //internal OSC 8Mz ANSEL = 0b00000000; //すべてデジタル) TRISA = 0b00110000; //MCLR:input only RA4:input others are output PORTA = 0b00100000; //初期化(MVLRは外部pullupしているのでHigh、他はLow) TRISB = 0b00000000; //RB1,0: OUTPUT PORTB = 0b00000000; //All Low WDTPS3 = 0; //WDT(ウォッチドッグ(番犬)タイマ) プリスケーラ WDTPS2 = 1; //WDT プリスケーラ WDTPS1 = 1; //WDT プリスケーラ WDTPS0 = 1; //WDT プリスケーラ 従ってレートは4096倍。元が0.032ms なので 131msec OPTION_REG = 0b10001110; //PORTB pins has not a weak internal pull-up. //PSA = 1; //WDT ポストスケーラー を使用 //PS2 = 1; PS1 = 1; PS0 = 0;//そのレートは64倍 × プリスケーラー = 8sec //割込間隔0.250sec = (1/8000000μs*4*8*62500) を指定 // (Fosc=8MHz Prescale=8) T1CON = 0b00110001; // 内部クロックでTIMER1を使用、プリスケーラカウント値 1:8 TMR1H = (t1init >> 8); // タイマーの初期化 TMR1L = (t1init & 0x00FF) ; // タイマーの初期化 TMR1IF = 0 ; // タイマー0割込フラグを0 //LCD initialize and cleare Lcd_init(); Lcd_clear(); /* display open message */ Lcd_write(0b00001100); //Display on, no cursor Lcd_goto(0x00); //LCDの表示位置を一行目左端 Lcd_puts("PowerSW Control");//LCDにメッセージを表示 Lcd_goto(0x40); //LCDの表示位置を二行目左端 Lcd_puts("v1.0 ");//LCDにメッセージを表示 if (debug) {Lcd_puts("DEBG ");}else {Lcd_puts(" ");} Lcd_puts("JA3OOK");//LCDにメッセージを表示 if (debug){ w_timer = 3; while(w_timer--){__delay_ms(1000);}; //Wait 3Sec } // End of hello msg on LCD Init_value(); //APデータ初期化 Lcd_goto(0x4A); Lcd_puts(" Ready"); //LCDにメッセージを表示 led_port=1; w_timer=1; while(w_timer--){__delay_ms(1000);}; //Wait 1sec. led_port=0; //End of ceremony pass_mainloop_ind = 0; //WDT メインループチェック pass_int_ind= 0; //WDT タイマー割込みとカウント動作チェック TMR1IE = 1 ; // タイマー1割込をマスクしない PEIE = 1 ; // 周辺割込みをマスクしない SWDTEN = 1 ; // WDTをマスクしない GIE = 1 ; // 全割込み処理をマスクしない Sense_voltage(); }