研究発表などでは、進行時間を通知するため独自のルールがあります。
一人発表の場合時間は8分とする
終了2分前に予鈴を鳴らす
質問は5分
この時間を知らせるため、タイムキーパーが必要になりますが。ここでは、タイムキーパーの処理を行うタイマーを制作します。
人手で行うなう場合、ストップウオッチ(時計)とベルを利用します。ここでは、時計はPIC内部のターマーを利用します。まだ、ベルの替わりにスピーカを利用します。
開始時に、スタートボタンを押します。これで、計時を開始します。計時は発表時間を減らします。残り2分で、スピーカに信号を送ります。
スタートボタンはext割り込みを利用します。実行中でもスタートボタンが有効になります。計時にはタイマー0割り込みを利用します。ブザー音にはタイマー割り込み1を利用します。
ポートBの1〜7を7素子数字素子C535のa〜gに接続します。ポートAの0〜2で、7素子の各桁をドライブします。ポートAの第3ビット(PA3)にはソフトウエアでブザー音を発振し、これをブザーに接続します。
ポートBの0端子には押しボタンスイッチを接続し、外部割込みとして利用します。タイマーのスタートや進行に利用し、最初の押し下げで、発表モードに入ります。発表時間中に押し下げた場合は質問モードに移行します。
発表者の人数(一人/二人)で、発表時間が異なります。この切り替えは、PA3に接続された切り替えスイッチを利用します。他に。発信用セラミック振動子(20MHz、osc端子)、CLR端子(5Vに接続)、への接続が必要です。
電源は、1.5Vの乾電池2本を利用します。仕様では、3vで、20MHzのクロックは保証外ですが、テストでは動作しました。クロックを4MHzに下げる方が安全です。その場合、タイマーの設定値を1/5に下げる必要があります。
プログラムでは3種の割り込みを利用します。一つは、PB0端子からのスイッチによる外部割込みで、開始や終了など次のフェーズに進むための信号として利用します。
外部割込み#int_ext は、押しボタンスイッチの押し下げで発生します。発表モード(prs==1)での押し下げは、質問モードに移行します。質問モードで押し下げた場合、発表モードに移行します。
タイマー0の割り込みは、時間進行を行います。タイマー0は 10mS で割り込みます。時刻は3桁の分単位で表示します。031 は3.2分の意味で、これは、3分12秒に相当します(0.1分は6秒単位)。発表モードでは残り時間を減算表示し、質問モードでは増加計数をします。
タイマー1の割り込みは、ブザー音の生成に利用します。prd で周期を設定し、PIN_A3 を反転します。ブザー音は、発表残り2分で1回、発表終了で2回、質問5分経過で3回鳴ります。音の高さも変更しています。
#include <16f88.h> #include <stdlib.h> #fuses HS,NOWDT,NOLVP//内部クロック、WDT,LVPなし #use delay(CLOCK=20000000) //クロック4MHz #use fast_io(B) //PB7..PB1に7素子のg..aを接続 //PA2,PA1,PA0に7素子の桁信号を接続 //PA3:スピーカ //PB0:スタートスイッチ //PA4:人数設定スイッチ //int ct;//数字の更新間隔 long val;//表示する数字 int digit;//表示する桁 //7素子表示パターン int segment_data[]={0x7E,0x0C,0xB6,0x9E,0xCC,0xDA,0xFA,0xE,0xFE,0xCE}; char st[3]; int prs; long cnt0=600; int buz,flag,buzcnt,seq; int pt=80; long prd; long tunit=600; #int_ext void extisr(){ //押しボタン処理 val=0; prs=1; if (input_a() & 0x10){ val=80; } else { val=150; } //val=80; //開始の音 prd=64500; buzcnt=0; enable_interrupts(INT_TIMER1); buz=1; seq=0; //output_bit(PIN_C0,0); } #int_rtcc //タイマ0割込み void rtcc_isr() { //時間処理 if(cnt0 == 0){ if(val==0) prs=0;//発表/質問切り替え if(prs) val--; else val++; if(prs && val==20){//予鈴 prd=64500;//ブザー音開始 set_timer1(prd); enable_interrupts(INT_TIMER1); buz=1; buzcnt=0; } if( val==0){//発表終了 prd=65000;//ブザー音開始 set_timer1(prd); enable_interrupts(INT_TIMER1); buz=1; buzcnt=1;//続けて1回ならす } if( !prs && (val==50)){//質問終了 prd=65200;//ブザー音開始 set_timer1(prd); enable_interrupts(INT_TIMER1); buz=1; buzcnt=2;//続けて2回ならす } if(val==1000) val=0; st[2]=val/100; st[1]=val/10-st[2]*10; st[0]=val%10; } cnt0++; if(cnt0==tunit) cnt0=0; //ブザーを止める if(cnt0 % 100 ==0 ){ if(buz) { buz =0; if(buzcnt>0) seq=1; disable_interrupts(INT_TIMER1); buzcnt--; } if(seq==2 ){//ブザー再開 set_timer1(prd); enable_interrupts(INT_TIMER1); buz=1; seq=0; output_bit(PIN_C0,1); } if(seq==1) seq=2; } set_timer0(60);//10mS } #int_timer1 void timer1_isr() {//ブザー音の生成 output_bit(PIN_A3,flag); if (flag==1) flag=0; else flag=1; set_timer1(prd); } void main(){ set_tris_b(0b00000001);//Bポート下位4bit出力 //set_tris_a(0b11111100); digit=0; cnt0=0; buz=0; prs=1; buzcnt=0; val=80;//表示する値 set_timer0(60); output_bit(PIN_C0,0); setup_counters(RTCC_INTERNAL,RTCC_DIV_256); setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); enable_interrupts(INT_EXT); enable_interrupts(INT_TIMER0); enable_interrupts(GLOBAL); while(1){ if(digit== 2){//第3桁の表示 output_b( segment_data[st[2]]); output_bit(PIN_A2,1);//3桁表示開始 delay_ms (5); //表示期間(ミリ秒) output_bit(PIN_A2,0);//表示を消す delay_us(100); } if(digit== 1){ output_b( segment_data[st[1]]); output_bit(PIN_A1,1); delay_ms (5); output_bit(PIN_A1,0); delay_us(100); } if(digit == 0){ output_b( segment_data[st[0]]); output_bit(PIN_A0,1); delay_ms (5); output_bit(PIN_A0,0); delay_us(100); } digit ++;//表示桁を変更 if(digit ==3 ) digit=0; } }